Pushdown Giant for acct(), kqueue(), kevent(), execve(), fork(),

vfork(), rfork(), jail().
This commit is contained in:
Matthew Dillon 2001-09-01 03:04:31 +00:00
parent 65efd81290
commit 116734c4d1
5 changed files with 70 additions and 23 deletions

View File

@ -106,6 +106,8 @@ SYSCTL_INT(_kern, OID_AUTO, acct_chkfreq, CTLFLAG_RW,
/*
* Accounting system call. Written based on the specification and
* previous implementation done by Mark Tinguely.
*
* MPSAFE
*/
int
acct(a1, uap)
@ -118,10 +120,12 @@ acct(a1, uap)
struct nameidata nd;
int error, flags;
mtx_lock(&Giant);
/* Make sure that the caller is root. */
error = suser(p);
if (error)
return (error);
goto done2;
/*
* If accounting is to be started to a file, open that file for
@ -133,12 +137,13 @@ acct(a1, uap)
flags = FWRITE;
error = vn_open(&nd, &flags, 0);
if (error)
return (error);
goto done2;
NDFREE(&nd, NDF_ONLY_PNBUF);
VOP_UNLOCK(nd.ni_vp, 0, p);
if (nd.ni_vp->v_type != VREG) {
vn_close(nd.ni_vp, FWRITE, p->p_ucred, p);
return (EACCES);
error = EACCES;
goto done2;
}
}
@ -153,7 +158,7 @@ acct(a1, uap)
acctp = savacctp = NULLVP;
}
if (SCARG(uap, path) == NULL)
return (error);
goto done2;
/*
* Save the new accounting file vnode, and schedule the new
@ -162,6 +167,8 @@ acct(a1, uap)
acctp = nd.ni_vp;
callout_init(&acctwatch_callout, 0);
acctwatch(NULL);
done2:
mtx_unlock(&Giant);
return (error);
}

View File

@ -331,17 +331,22 @@ filt_timer(struct knote *kn, long hint)
return (kn->kn_data != 0);
}
/*
* MPSAFE
*/
int
kqueue(struct proc *p, struct kqueue_args *uap)
{
struct filedesc *fdp = p->p_fd;
struct filedesc *fdp;
struct kqueue *kq;
struct file *fp;
int fd, error;
mtx_lock(&Giant);
fdp = p->p_fd;
error = falloc(p, &fp, &fd);
if (error)
return (error);
goto done2;
fp->f_flag = FREAD | FWRITE;
fp->f_type = DTYPE_KQUEUE;
fp->f_ops = &kqueueops;
@ -352,6 +357,8 @@ kqueue(struct proc *p, struct kqueue_args *uap)
if (fdp->fd_knlistsize < 0)
fdp->fd_knlistsize = 0; /* this process has a kq */
kq->kq_fdp = fdp;
done2:
mtx_unlock(&Giant);
return (error);
}
@ -365,21 +372,27 @@ struct kevent_args {
const struct timespec *timeout;
};
#endif
/*
* MPSAFE
*/
int
kevent(struct proc *p, struct kevent_args *uap)
{
struct filedesc* fdp = p->p_fd;
struct filedesc *fdp;
struct kevent *kevp;
struct kqueue *kq;
struct file *fp = NULL;
struct timespec ts;
int i, n, nerrors, error;
mtx_lock(&Giant);
fdp = p->p_fd;
if (((u_int)uap->fd) >= fdp->fd_nfiles ||
(fp = fdp->fd_ofiles[uap->fd]) == NULL ||
(fp->f_type != DTYPE_KQUEUE))
return (EBADF);
(fp->f_type != DTYPE_KQUEUE)) {
error = EBADF;
goto done;
}
fhold(fp);
if (uap->timeout != NULL) {
@ -430,6 +443,7 @@ kevent(struct proc *p, struct kevent_args *uap)
done:
if (fp != NULL)
fdrop(fp, p);
mtx_unlock(&Giant);
return (error);
}

View File

@ -98,6 +98,8 @@ struct execve_args {
/*
* execve() system call.
*
* MPSAFE
*/
int
execve(p, uap)
@ -133,6 +135,8 @@ execve(p, uap)
imgp->ps_strings = 0;
imgp->auxarg_size = 0;
mtx_lock(&Giant);
/*
* Allocate temporary demand zeroed space for argument and
* environment strings
@ -445,17 +449,18 @@ execve(p, uap)
}
if (error == 0)
return (0);
goto done2;
exec_fail:
if (imgp->vmspace_destroyed) {
/* sorry, no more process anymore. exit gracefully */
exit1(p, W_EXITCODE(0, SIGABRT));
/* NOT REACHED */
return(0);
} else {
return(error);
}
error = 0;
}
done2:
mtx_unlock(&Giant);
return(error);
}
int

