diff options
-rw-r--r-- | runsc/cmd/gofer.go | 8 | ||||
-rw-r--r-- | runsc/config/config.go | 3 | ||||
-rw-r--r-- | runsc/config/flags.go | 1 | ||||
-rw-r--r-- | runsc/fsgofer/fsgofer.go | 21 | ||||
-rw-r--r-- | runsc/fsgofer/fsgofer_test.go | 32 |
5 files changed, 58 insertions, 7 deletions
diff --git a/runsc/cmd/gofer.go b/runsc/cmd/gofer.go index 444153674..639b2219c 100644 --- a/runsc/cmd/gofer.go +++ b/runsc/cmd/gofer.go @@ -165,7 +165,8 @@ func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) // Start with root mount, then add any other additional mount as needed. ats := make([]p9.Attacher, 0, len(spec.Mounts)+1) ap, err := fsgofer.NewAttachPoint("/", fsgofer.Config{ - ROMount: spec.Root.Readonly || conf.Overlay, + ROMount: spec.Root.Readonly || conf.Overlay, + EnableXattr: conf.Verity, }) if err != nil { Fatalf("creating attach point: %v", err) @@ -177,8 +178,9 @@ func (g *Gofer) Execute(_ context.Context, f *flag.FlagSet, args ...interface{}) for _, m := range spec.Mounts { if specutils.Is9PMount(m) { cfg := fsgofer.Config{ - ROMount: isReadonlyMount(m.Options) || conf.Overlay, - HostUDS: conf.FSGoferHostUDS, + ROMount: isReadonlyMount(m.Options) || conf.Overlay, + HostUDS: conf.FSGoferHostUDS, + EnableXattr: conf.Verity, } ap, err := fsgofer.NewAttachPoint(m.Destination, cfg) if err != nil { diff --git a/runsc/config/config.go b/runsc/config/config.go index e9fd7708f..34ef48825 100644 --- a/runsc/config/config.go +++ b/runsc/config/config.go @@ -64,6 +64,9 @@ type Config struct { // Overlay is whether to wrap the root filesystem in an overlay. Overlay bool `flag:"overlay"` + // Verity is whether there's one or more verity file system to mount. + Verity bool `flag:"verity"` + // FSGoferHostUDS enables the gofer to mount a host UDS. FSGoferHostUDS bool `flag:"fsgofer-host-uds"` diff --git a/runsc/config/flags.go b/runsc/config/flags.go index 7e738dfdf..adbee506c 100644 --- a/runsc/config/flags.go +++ b/runsc/config/flags.go @@ -69,6 +69,7 @@ func RegisterFlags() { // Flags that control sandbox runtime behavior: FS related. flag.Var(fileAccessTypePtr(FileAccessExclusive), "file-access", "specifies which filesystem to use for the root mount: exclusive (default), shared. Volume mounts are always shared.") flag.Bool("overlay", false, "wrap filesystem mounts with writable overlay. All modifications are stored in memory inside the sandbox.") + flag.Bool("verity", false, "specifies whether a verity file system will be mounted.") flag.Bool("overlayfs-stale-read", true, "assume root mount is an overlay filesystem") flag.Bool("fsgofer-host-uds", false, "allow the gofer to mount Unix Domain Sockets.") flag.Bool("vfs2", false, "enables VFSv2. This uses the new VFS layer that is faster than the previous one.") diff --git a/runsc/fsgofer/fsgofer.go b/runsc/fsgofer/fsgofer.go index cfa3796b1..1e80a634d 100644 --- a/runsc/fsgofer/fsgofer.go +++ b/runsc/fsgofer/fsgofer.go @@ -66,6 +66,9 @@ type Config struct { // HostUDS signals whether the gofer can mount a host's UDS. HostUDS bool + + // enableXattr allows Get/SetXattr for the mounted file systems. + EnableXattr bool } type attachPoint struct { @@ -795,12 +798,22 @@ func (l *localFile) SetAttr(valid p9.SetAttrMask, attr p9.SetAttr) error { return err } -func (*localFile) GetXattr(string, uint64) (string, error) { - return "", unix.EOPNOTSUPP +func (l *localFile) GetXattr(name string, size uint64) (string, error) { + if !l.attachPoint.conf.EnableXattr { + return "", unix.EOPNOTSUPP + } + buffer := make([]byte, size) + if _, err := unix.Fgetxattr(l.file.FD(), name, buffer); err != nil { + return "", err + } + return string(buffer), nil } -func (*localFile) SetXattr(string, string, uint32) error { - return unix.EOPNOTSUPP +func (l *localFile) SetXattr(name string, value string, flags uint32) error { + if !l.attachPoint.conf.EnableXattr { + return unix.EOPNOTSUPP + } + return unix.Fsetxattr(l.file.FD(), name, []byte(value), int(flags)) } func (*localFile) ListXattr(uint64) (map[string]struct{}, error) { diff --git a/runsc/fsgofer/fsgofer_test.go b/runsc/fsgofer/fsgofer_test.go index 99ea9bd32..a5f09f88f 100644 --- a/runsc/fsgofer/fsgofer_test.go +++ b/runsc/fsgofer/fsgofer_test.go @@ -565,6 +565,38 @@ func TestSetAttrOwner(t *testing.T) { }) } +func SetGetXattr(l *localFile, name string, value string) error { + if err := l.SetXattr(name, value, 0 /* flags */); err != nil { + return err + } + ret, err := l.GetXattr(name, uint64(len(value))) + if err != nil { + return err + } + if ret != value { + return fmt.Errorf("Got value %s, want %s", ret, value) + } + return nil +} + +func TestSetGetXattr(t *testing.T) { + xattrConfs := []Config{{ROMount: false, EnableXattr: false}, {ROMount: false, EnableXattr: true}} + runCustom(t, []uint32{unix.S_IFREG}, xattrConfs, func(t *testing.T, s state) { + name := "user.test" + value := "tmp" + err := SetGetXattr(s.file, name, value) + if s.conf.EnableXattr { + if err != nil { + t.Fatalf("%v: SetGetXattr failed, err: %v", s, err) + } + } else { + if err == nil { + t.Fatalf("%v: SetGetXattr should have failed", s) + } + } + }) +} + func TestLink(t *testing.T) { if !specutils.HasCapabilities(capability.CAP_DAC_READ_SEARCH) { t.Skipf("Link test requires CAP_DAC_READ_SEARCH, running as %d", os.Getuid()) |