Skip to content

Commit 03b9d65

Browse files
committed
fusefrontend: -allow_other: Use OpenatUser in Create FUSE call.
Revert commit b22cc03. Instead of manually adjusting the user and mode after creating the file, adjust effective permissions and let the kernel deal with it. Related to #338.
1 parent 6693224 commit 03b9d65

File tree

3 files changed

+34
-28
lines changed

3 files changed

+34
-28
lines changed

internal/fusefrontend/fs.go

+6-28
Original file line numberDiff line numberDiff line change
@@ -238,15 +238,11 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
238238
return nil, fuse.ToStatus(err)
239239
}
240240
defer syscall.Close(dirfd)
241-
// Don't set full mode before we have set the correct owner. Files with SUID/SGID
242-
// mode belonging to the wrong owner would be a security risk. Even for other
243-
// modes, we don't want anyone else to open the file in the meantime: the fd would
244-
// stay open and could later be used to read the file.
245-
origMode := mode
246-
if fs.args.PreserveOwner {
247-
mode = 0000
248-
}
249241
fd := -1
242+
// Make sure context is nil if we don't want to preserve the owner
243+
if !fs.args.PreserveOwner {
244+
context = nil
245+
}
250246
// Handle long file name
251247
if !fs.args.PlaintextNames && nametransform.IsLongContent(cName) {
252248
// Create ".name"
@@ -255,14 +251,14 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
255251
return nil, fuse.ToStatus(err)
256252
}
257253
// Create content
258-
fd, err = syscallcompat.Openat(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode)
254+
fd, err = syscallcompat.OpenatUser(dirfd, cName, newFlags|os.O_CREATE|os.O_EXCL, mode, context)
259255
if err != nil {
260256
nametransform.DeleteLongNameAt(dirfd, cName)
261257
return nil, fuse.ToStatus(err)
262258
}
263259
} else {
264260
// Create content, normal (short) file name
265-
fd, err = syscallcompat.Openat(dirfd, cName, newFlags|syscall.O_CREAT|syscall.O_EXCL, mode)
261+
fd, err = syscallcompat.OpenatUser(dirfd, cName, newFlags|syscall.O_CREAT|syscall.O_EXCL, mode, context)
266262
if err != nil {
267263
// xfstests generic/488 triggers this
268264
if err == syscall.EMFILE {
@@ -273,24 +269,6 @@ func (fs *FS) Create(path string, flags uint32, mode uint32, context *fuse.Conte
273269
return nil, fuse.ToStatus(err)
274270
}
275271
}
276-
// Set owner
277-
if fs.args.PreserveOwner {
278-
err = syscall.Fchown(fd, int(context.Owner.Uid), int(context.Owner.Gid))
279-
if err != nil {
280-
tlog.Warn.Printf("Create %q: Fchown %d:%d failed: %v", cName, context.Owner.Uid, context.Owner.Gid, err)
281-
// In case of a failure, we don't want to proceed setting more
282-
// permissive modes.
283-
syscall.Close(fd)
284-
return nil, fuse.ToStatus(err)
285-
}
286-
}
287-
// Set mode
288-
if mode != origMode {
289-
err = syscall.Fchmod(fd, origMode)
290-
if err != nil {
291-
tlog.Warn.Printf("Create %q: Fchmod %#o -> %#o failed: %v", cName, mode, origMode, err)
292-
}
293-
}
294272
f := os.NewFile(uintptr(fd), cName)
295273
return NewFile(f, fs)
296274
}

internal/syscallcompat/sys_darwin.go

+5
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
4646
return emulateOpenat(dirfd, path, flags, mode)
4747
}
4848

49+
func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) {
50+
// FIXME: take into account context.Owner
51+
return Openat(dirfd, path, flags, mode)
52+
}
53+
4954
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
5055
return emulateRenameat(olddirfd, oldpath, newdirfd, newpath)
5156
}

internal/syscallcompat/sys_linux.go

+23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package syscallcompat
33

44
import (
55
"fmt"
6+
"runtime"
67
"sync"
78
"syscall"
89

@@ -75,6 +76,28 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
7576
return syscall.Openat(dirfd, path, flags, mode)
7677
}
7778

79+
// OpenatUser runs the Openat syscall in the context of a different user.
80+
func OpenatUser(dirfd int, path string, flags int, mode uint32, context *fuse.Context) (fd int, err error) {
81+
if context != nil {
82+
runtime.LockOSThread()
83+
defer runtime.UnlockOSThread()
84+
85+
err = syscall.Setregid(-1, int(context.Owner.Gid))
86+
if err != nil {
87+
return -1, err
88+
}
89+
defer syscall.Setregid(-1, 0)
90+
91+
err = syscall.Setreuid(-1, int(context.Owner.Uid))
92+
if err != nil {
93+
return -1, err
94+
}
95+
defer syscall.Setreuid(-1, 0)
96+
}
97+
98+
return Openat(dirfd, path, flags, mode)
99+
}
100+
78101
// Renameat wraps the Renameat syscall.
79102
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
80103
return syscall.Renameat(olddirfd, oldpath, newdirfd, newpath)

0 commit comments

Comments
 (0)