Avoid file lock leakage when linuxthreads port or rfork is used:

- Mark the process leader as having an advisory lock
  - Check if process leader is marked as having advisory lock when
    closing file
  - Check that file is still open after lock has been obtained
  - Don't allow file descriptor table sharing between processes
    with different leaders

PR:		10265
Reviewed by:	alfred
This commit is contained in:
Tor Egge 2003-02-15 22:43:05 +00:00
parent 6f8ebcc232
commit 218a01e062
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110962
2 changed files with 58 additions and 15 deletions

View File

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

View File

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