summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-06-26 20:13:21 +0200
committerJakob Unterwurzacher2016-06-26 20:13:21 +0200
commit0115588680c1b00a24407c54d8f7c46a6fa3baf1 (patch)
tree48394a0ce02fd9e18c602434095623e707dce3b9
parentfb5e7023eef0b78de4b27dedfa1cc1c56c71a8cc (diff)
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--
-rw-r--r--internal/fusefrontend/file.go5
-rw-r--r--internal/fusefrontend/fs.go7
-rw-r--r--main.go2
3 files changed, 11 insertions, 3 deletions
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go
index 780a792..546526b 100644
--- a/internal/fusefrontend/file.go
+++ b/internal/fusefrontend/file.go
@@ -459,7 +459,10 @@ func (f *file) Chmod(mode uint32) fuse.Status {
f.fdLock.RLock()
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 {
diff --git a/internal/fusefrontend/fs.go b/internal/fusefrontend/fs.go
index 9ae57fa..49bd031 100644
--- a/internal/fusefrontend/fs.go
+++ b/internal/fusefrontend/fs.go
@@ -158,11 +158,14 @@ func (fs *FS) Chmod(path string, mode uint32, context *fuse.Context) (code fuse.
if fs.isFiltered(path) {
return fuse.EPERM
}
- cPath, err := fs.encryptPath(path)
+ cPath, err := fs.getBackingPath(path)
if err != nil {
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) {
diff --git a/main.go b/main.go
index 8b2f41a..68dfb0a 100644
--- a/main.go
+++ b/main.go
@@ -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,
// we can use device files by passing the opposite mount option, "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
// First column, "Filesystem"