summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-11-24 20:34:06 +0000
committerkib <kib@FreeBSD.org>2011-11-24 20:34:06 +0000
commit6ecd4a2bb26b95634ff18d310e228dedf6fcae50 (patch)
tree6880f765258a6f4378329964c5a5a2beaaa1eea0 /sys/kern/vfs_syscalls.c
parent6b1253786db1ae2f5aececb06fc2c6aa974392ff (diff)
downloadFreeBSD-src-6ecd4a2bb26b95634ff18d310e228dedf6fcae50.zip
FreeBSD-src-6ecd4a2bb26b95634ff18d310e228dedf6fcae50.tar.gz
Fix a race between getvnode() dereferencing half-constructed file
and dupfdopen(). Reported and tested by: pho MFC after: 3 days
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index fe012d5..b3920d3 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -4344,7 +4344,20 @@ getvnode(struct filedesc *fdp, int fd, cap_rights_t rights,
fp = fp_fromcap;
}
#endif /* CAPABILITIES */
- if (fp->f_vnode == NULL) {
+
+ /*
+ * The file could be not of the vnode type, or it may be not
+ * yet fully initialized, in which case the f_vnode pointer
+ * may be set, but f_ops is still badfileops. E.g.,
+ * devfs_open() transiently create such situation to
+ * facilitate csw d_fdopen().
+ *
+ * Dupfdopen() handling in kern_openat() installs the
+ * half-baked file into the process descriptor table, allowing
+ * other thread to dereference it. Guard against the race by
+ * checking f_ops.
+ */
+ if (fp->f_vnode == NULL || fp->f_ops == &badfileops) {
fdrop(fp, curthread);
return (EINVAL);
}
OpenPOWER on IntegriCloud