fuse: Error out in case of unsupported file type instead of panicking.

Linux has the same behavior; see callers of fs/fuse/dir.c:fuse_invalid_attr().

Reported-by: syzbot+7e65f2f0bdf121c71bcf@syzkaller.appspotmail.com
PiperOrigin-RevId: 663853750
This commit is contained in:
Ayush Ranjan
2024-08-16 13:59:55 -07:00
committed by gVisor bot
parent 47e1c24f38
commit 834bef5996
2 changed files with 20 additions and 8 deletions
+15 -2
View File
@@ -301,8 +301,11 @@ func (fs *filesystem) newRoot(ctx context.Context, creds *auth.Credentials, mode
return &d
}
func (fs *filesystem) newInode(ctx context.Context, out linux.FUSEEntryOut) kernfs.Inode {
func (fs *filesystem) newInode(ctx context.Context, out linux.FUSEEntryOut) (kernfs.Inode, error) {
attr := out.Attr
if !isValidType(attr.Mode) {
return nil, linuxerr.EIO
}
i := &inode{fs: fs, nodeID: out.NodeID, generation: out.Generation}
i.attrMu.Lock()
defer i.attrMu.Unlock()
@@ -314,5 +317,15 @@ func (fs *filesystem) newInode(ctx context.Context, out linux.FUSEEntryOut) kern
i.OrderedChildren.Init(kernfs.OrderedChildrenOptions{})
i.InitRefs()
return i
return i, nil
}
// isValidType is analogous to fs/fuse/dir.c:fuse_valid_type().
func isValidType(mode uint32) bool {
switch mode & linux.S_IFMT {
case linux.S_IFREG, linux.S_IFDIR, linux.S_IFLNK, linux.S_IFCHR, linux.S_IFBLK, linux.S_IFIFO, linux.S_IFSOCK:
return true
default:
return false
}
}
+5 -6
View File
@@ -15,7 +15,6 @@
package fuse
import (
"fmt"
gotime "time"
"gvisor.dev/gvisor/pkg/abi/linux"
@@ -171,12 +170,9 @@ func (i *inode) touchAtime() {
i.atime.Store(i.fs.clock.Now().Nanoseconds())
}
// Precondition: isValidType(mode) == true.
// +checklocks:i.attrMu
func (i *inode) init(creds *auth.Credentials, devMajor, devMinor uint32, nodeid uint64, mode linux.FileMode, nlink uint32) {
if mode.FileType() == 0 {
panic(fmt.Sprintf("No file type specified in 'mode' for InodeAttrs.Init(): mode=0%o", mode))
}
i.nodeID = nodeid
i.ino.Store(nodeid)
i.mode.Store(uint32(mode))
@@ -560,7 +556,10 @@ func (i *inode) newEntry(ctx context.Context, name string, fileType linux.FileMo
if opcode != linux.FUSE_LOOKUP && ((out.Attr.Mode&linux.S_IFMT)^uint32(fileType) != 0 || out.NodeID == 0 || out.NodeID == linux.FUSE_ROOT_ID) {
return nil, linuxerr.EIO
}
child := i.fs.newInode(ctx, out.FUSEEntryOut)
child, err := i.fs.newInode(ctx, out.FUSEEntryOut)
if err != nil {
return nil, err
}
if opcode == linux.FUSE_CREATE {
// File handler is returned by fuse server at a time of file create.
// Save it temporary in a created child, so Open could return it when invoked