avoid a panic due to recent changes in kern_fork.c; prepare for lwp by

keeping messages independent of the process itself
This commit is contained in:
provos 2003-03-30 00:40:05 +00:00
parent 44d9add676
commit cb0252af40
2 changed files with 77 additions and 55 deletions

View File

@ -1,7 +1,7 @@
/* $NetBSD: kern_systrace.c,v 1.25 2003/03/21 21:13:51 dsl Exp $ */
/* $NetBSD: kern_systrace.c,v 1.26 2003/03/30 00:40:06 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002, 2003 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.25 2003/03/21 21:13:51 dsl Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_systrace.c,v 1.26 2003/03/30 00:40:06 provos Exp $");
#include "opt_systrace.h"
@ -115,7 +115,6 @@ struct str_policy {
struct str_process {
TAILQ_ENTRY(str_process) next;
TAILQ_ENTRY(str_process) msg_next;
struct proc *proc;
const struct emul *oldemul;
@ -138,8 +137,6 @@ struct str_process {
uid_t saveuid;
gid_t setegid;
gid_t savegid;
struct str_message msg;
};
uid_t systrace_seteuid(struct proc *, uid_t);
@ -163,7 +160,8 @@ struct proc *systrace_find(struct str_process *);
struct str_process *systrace_findpid(struct fsystrace *fst, pid_t pid);
void systrace_wakeup(struct fsystrace *);
void systrace_closepolicy(struct fsystrace *, struct str_policy *);
int systrace_insert_process(struct fsystrace *, struct proc *);
int systrace_insert_process(struct fsystrace *, struct proc *,
struct str_process **);
struct str_policy *systrace_newpolicy(struct fsystrace *, int);
int systrace_msg_child(struct fsystrace *, struct str_process *, pid_t);
int systrace_msg_ask(struct fsystrace *, struct str_process *,
@ -172,7 +170,7 @@ int systrace_msg_result(struct fsystrace *, struct str_process *,
int, int, size_t, register_t [], register_t []);
int systrace_msg_emul(struct fsystrace *, struct str_process *);
int systrace_msg_ugid(struct fsystrace *, struct str_process *);
int systrace_make_msg(struct str_process *, int);
int systrace_make_msg(struct str_process *, int, struct str_message *);
static struct fileops systracefops = {
systracef_read,
@ -194,6 +192,7 @@ static struct fileops systracefops = {
struct pool systr_proc_pl;
struct pool systr_policy_pl;
struct pool systr_msgcontainer_pl;
int systrace_debug = 0;
struct lock systrace_lck;
@ -217,7 +216,7 @@ systracef_read(struct file *fp, off_t *poff, struct uio *uio,
)
{
struct fsystrace *fst = (struct fsystrace *)fp->f_data;
struct str_process *process;
struct str_msgcontainer *cont;
int error = 0;
if (uio->uio_resid != sizeof(struct str_message))
@ -227,15 +226,14 @@ systracef_read(struct file *fp, off_t *poff, struct uio *uio,
systrace_lock();
SYSTRACE_LOCK(fst, curlwp);
systrace_unlock();
if ((process = TAILQ_FIRST(&fst->messages)) != NULL) {
error = uiomove((caddr_t)&process->msg,
if ((cont = TAILQ_FIRST(&fst->messages)) != NULL) {
error = uiomove((caddr_t)&cont->msg,
sizeof(struct str_message), uio);
if (!error) {
TAILQ_REMOVE(&fst->messages, process, msg_next);
CLR(process->flags, STR_PROC_ONQUEUE);
if (SYSTR_MSG_NOPROCESS(process))
pool_put(&systr_proc_pl, process);
TAILQ_REMOVE(&fst->messages, cont, next);
if (!SYSTR_MSG_NOPROCESS(cont))
CLR(cont->strp->flags, STR_PROC_ONQUEUE);
pool_put(&systr_msgcontainer_pl, cont);
}
} else if (TAILQ_FIRST(&fst->processes) == NULL) {
@ -492,6 +490,7 @@ systracef_close(struct file *fp, struct proc *p)
{
struct fsystrace *fst = (struct fsystrace *)fp->f_data;
struct str_process *strp;
struct str_msgcontainer *cont;
struct str_policy *strpol;
systrace_lock();
@ -508,10 +507,10 @@ systracef_close(struct file *fp, struct proc *p)
}
/* Clean up fork and exit messages */
for (strp = TAILQ_FIRST(&fst->messages); strp;
strp = TAILQ_FIRST(&fst->messages)) {
TAILQ_REMOVE(&fst->messages, strp, msg_next);
pool_put(&systr_proc_pl, strp);
for (cont = TAILQ_FIRST(&fst->messages); cont;
cont = TAILQ_FIRST(&fst->messages)) {
TAILQ_REMOVE(&fst->messages, cont, next);
pool_put(&systr_msgcontainer_pl, cont);
}
/* Clean up all policies */
@ -559,6 +558,8 @@ systrace_init(void)
"strprocpl", NULL);
pool_init(&systr_policy_pl, sizeof(struct str_policy), 0, 0, 0,
"strpolpl", NULL);
pool_init(&systr_msgcontainer_pl, sizeof(struct str_msgcontainer),
0, 0, 0, "strmsgpl", NULL);
lockinit(&systrace_lck, PLOCK, "systrace", 0, 0);
}
@ -663,10 +664,11 @@ systrace_sys_fork(struct proc *oldproc, struct proc *p)
SYSTRACE_LOCK(fst, curlwp);
systrace_unlock();
if (systrace_insert_process(fst, p))
if (systrace_insert_process(fst, p, &strp)) {
/* We need to kill the child */
psignal(p, SIGKILL);
goto out;
if ((strp = systrace_findpid(fst, p->p_pid)) == NULL)
panic("systrace_fork");
}
/* Reference policy */
if ((strp->policy = oldstrp->policy) != NULL)
@ -1231,7 +1233,7 @@ systrace_attach(struct fsystrace *fst, pid_t pid)
goto out;
}
error = systrace_insert_process(fst, proc);
error = systrace_insert_process(fst, proc, NULL);
#if defined(__NetBSD__) && defined(__HAVE_SYSCALL_INTERN)
/*
@ -1389,9 +1391,6 @@ systrace_detach(struct str_process *strp)
fst = strp->parent;
systrace_wakeup(fst);
if (ISSET(strp->flags, STR_PROC_ONQUEUE))
TAILQ_REMOVE(&fst->messages, strp, msg_next);
TAILQ_REMOVE(&fst->processes, strp, next);
fst->nprocesses--;
@ -1422,7 +1421,8 @@ systrace_closepolicy(struct fsystrace *fst, struct str_policy *policy)
int
systrace_insert_process(struct fsystrace *fst, struct proc *proc)
systrace_insert_process(struct fsystrace *fst, struct proc *proc,
struct str_process **pstrp)
{
struct str_process *strp;
@ -1440,6 +1440,10 @@ systrace_insert_process(struct fsystrace *fst, struct proc *proc)
proc->p_systrace = strp;
SET(proc->p_flag, P_SYSTRACE);
/* Pass the new pointer back to the caller */
if (pstrp != NULL)
*pstrp = strp;
return (0);
}
@ -1481,7 +1485,8 @@ int
systrace_msg_ask(struct fsystrace *fst, struct str_process *strp,
int code, size_t argsize, register_t args[])
{
struct str_msg_ask *msg_ask = &strp->msg.msg_data.msg_ask;
struct str_message msg;
struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
int i;
msg_ask->code = code;
@ -1489,14 +1494,15 @@ systrace_msg_ask(struct fsystrace *fst, struct str_process *strp,
for (i = 0; i < (argsize/sizeof(register_t)) && i < SYSTR_MAXARGS; i++)
msg_ask->args[i] = args[i];
return (systrace_make_msg(strp, SYSTR_MSG_ASK));
return (systrace_make_msg(strp, SYSTR_MSG_ASK, &msg));
}
int
systrace_msg_result(struct fsystrace *fst, struct str_process *strp,
int error, int code, size_t argsize, register_t args[], register_t rval[])
{
struct str_msg_ask *msg_ask = &strp->msg.msg_data.msg_ask;
struct str_message msg;
struct str_msg_ask *msg_ask = &msg.msg_data.msg_ask;
int i;
msg_ask->code = code;
@ -1508,42 +1514,52 @@ systrace_msg_result(struct fsystrace *fst, struct str_process *strp,
msg_ask->rval[0] = rval[0];
msg_ask->rval[1] = rval[1];
return (systrace_make_msg(strp, SYSTR_MSG_RES));
return (systrace_make_msg(strp, SYSTR_MSG_RES, &msg));
}
int
systrace_msg_emul(struct fsystrace *fst, struct str_process *strp)
{
struct str_msg_emul *msg_emul = &strp->msg.msg_data.msg_emul;
struct str_message msg;
struct str_msg_emul *msg_emul = &msg.msg_data.msg_emul;
struct proc *p = strp->proc;
memcpy(msg_emul->emul, p->p_emul->e_name, SYSTR_EMULEN);
return (systrace_make_msg(strp, SYSTR_MSG_EMUL));
return (systrace_make_msg(strp, SYSTR_MSG_EMUL, &msg));
}
int
systrace_msg_ugid(struct fsystrace *fst, struct str_process *strp)
{
struct str_msg_ugid *msg_ugid = &strp->msg.msg_data.msg_ugid;
struct str_message msg;
struct str_msg_ugid *msg_ugid = &msg.msg_data.msg_ugid;
struct proc *p = strp->proc;
msg_ugid->uid = p->p_cred->p_ruid;
msg_ugid->gid = p->p_cred->p_rgid;
return (systrace_make_msg(strp, SYSTR_MSG_UGID));
return (systrace_make_msg(strp, SYSTR_MSG_UGID, &msg));
}
int
systrace_make_msg(struct str_process *strp, int type)
systrace_make_msg(struct str_process *strp, int type, struct str_message *tmsg)
{
struct str_message *msg = &strp->msg;
struct str_msgcontainer *cont;
struct str_message *msg;
struct fsystrace *fst = strp->parent;
#ifndef __NetBSD__
struct proc *p = strp->proc;
#endif
int st;
cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
memset(cont, 0, sizeof(struct str_msgcontainer));
cont->strp = strp;
msg = &cont->msg;
/* Copy the already filled in fields */
memcpy(&msg->msg_data, &tmsg->msg_data, sizeof(msg->msg_data));
/* Add the extra fields to the message */
msg->msg_seqnr = ++strp->seqnr;
msg->msg_type = type;
msg->msg_pid = strp->pid;
@ -1556,18 +1572,14 @@ systrace_make_msg(struct str_process *strp, int type)
if (ISSET(strp->flags, STR_PROC_ONQUEUE))
goto out;
TAILQ_INSERT_TAIL(&fst->messages, strp, msg_next);
TAILQ_INSERT_TAIL(&fst->messages, cont, next);
SET(strp->flags, STR_PROC_ONQUEUE);
out:
systrace_wakeup(fst);
/* Release the lock - XXX */
#ifndef __NetBSD__
SYSTRACE_UNLOCK(fst, p);
#else
SYSTRACE_UNLOCK(fst, strp->proc);
#endif
while (1) {
st = tsleep(strp, PWAIT | PCATCH, "systrmsg", 0);
@ -1586,17 +1598,19 @@ systrace_make_msg(struct str_process *strp, int type)
int
systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid)
{
struct str_process *nstrp;
struct str_msgcontainer *cont;
struct str_message *msg;
struct str_msg_child *msg_child;
nstrp = pool_get(&systr_proc_pl, PR_WAITOK);
memset(nstrp, 0, sizeof(struct str_process));
cont = pool_get(&systr_msgcontainer_pl, PR_WAITOK);
memset(cont, 0, sizeof(struct str_msgcontainer));
cont->strp = strp;
msg = &cont->msg;
DPRINTF(("%s: %p: pid %d -> pid %d\n", __func__,
nstrp, strp->pid, npid));
msg, strp->pid, npid));
msg = &nstrp->msg;
msg_child = &msg->msg_data.msg_child;
msg->msg_type = SYSTR_MSG_CHILD;
@ -1607,7 +1621,7 @@ systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid)
msg->msg_policy = -1;
msg_child->new_pid = npid;
TAILQ_INSERT_TAIL(&fst->messages, nstrp, msg_next);
TAILQ_INSERT_TAIL(&fst->messages, cont, next);
systrace_wakeup(fst);

View File

@ -1,4 +1,4 @@
/* $NetBSD: systrace.h,v 1.8 2002/11/10 14:01:57 fvdl Exp $ */
/* $NetBSD: systrace.h,v 1.9 2003/03/30 00:40:05 provos Exp $ */
/*
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
@ -87,6 +87,15 @@ struct str_message {
} msg_data;
};
struct str_process;
struct str_msgcontainer {
TAILQ_ENTRY(str_msgcontainer) next;
struct str_process *strp;
struct str_message msg;
};
struct systrace_answer {
pid_t stra_pid;
u_int16_t stra_seqnr;
@ -165,7 +174,6 @@ struct systrace_replace {
#define ISSET(t, f) ((t) & (f))
#define CLR(t, f) ((t) &= ~(f))
struct str_process;
struct fsystrace {
struct lock lock;
struct selinfo si;
@ -175,7 +183,7 @@ struct fsystrace {
TAILQ_HEAD(strpolicyq, str_policy) policies;
struct strprocessq messages;
TAILQ_HEAD(strmessageq, str_msgcontainer) messages;
size_t npolicynr;
size_t npolicies;