Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151672194
D20947.id59912.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D20947.id59912.diff
View Options
Index: sys/kern/kern_descrip.c
===================================================================
--- sys/kern/kern_descrip.c
+++ sys/kern/kern_descrip.c
@@ -853,6 +853,10 @@
goto unlock;
}
+ oldfde = &fdp->fd_ofiles[old];
+ if (!fhold(oldfde->fde_file))
+ goto unlock;
+
/*
* If the caller specified a file descriptor, make sure the file
* table is large enough to hold it, and grab it. Otherwise, just
@@ -861,13 +865,17 @@
switch (mode) {
case FDDUP_NORMAL:
case FDDUP_FCNTL:
- if ((error = fdalloc(td, new, &new)) != 0)
+ if ((error = fdalloc(td, new, &new)) != 0) {
+ fdrop(oldfde->fde_file, td);
goto unlock;
+ }
break;
case FDDUP_MUSTREPLACE:
/* Target file descriptor must exist. */
- if (fget_locked(fdp, new) == NULL)
+ if (fget_locked(fdp, new) == NULL) {
+ fdrop(oldfde->fde_file, td);
goto unlock;
+ }
break;
case FDDUP_FIXED:
if (new >= fdp->fd_nfiles) {
@@ -884,6 +892,7 @@
error = racct_set_unlocked(p, RACCT_NOFILE, new + 1);
if (error != 0) {
error = EMFILE;
+ fdrop(oldfde->fde_file, td);
goto unlock;
}
}
@@ -899,8 +908,6 @@
KASSERT(old != new, ("new fd is same as old"));
- oldfde = &fdp->fd_ofiles[old];
- fhold(oldfde->fde_file);
newfde = &fdp->fd_ofiles[new];
delfp = newfde->fde_file;
@@ -1901,12 +1908,14 @@
MPASS(fd != NULL);
+ if (!fhold(fp))
+ return (EBADF);
FILEDESC_XLOCK(fdp);
if ((error = fdalloc(td, 0, fd))) {
FILEDESC_XUNLOCK(fdp);
+ fdrop(fp, td);
return (error);
}
- fhold(fp);
_finstall(fdp, fp, *fd, flags, fcaps);
FILEDESC_XUNLOCK(fdp);
return (0);
@@ -2047,7 +2056,8 @@
for (i = 0; i <= fdp->fd_lastfile; ++i) {
ofde = &fdp->fd_ofiles[i];
if (ofde->fde_file == NULL ||
- (ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0) {
+ (ofde->fde_file->f_ops->fo_flags & DFLAG_PASSABLE) == 0 ||
+ !fhold(ofde->fde_file)) {
if (newfdp->fd_freefile == -1)
newfdp->fd_freefile = i;
continue;
@@ -2055,7 +2065,6 @@
nfde = &newfdp->fd_ofiles[i];
*nfde = *ofde;
filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true);
- fhold(nfde->fde_file);
fdused_init(newfdp, i);
newfdp->fd_lastfile = i;
}
@@ -2108,10 +2117,13 @@
error = EINVAL;
goto bad;
}
+ if (!fhold(nfde->fde_file)) {
+ error = EBADF;
+ goto bad;
+ }
nfde = &newfdp->fd_ofiles[i];
*nfde = *ofde;
filecaps_copy(&ofde->fde_caps, &nfde->fde_caps, true);
- fhold(nfde->fde_file);
fdused_init(newfdp, i);
newfdp->fd_lastfile = i;
}
@@ -2153,9 +2165,9 @@
(p->p_leader->p_flag & P_ADVLOCK) != 0) {
for (i = 0; i <= fdp->fd_lastfile; i++) {
fp = fdp->fd_ofiles[i].fde_file;
- if (fp == NULL || fp->f_type != DTYPE_VNODE)
+ if (fp == NULL || fp->f_type != DTYPE_VNODE ||
+ !fhold(fp))
continue;
- fhold(fp);
FILEDESC_XUNLOCK(fdp);
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@@ -2596,8 +2608,8 @@
get_locked:
FILEDESC_SLOCK(fdp);
error = fget_cap_locked(fdp, fd, needrightsp, fpp, havecapsp);
- if (error == 0)
- fhold(*fpp);
+ if (error == 0 && !fhold(*fpp))
+ error = EBADF;
FILEDESC_SUNLOCK(fdp);
#endif
return (error);
@@ -2656,14 +2668,19 @@
* table before this fd was closed, so it possible that
* there is a stale fp pointer in cached version.
*/
- fdt = *(const struct fdescenttbl * const volatile *)&(fdp->fd_files);
+ fdt = *(const struct fdescenttbl * const volatile *)
+ &(fdp->fd_files);
continue;
}
+ if (__predict_false(count + 1 < count))
+ return (EBADF);
+
/*
* Use an acquire barrier to force re-reading of fdt so it is
* refreshed for verification.
*/
- if (atomic_fcmpset_acq_int(&fp->f_count, &count, count + 1) == 0)
+ if (__predict_false(atomic_fcmpset_acq_int(&fp->f_count,
+ &count, count + 1) == 0))
goto retry;
fdt = fdp->fd_files;
#ifdef CAPABILITIES
@@ -3048,7 +3065,11 @@
FILEDESC_XUNLOCK(fdp);
return (EACCES);
}
- fhold(fp);
+ if (!fhold(fp)) {
+ fdunused(fdp, indx);
+ FILEDESC_XUNLOCK(fdp);
+ return (EBADF);
+ }
newfde = &fdp->fd_ofiles[indx];
oldfde = &fdp->fd_ofiles[dfd];
ioctls = filecaps_copy_prep(&oldfde->fde_caps);
Index: sys/kern/sys_generic.c
===================================================================
--- sys/kern/sys_generic.c
+++ sys/kern/sys_generic.c
@@ -757,7 +757,11 @@
fp = NULL; /* fhold() was not called yet */
goto out;
}
- fhold(fp);
+ if (!fhold(fp)) {
+ error = EBADF;
+ fp = NULL;
+ goto out;
+ }
if (locked == LA_SLOCKED) {
FILEDESC_SUNLOCK(fdp);
locked = LA_UNLOCKED;
Index: sys/kern/uipc_usrreq.c
===================================================================
--- sys/kern/uipc_usrreq.c
+++ sys/kern/uipc_usrreq.c
@@ -2133,7 +2133,7 @@
struct file *fp;
struct timeval *tv;
struct timespec *ts;
- int i, *fdp;
+ int i, j, *fdp;
void *data;
socklen_t clen = control->m_len, datalen;
int error, oldfds;
@@ -2214,6 +2214,19 @@
goto out;
}
fdp = data;
+ for (i = 0; i < oldfds; i++, fdp++) {
+ if (!fhold(fdesc->fd_ofiles[*fdp].fde_file)) {
+ fdp = data;
+ for (j = 0; j < i; j++, fdp++) {
+ fdrop(fdesc->fd_ofiles[*fdp].
+ fde_file, td);
+ }
+ FILEDESC_SUNLOCK(fdesc);
+ error = EBADF;
+ goto out;
+ }
+ }
+ fdp = data;
fdep = (struct filedescent **)
CMSG_DATA(mtod(*controlp, struct cmsghdr *));
fdev = malloc(sizeof(*fdev) * oldfds, M_FILECAPS,
@@ -2415,7 +2428,6 @@
unp->unp_file = fp;
unp->unp_msgcount++;
}
- fhold(fp);
unp_rights++;
UNP_LINK_WUNLOCK();
}
@@ -2576,10 +2588,10 @@
if ((unp->unp_gcflag & UNPGC_DEAD) != 0) {
f = unp->unp_file;
if (unp->unp_msgcount == 0 || f == NULL ||
- f->f_count != unp->unp_msgcount)
+ f->f_count != unp->unp_msgcount ||
+ !fhold(f))
continue;
unref[total++] = f;
- fhold(f);
KASSERT(total <= unp_unreachable,
("unp_gc: incorrect unreachable count."));
}
Index: sys/sys/file.h
===================================================================
--- sys/sys/file.h
+++ sys/sys/file.h
@@ -284,8 +284,12 @@
return (0);
}
-#define fhold(fp) \
- (refcount_acquire(&(fp)->f_count))
+static __inline __result_use_check bool
+fhold(struct file *fp)
+{
+ return (refcount_acquire_checked(&fp->f_count));
+}
+
#define fdrop(fp, td) \
(refcount_release(&(fp)->f_count) ? _fdrop((fp), (td)) : _fnoop())
Index: sys/sys/refcount.h
===================================================================
--- sys/sys/refcount.h
+++ sys/sys/refcount.h
@@ -54,6 +54,20 @@
atomic_add_int(count, 1);
}
+static __inline __result_use_check bool
+refcount_acquire_checked(volatile u_int *count)
+{
+ u_int lcount;
+
+ for (lcount = *count;;) {
+ if (__predict_false(lcount + 1 < lcount))
+ return (false);
+ if (__predict_true(atomic_fcmpset_int(count, &lcount,
+ lcount + 1) == 1))
+ return (true);
+ }
+}
+
static __inline int
refcount_release(volatile u_int *count)
{
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Apr 10, 10:22 PM (16 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31249853
Default Alt Text
D20947.id59912.diff (6 KB)
Attached To
Mode
D20947: Check and avoid overflow when incrementing fp->f_count in fget_unlocked() and fhold().
Attached
Detach File
Event Timeline
Log In to Comment