mirror of
https://github.com/containerd/containerd.git
synced 2026-08-09 17:39:22 +00:00
See __fsverity_file_open():
``` c
int __fsverity_file_open(struct inode *inode, struct file *filp)
{
if (filp->f_mode & FMODE_WRITE)
return -EPERM;
return ensure_verity_info(inode);
}
```
Fixes: 5b9d871fea ("Add EROFS mount handler plugin")
Closes: https://github.com/containerd/containerd/issues/12451
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
137 lines
3.2 KiB
Go
137 lines
3.2 KiB
Go
/*
|
|
Copyright The containerd Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package erofs
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/containerd/platforms"
|
|
"github.com/containerd/plugin"
|
|
"github.com/containerd/plugin/registry"
|
|
|
|
"github.com/containerd/containerd/v2/core/mount"
|
|
"github.com/containerd/containerd/v2/plugins"
|
|
"github.com/containerd/errdefs"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
var forceloop bool
|
|
|
|
type erofsMountHandler struct {
|
|
}
|
|
|
|
func newErofsMountHandler() mount.Handler {
|
|
return erofsMountHandler{}
|
|
}
|
|
|
|
func (erofsMountHandler) Mount(ctx context.Context, m mount.Mount, mp string, _ []mount.ActiveMount) (mount.ActiveMount, error) {
|
|
if m.Type != "erofs" {
|
|
return mount.ActiveMount{}, errdefs.ErrNotImplemented
|
|
}
|
|
|
|
// Ignore the loop option which is specified if the dedicated mount handler is available
|
|
for i, v := range m.Options {
|
|
if v == "loop" {
|
|
m.Options = append(m.Options[:i], m.Options[i+1:]...)
|
|
break
|
|
}
|
|
}
|
|
|
|
if err := os.MkdirAll(mp, 0700); err != nil {
|
|
return mount.ActiveMount{}, err
|
|
}
|
|
|
|
var err error = unix.ENOTBLK
|
|
if !forceloop {
|
|
// Try to use file-backed mount feature if available (Linux 6.12+) first
|
|
err = m.Mount(mp)
|
|
}
|
|
if errors.Is(err, unix.ENOTBLK) {
|
|
var loops []*os.File
|
|
|
|
// Never try to mount with raw files anymore if tried
|
|
forceloop = true
|
|
params := mount.LoopParams{
|
|
Readonly: true,
|
|
Autoclear: true,
|
|
}
|
|
// set up all loop devices
|
|
loop, err := mount.SetupLoop(m.Source, params)
|
|
if err != nil {
|
|
return mount.ActiveMount{}, err
|
|
}
|
|
m.Source = loop.Name()
|
|
loops = append(loops, loop)
|
|
defer func() {
|
|
for _, loop := range loops {
|
|
loop.Close()
|
|
}
|
|
}()
|
|
|
|
for i, v := range m.Options {
|
|
// Convert raw files in `device=` into loop devices too
|
|
if strings.HasPrefix(v, "device=") {
|
|
loop, err := mount.SetupLoop(strings.TrimPrefix(v, "device="), params)
|
|
if err != nil {
|
|
return mount.ActiveMount{}, err
|
|
}
|
|
m.Options[i] = "device=" + loop.Name()
|
|
}
|
|
}
|
|
err = m.Mount(mp)
|
|
if err != nil {
|
|
return mount.ActiveMount{}, err
|
|
}
|
|
} else if err != nil {
|
|
return mount.ActiveMount{}, err
|
|
}
|
|
|
|
t := time.Now()
|
|
return mount.ActiveMount{
|
|
Mount: m,
|
|
MountedAt: &t,
|
|
MountPoint: mp,
|
|
}, nil
|
|
}
|
|
|
|
func (erofsMountHandler) Unmount(ctx context.Context, path string) error {
|
|
return mount.Unmount(path, 0)
|
|
}
|
|
|
|
type Config struct{}
|
|
|
|
func init() {
|
|
registry.Register(&plugin.Registration{
|
|
Type: plugins.MountHandlerPlugin,
|
|
ID: "erofs",
|
|
Config: &Config{},
|
|
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
|
|
p := platforms.DefaultSpec()
|
|
p.OS = runtime.GOOS
|
|
ic.Meta.Platforms = append(ic.Meta.Platforms, p)
|
|
|
|
return newErofsMountHandler(), nil
|
|
},
|
|
})
|
|
}
|