mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add missing error checks for FileDescription.Init.
Syzkaller discovered this bug in pipefs by doing something quite strange: creat(&(0x7f0000002a00)='./file1\x00', 0x0) mount(&(0x7f0000000440)=ANY=[], &(0x7f00000002c0)='./file1\x00', &(0x7f0000000300)='devtmpfs\x00', 0x20000d, 0x0) creat(&(0x7f0000000000)='./file1/file0\x00', 0x0) This can be reproduced with: touch mymount mkfifo /dev/mypipe mount -o ro -t devtmpfs devtmpfs mymount echo 123 > mymount/mypipe PiperOrigin-RevId: 349687714
This commit is contained in:
@@ -200,7 +200,9 @@ func (in *inode) open(rp *vfs.ResolvingPath, vfsd *vfs.Dentry, opts *vfs.OpenOpt
|
||||
}
|
||||
var fd symlinkFD
|
||||
fd.LockFD.Init(&in.locks)
|
||||
fd.vfsfd.Init(&fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{})
|
||||
if err := fd.vfsfd.Init(&fd, opts.Flags, mnt, vfsd, &vfs.FileDescriptionOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &fd.vfsfd, nil
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown inode type: %T", in.impl))
|
||||
|
||||
@@ -164,11 +164,11 @@ func (i *inode) StatFS(ctx context.Context, fs *vfs.Filesystem) (linux.Statfs, e
|
||||
// and write ends of a newly-created pipe, as for pipe(2) and pipe2(2).
|
||||
//
|
||||
// Preconditions: mnt.Filesystem() must have been returned by NewFilesystem().
|
||||
func NewConnectedPipeFDs(ctx context.Context, mnt *vfs.Mount, flags uint32) (*vfs.FileDescription, *vfs.FileDescription) {
|
||||
func NewConnectedPipeFDs(ctx context.Context, mnt *vfs.Mount, flags uint32) (*vfs.FileDescription, *vfs.FileDescription, error) {
|
||||
fs := mnt.Filesystem().Impl().(*filesystem)
|
||||
inode := newInode(ctx, fs)
|
||||
var d kernfs.Dentry
|
||||
d.Init(&fs.Filesystem, inode)
|
||||
defer d.DecRef(ctx)
|
||||
return inode.pipe.ReaderWriterPair(mnt, d.VFSDentry(), flags)
|
||||
return inode.pipe.ReaderWriterPair(ctx, mnt, d.VFSDentry(), flags)
|
||||
}
|
||||
|
||||
@@ -63,10 +63,19 @@ func NewVFSPipe(isNamed bool, sizeBytes int64) *VFSPipe {
|
||||
// ReaderWriterPair returns read-only and write-only FDs for vp.
|
||||
//
|
||||
// Preconditions: statusFlags should not contain an open access mode.
|
||||
func (vp *VFSPipe) ReaderWriterPair(mnt *vfs.Mount, vfsd *vfs.Dentry, statusFlags uint32) (*vfs.FileDescription, *vfs.FileDescription) {
|
||||
func (vp *VFSPipe) ReaderWriterPair(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, statusFlags uint32) (*vfs.FileDescription, *vfs.FileDescription, error) {
|
||||
// Connected pipes share the same locks.
|
||||
locks := &vfs.FileLocks{}
|
||||
return vp.newFD(mnt, vfsd, linux.O_RDONLY|statusFlags, locks), vp.newFD(mnt, vfsd, linux.O_WRONLY|statusFlags, locks)
|
||||
r, err := vp.newFD(mnt, vfsd, linux.O_RDONLY|statusFlags, locks)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
w, err := vp.newFD(mnt, vfsd, linux.O_WRONLY|statusFlags, locks)
|
||||
if err != nil {
|
||||
r.DecRef(ctx)
|
||||
return nil, nil, err
|
||||
}
|
||||
return r, w, nil
|
||||
}
|
||||
|
||||
// Allocate implements vfs.FileDescriptionImpl.Allocate.
|
||||
@@ -85,7 +94,10 @@ func (vp *VFSPipe) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, s
|
||||
return nil, syserror.EINVAL
|
||||
}
|
||||
|
||||
fd := vp.newFD(mnt, vfsd, statusFlags, locks)
|
||||
fd, err := vp.newFD(mnt, vfsd, statusFlags, locks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Named pipes have special blocking semantics during open:
|
||||
//
|
||||
@@ -137,16 +149,18 @@ func (vp *VFSPipe) Open(ctx context.Context, mnt *vfs.Mount, vfsd *vfs.Dentry, s
|
||||
}
|
||||
|
||||
// Preconditions: vp.mu must be held.
|
||||
func (vp *VFSPipe) newFD(mnt *vfs.Mount, vfsd *vfs.Dentry, statusFlags uint32, locks *vfs.FileLocks) *vfs.FileDescription {
|
||||
func (vp *VFSPipe) newFD(mnt *vfs.Mount, vfsd *vfs.Dentry, statusFlags uint32, locks *vfs.FileLocks) (*vfs.FileDescription, error) {
|
||||
fd := &VFSPipeFD{
|
||||
pipe: &vp.pipe,
|
||||
}
|
||||
fd.LockFD.Init(locks)
|
||||
fd.vfsfd.Init(fd, statusFlags, mnt, vfsd, &vfs.FileDescriptionOptions{
|
||||
if err := fd.vfsfd.Init(fd, statusFlags, mnt, vfsd, &vfs.FileDescriptionOptions{
|
||||
DenyPRead: true,
|
||||
DenyPWrite: true,
|
||||
UseDentryMetadata: true,
|
||||
})
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case fd.vfsfd.IsReadable() && fd.vfsfd.IsWritable():
|
||||
@@ -160,7 +174,7 @@ func (vp *VFSPipe) newFD(mnt *vfs.Mount, vfsd *vfs.Dentry, statusFlags uint32, l
|
||||
panic("invalid pipe flags: must be readable, writable, or both")
|
||||
}
|
||||
|
||||
return &fd.vfsfd
|
||||
return &fd.vfsfd, nil
|
||||
}
|
||||
|
||||
// VFSPipeFD implements vfs.FileDescriptionImpl for pipes. It also implements
|
||||
|
||||
@@ -42,7 +42,10 @@ func pipe2(t *kernel.Task, addr usermem.Addr, flags int32) error {
|
||||
if flags&^(linux.O_NONBLOCK|linux.O_CLOEXEC) != 0 {
|
||||
return syserror.EINVAL
|
||||
}
|
||||
r, w := pipefs.NewConnectedPipeFDs(t, t.Kernel().PipeMount(), uint32(flags&linux.O_NONBLOCK))
|
||||
r, w, err := pipefs.NewConnectedPipeFDs(t, t.Kernel().PipeMount(), uint32(flags&linux.O_NONBLOCK))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer r.DecRef(t)
|
||||
defer w.DecRef(t)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user