summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/fsimpl/overlay/regular_file.go
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2021-03-16 14:53:42 -0700
committergVisor bot <gvisor-bot@google.com>2021-03-16 14:55:29 -0700
commit607a1e481c276c8ab0c3e194ed04b38bc07b71b6 (patch)
treee760228af2d1b5fc7766a284fb6a8bb9b2b6ba28 /pkg/sentry/fsimpl/overlay/regular_file.go
parent05193de1ccaf487a175dead4121c62b99e02d0f5 (diff)
setgid directory support in overlayfs
PiperOrigin-RevId: 363276495
Diffstat (limited to 'pkg/sentry/fsimpl/overlay/regular_file.go')
-rw-r--r--pkg/sentry/fsimpl/overlay/regular_file.go43
1 files changed, 41 insertions, 2 deletions
diff --git a/pkg/sentry/fsimpl/overlay/regular_file.go b/pkg/sentry/fsimpl/overlay/regular_file.go
index 25c785fd4..d791c06db 100644
--- a/pkg/sentry/fsimpl/overlay/regular_file.go
+++ b/pkg/sentry/fsimpl/overlay/regular_file.go
@@ -205,6 +205,20 @@ func (fd *regularFileFD) SetStat(ctx context.Context, opts vfs.SetStatOptions) e
if err := wrappedFD.SetStat(ctx, opts); err != nil {
return err
}
+
+ // Changing owners may clear one or both of the setuid and setgid bits,
+ // so we may have to update opts before setting d.mode.
+ if opts.Stat.Mask&(linux.STATX_UID|linux.STATX_GID) != 0 {
+ stat, err := wrappedFD.Stat(ctx, vfs.StatOptions{
+ Mask: linux.STATX_MODE,
+ })
+ if err != nil {
+ return err
+ }
+ opts.Stat.Mode = stat.Mode
+ opts.Stat.Mask |= linux.STATX_MODE
+ }
+
d.updateAfterSetStatLocked(&opts)
if ev := vfs.InotifyEventFromStatMask(opts.Stat.Mask); ev != 0 {
d.InotifyWithParent(ctx, ev, 0, vfs.InodeEvent)
@@ -295,7 +309,11 @@ func (fd *regularFileFD) PWrite(ctx context.Context, src usermem.IOSequence, off
return 0, err
}
defer wrappedFD.DecRef(ctx)
- return wrappedFD.PWrite(ctx, src, offset, opts)
+ n, err := wrappedFD.PWrite(ctx, src, offset, opts)
+ if err != nil {
+ return n, err
+ }
+ return fd.updateSetUserGroupIDs(ctx, wrappedFD, n)
}
// Write implements vfs.FileDescriptionImpl.Write.
@@ -307,7 +325,28 @@ func (fd *regularFileFD) Write(ctx context.Context, src usermem.IOSequence, opts
if err != nil {
return 0, err
}
- return wrappedFD.Write(ctx, src, opts)
+ n, err := wrappedFD.Write(ctx, src, opts)
+ if err != nil {
+ return n, err
+ }
+ return fd.updateSetUserGroupIDs(ctx, wrappedFD, n)
+}
+
+func (fd *regularFileFD) updateSetUserGroupIDs(ctx context.Context, wrappedFD *vfs.FileDescription, written int64) (int64, error) {
+ // Writing can clear the setuid and/or setgid bits. We only have to
+ // check this if something was written and one of those bits was set.
+ dentry := fd.dentry()
+ if written == 0 || atomic.LoadUint32(&dentry.mode)&(linux.S_ISUID|linux.S_ISGID) == 0 {
+ return written, nil
+ }
+ stat, err := wrappedFD.Stat(ctx, vfs.StatOptions{Mask: linux.STATX_MODE})
+ if err != nil {
+ return written, err
+ }
+ dentry.copyMu.Lock()
+ defer dentry.copyMu.Unlock()
+ atomic.StoreUint32(&dentry.mode, uint32(stat.Mode))
+ return written, nil
}
// Seek implements vfs.FileDescriptionImpl.Seek.