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:
Konstantin Belousov 2007-05-04 14:23:29 +00:00
parent c65aee44c6
commit 5c76452f8f
3 changed files with 20 additions and 3 deletions

View File

@ -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]);

View File

@ -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

View File

@ -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