Pushdown Giant for acct(), kqueue(), kevent(), execve(), fork(),
vfork(), rfork(), jail().
This commit is contained in:
parent
65efd81290
commit
116734c4d1
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user