diff options
author | Kevin Krakauer <krakauer@google.com> | 2021-02-10 17:43:25 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-02-10 17:45:18 -0800 |
commit | 81ea0016e62318053f97ec714967047e6191fb2b (patch) | |
tree | 36cffbaec97f79f8f06f442d28aba077f470b4be /pkg/sentry/fsimpl/kernfs | |
parent | ff04d019e3d20adf0f5ef3146fa28d3b83a4819a (diff) |
Support setgid directories in tmpfs and kernfs
PiperOrigin-RevId: 356868412
Diffstat (limited to 'pkg/sentry/fsimpl/kernfs')
-rw-r--r-- | pkg/sentry/fsimpl/kernfs/inode_impl_util.go | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go index 8139bff76..6b890a39c 100644 --- a/pkg/sentry/fsimpl/kernfs/inode_impl_util.go +++ b/pkg/sentry/fsimpl/kernfs/inode_impl_util.go @@ -294,22 +294,41 @@ func (a *InodeAttrs) SetStat(ctx context.Context, fs *vfs.Filesystem, creds *aut return err } + clearSID := false stat := opts.Stat + if stat.Mask&linux.STATX_UID != 0 { + atomic.StoreUint32(&a.uid, stat.UID) + clearSID = true + } + if stat.Mask&linux.STATX_GID != 0 { + atomic.StoreUint32(&a.gid, stat.GID) + clearSID = true + } if stat.Mask&linux.STATX_MODE != 0 { for { old := atomic.LoadUint32(&a.mode) - new := old | uint32(stat.Mode & ^uint16(linux.S_IFMT)) - if swapped := atomic.CompareAndSwapUint32(&a.mode, old, new); swapped { + ft := old & linux.S_IFMT + newMode := ft | uint32(stat.Mode & ^uint16(linux.S_IFMT)) + if clearSID { + newMode = vfs.ClearSUIDAndSGID(newMode) + } + if swapped := atomic.CompareAndSwapUint32(&a.mode, old, newMode); swapped { + clearSID = false break } } } - if stat.Mask&linux.STATX_UID != 0 { - atomic.StoreUint32(&a.uid, stat.UID) - } - if stat.Mask&linux.STATX_GID != 0 { - atomic.StoreUint32(&a.gid, stat.GID) + // We may have to clear the SUID/SGID bits, but didn't do so as part of + // STATX_MODE. + if clearSID { + for { + old := atomic.LoadUint32(&a.mode) + newMode := vfs.ClearSUIDAndSGID(old) + if swapped := atomic.CompareAndSwapUint32(&a.mode, old, newMode); swapped { + break + } + } } now := ktime.NowFromContext(ctx).Nanoseconds() |