View File

@ -105,6 +105,9 @@ init_fork_list(void *data __unused)
}
SYSINIT(fork_list, SI_SUB_INTRINSIC, SI_ORDER_ANY, init_fork_list, NULL);
/*
* MPSAFE
*/
/* ARGSUSED */
int
fork(p, uap)
@ -114,14 +117,19 @@ fork(p, uap)
int error;
struct proc *p2;
mtx_lock(&Giant);
error = fork1(p, RFFDG | RFPROC, &p2);
if (error == 0) {
p->p_retval[0] = p2->p_pid;
p->p_retval[1] = 0;
}
mtx_unlock(&Giant);
return error;
}
/*
* MPSAFE
*/
/* ARGSUSED */
int
vfork(p, uap)
@ -131,14 +139,19 @@ vfork(p, uap)
int error;
struct proc *p2;
mtx_lock(&Giant);
error = fork1(p, RFFDG | RFPROC | RFPPWAIT | RFMEM, &p2);
if (error == 0) {
p->p_retval[0] = p2->p_pid;
p->p_retval[1] = 0;
}
mtx_unlock(&Giant);
return error;
}
/*
* MPSAFE
*/
int
rfork(p, uap)
struct proc *p;
@ -148,11 +161,13 @@ rfork(p, uap)
struct proc *p2;
/* mask kernel only flags out of the user flags */
mtx_lock(&Giant);
error = fork1(p, uap->flags & ~RFKERNELONLY, &p2);
if (error == 0) {
p->p_retval[0] = p2 ? p2->p_pid : 0;
p->p_retval[1] = 0;
}
mtx_unlock(&Giant);
return error;
}
@ -753,12 +768,8 @@ fork_return(p, frame)
userret(p, frame, 0);
#ifdef KTRACE
if (KTRPOINT(p, KTR_SYSRET)) {
if (!mtx_owned(&Giant))
mtx_lock(&Giant);
ktrsysret(p->p_tracep, SYS_fork, 0, 0);
}
#endif
if (mtx_owned(&Giant))
mtx_unlock(&Giant);
mtx_assert(&Giant, MA_NOTOWNED);
}

View File

@ -44,6 +44,9 @@ SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
&jail_sysvipc_allowed, 0,
"Processes in jail can use System V IPC primitives");
/*
* MPSAFE
*/
int
jail(p, uap)
struct proc *p;
@ -56,15 +59,19 @@ jail(p, uap)
struct jail j;
struct chroot_args ca;
mtx_lock(&Giant);
/* Implicitly fail if already in jail. */
error = suser(p);
if (error)
return (error);
goto done2;
error = copyin(uap->jail, &j, sizeof j);
if (error)
return (error);
if (j.version != 0)
return (EINVAL);
goto done2;
if (j.version != 0) {
error = EINVAL;
goto done2;
}
MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
if (error)
@ -79,10 +86,13 @@ jail(p, uap)
p->p_ucred = crcopy(p->p_ucred);
p->p_ucred->cr_prison = pr;
pr->pr_ref = 1;
mtx_unlock(&Giant);
return (0);
bail:
FREE(pr, M_PRISON);
done2:
mtx_unlock(&Giant);
return (error);
}