diff options
| author | Tor Egge <tegge@FreeBSD.org> | 2003-02-15 22:43:05 +0000 |
|---|---|---|
| committer | Tor Egge <tegge@FreeBSD.org> | 2003-02-15 22:43:05 +0000 |
| commit | 218a01e0624b8b439277a5e0f5b52a529840121e (patch) | |
| tree | b8fc43179ec725ae6a10c79cff344462bcda2b98 | |
| parent | 6f8ebcc2323135ca3f26a0458f86c9c0942c6086 (diff) | |
Notes
| -rw-r--r-- | sys/kern/kern_descrip.c | 66 | ||||
| -rw-r--r-- | sys/kern/kern_fork.c | 7 |
2 files changed, 58 insertions, 15 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index ba3424d9a473..342673eabcd3 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -367,9 +367,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) error = EBADF; break; } - PROC_LOCK(p); - p->p_flag |= P_ADVLOCK; - PROC_UNLOCK(p); + PROC_LOCK(p->p_leader); + p->p_leader->p_flag |= P_ADVLOCK; + PROC_UNLOCK(p->p_leader); error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK, flp, flg); break; @@ -378,9 +378,9 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) error = EBADF; break; } - PROC_LOCK(p); - p->p_flag |= P_ADVLOCK; - PROC_UNLOCK(p); + PROC_LOCK(p->p_leader); + p->p_leader->p_flag |= P_ADVLOCK; + PROC_UNLOCK(p->p_leader); error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK, flp, flg); break; @@ -392,6 +392,19 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) error = EINVAL; break; } + /* Check for race with close */ + FILEDESC_LOCK(fdp); + if ((unsigned) fd >= fdp->fd_nfiles || + fp != fdp->fd_ofiles[fd]) { + FILEDESC_UNLOCK(fdp); + flp->l_whence = SEEK_SET; + flp->l_start = 0; + flp->l_len = 0; + flp->l_type = F_UNLCK; + (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader, + F_UNLCK, flp, F_POSIX); + } else + FILEDESC_UNLOCK(fdp); fdrop(fp, td); break; @@ -427,6 +440,19 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg) vp = fp->f_data; error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK, flp, F_POSIX); + /* Check for race with close */ + FILEDESC_LOCK(fdp); + if ((unsigned) fd >= fdp->fd_nfiles || + fp != fdp->fd_ofiles[fd]) { + FILEDESC_UNLOCK(fdp); + flp->l_whence = SEEK_SET; + flp->l_start = 0; + flp->l_len = 0; + flp->l_type = F_UNLCK; + (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader, + F_UNLCK, flp, F_POSIX); + } else + FILEDESC_UNLOCK(fdp); fdrop(fp, td); break; default: @@ -1632,15 +1658,25 @@ closef(fp, td) * If the descriptor was in a message, POSIX-style locks * aren't passed with the descriptor. */ - if (td && (td->td_proc->p_flag & P_ADVLOCK) && - fp->f_type == DTYPE_VNODE) { - lf.l_whence = SEEK_SET; - lf.l_start = 0; - lf.l_len = 0; - lf.l_type = F_UNLCK; - vp = fp->f_data; - (void) VOP_ADVLOCK(vp, (caddr_t)td->td_proc->p_leader, - F_UNLCK, &lf, F_POSIX); + if (td != NULL && fp->f_type == DTYPE_VNODE) { + struct proc *p = td->td_proc; + int pflagcopy; + if (p->p_leader != p || + p->p_peers != NULL) { + PROC_LOCK(p->p_leader); + pflagcopy = p->p_leader->p_flag; + PROC_UNLOCK(p->p_leader); + } else + pflagcopy = p->p_flag; + if ((pflagcopy & P_ADVLOCK) != 0) { + lf.l_whence = SEEK_SET; + lf.l_start = 0; + lf.l_len = 0; + lf.l_type = F_UNLCK; + vp = fp->f_data; + (void) VOP_ADVLOCK(vp, (caddr_t)td->td_proc->p_leader, + F_UNLCK, &lf, F_POSIX); + } } return (fdrop(fp, td)); } diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index f84afa89ef4b..166f1c6b72b6 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -166,6 +166,13 @@ rfork(td, uap) /* Don't allow kernel only flags. */ if ((uap->flags & RFKERNELONLY) != 0) return (EINVAL); + /* + * Don't allow sharing of file descriptor table unless + * RFTHREAD flag is supplied + */ + if ((uap->flags & (RFPROC | RFTHREAD | RFFDG | RFCFDG)) == + RFPROC) + return(EINVAL); mtx_lock(&Giant); error = fork1(td, uap->flags, 0, &p2); if (error == 0) { |
