Mark the filedescriptor table entries with VOP_OPEN being performed for them
as UF_OPENING. Disable closing of that entries. This should fix the crashes caused by devfs_open() (and fifo_open()) dereferencing struct file * by index, while the filedescriptor is closed by parallel thread. Idea by: tegge Reviewed by: tegge (previous version of patch) Tested by: Peter Holm Approved by: re (kensmith) MFC after: 3 weeks
This commit is contained in:
parent
c65aee44c6
commit
5c76452f8f
@ -666,7 +666,9 @@ do_dup(struct thread *td, enum dup_type type, int old, int new,
|
||||
* bad file descriptor. Userland should do its own locking to
|
||||
* avoid this case.
|
||||
*/
|
||||
if (fdp->fd_ofiles[old] != fp) {
|
||||
if (fdp->fd_ofiles[old] != fp ||
|
||||
(fdp->fd_ofileflags[old] & UF_OPENING) != 0 ||
|
||||
(fdp->fd_ofileflags[new] & UF_OPENING) != 0) {
|
||||
/* we've allocated a descriptor which we won't use */
|
||||
if (fdp->fd_ofiles[new] == NULL)
|
||||
fdunused(fdp, new);
|
||||
@ -990,7 +992,8 @@ kern_close(td, fd)
|
||||
|
||||
FILEDESC_XLOCK(fdp);
|
||||
if ((unsigned)fd >= fdp->fd_nfiles ||
|
||||
(fp = fdp->fd_ofiles[fd]) == NULL) {
|
||||
(fp = fdp->fd_ofiles[fd]) == NULL ||
|
||||
(fdp->fd_ofileflags[fd] & UF_OPENING) != 0) {
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
return (EBADF);
|
||||
}
|
||||
@ -1504,7 +1507,8 @@ fdcopy(struct filedesc *fdp)
|
||||
newfdp->fd_freefile = -1;
|
||||
for (i = 0; i <= fdp->fd_lastfile; ++i) {
|
||||
if (fdisused(fdp, i) &&
|
||||
fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE) {
|
||||
fdp->fd_ofiles[i]->f_type != DTYPE_KQUEUE &&
|
||||
(fdp->fd_ofileflags[i] & UF_OPENING) == 0) {
|
||||
newfdp->fd_ofiles[i] = fdp->fd_ofiles[i];
|
||||
newfdp->fd_ofileflags[i] = fdp->fd_ofileflags[i];
|
||||
fhold(newfdp->fd_ofiles[i]);
|
||||
|
@ -984,7 +984,19 @@ kern_open(struct thread *td, char *path, enum uio_seg pathseg, int flags,
|
||||
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
|
||||
NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td);
|
||||
td->td_dupfd = -1; /* XXX check for fdopen */
|
||||
FILEDESC_XLOCK(fdp);
|
||||
if (fp != fdp->fd_ofiles[indx]) {
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
fdrop(fp, td);
|
||||
td->td_retval[0] = indx;
|
||||
return (0);
|
||||
}
|
||||
fdp->fd_ofileflags[indx] |= UF_OPENING;
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
error = vn_open(&nd, &flags, cmode, indx);
|
||||
FILEDESC_XLOCK(fdp);
|
||||
fdp->fd_ofileflags[indx] &= ~UF_OPENING;
|
||||
FILEDESC_XUNLOCK(fdp);
|
||||
if (error) {
|
||||
/*
|
||||
* If the vn_open replaced the method vector, something
|
||||
|
@ -89,6 +89,7 @@ struct filedesc_to_leader {
|
||||
* Per-process open flags.
|
||||
*/
|
||||
#define UF_EXCLOSE 0x01 /* auto-close on exec */
|
||||
#define UF_OPENING 0x02 /* file is being opened */
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user