main, fusefrontend: enable suid functionality

FUSE filesystems are mounted with "nosuid" by default. If we run as root,
we can use device files by passing the opposite mount option, "suid".

Also we have to use syscall.Chmod instead of os.Chmod because the
portability translation layer "syscallMode" messes up the sgid
and suid bits.

Fixes 70% of the failures in xfstests generic/193. The remaining are
related to truncate, but we err on the safe side:

    $ diff -u tests/generic/193.out /home/jakob/src/fuse-xfstests/results//generic/193.out.bad
    [...]
     check that suid/sgid bits are cleared after successful truncate...
     with no exec perm
     before: -rwSr-Sr--
    -after:  -rw-r-Sr--
    +after:  -rw-r--r--
This commit is contained in:
Jakob Unterwurzacher 2016-06-26 20:13:21 +02:00
parent fb5e7023ee
commit 0115588680
3 changed files with 11 additions and 3 deletions

View File

@ -459,7 +459,10 @@ func (f *file) Chmod(mode uint32) fuse.Status {
f.fdLock.RLock() f.fdLock.RLock()
defer f.fdLock.RUnlock() defer f.fdLock.RUnlock()
return fuse.ToStatus(f.fd.Chmod(os.FileMode(mode))) // os.File.Chmod goes through the "syscallMode" translation function that messes
// up the suid and sgid bits. So use syscall.Fchmod directly.
err := syscall.Fchmod(f.intFd(), mode)
return fuse.ToStatus(err)
} }
func (f *file) Chown(uid uint32, gid uint32) fuse.Status { func (f *file) Chown(uid uint32, gid uint32) fuse.Status {

View File

@ -158,11 +158,14 @@ func (fs *FS) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.
if fs.isFiltered(path) { if fs.isFiltered(path) {
return fuse.EPERM return fuse.EPERM
} }
cPath, err := fs.encryptPath(path) cPath, err := fs.getBackingPath(path)
if err != nil { if err != nil {
return fuse.ToStatus(err) return fuse.ToStatus(err)
} }
return fs.FileSystem.Chmod(cPath, mode, context) // os.Chmod goes through the "syscallMode" translation function that messes
// up the suid and sgid bits. So use syscall.Chmod directly.
err = syscall.Chmod(cPath, mode)
return fuse.ToStatus(err)
} }
func (fs *FS) Chown(path string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) { func (fs *FS) Chown(path string, uid uint32, gid uint32, context *fuse.Context) (code fuse.Status) {

View File

@ -406,6 +406,8 @@ func initFuseFrontend(key []byte, args argContainer, confFile *configfile.ConfFi
// FUSE filesystems are mounted with "nodev" by default. If we run as root, // FUSE filesystems are mounted with "nodev" by default. If we run as root,
// we can use device files by passing the opposite mount option, "dev". // we can use device files by passing the opposite mount option, "dev".
mOpts.Options = append(mOpts.Options, "dev") mOpts.Options = append(mOpts.Options, "dev")
// Same thing for "nosuid". If we run as root, we can pass "suid".
mOpts.Options = append(mOpts.Options, "suid")
} }
// Set values shown in "df -T" and friends // Set values shown in "df -T" and friends
// First column, "Filesystem" // First column, "Filesystem"