diff options
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/systrace.c | 101 | ||||
-rw-r--r-- | sys/dev/systrace.h | 12 |
2 files changed, 99 insertions, 14 deletions
diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c index 6af4929574f..4ec62be84e0 100644 --- a/sys/dev/systrace.c +++ b/sys/dev/systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.c,v 1.36 2004/07/07 07:31:40 marius Exp $ */ +/* $OpenBSD: systrace.c,v 1.37 2004/11/07 20:39:31 marius Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -86,6 +86,12 @@ struct str_policy { u_char *sysent; }; +struct str_inject { + caddr_t kaddr; + caddr_t uaddr; + size_t len; +}; + #define STR_PROC_ONQUEUE 0x01 #define STR_PROC_WAITANSWER 0x02 #define STR_PROC_SYSCALLRES 0x04 @@ -117,11 +123,15 @@ struct str_process { uid_t saveuid; gid_t setegid; gid_t savegid; - + int isscript; char scriptname[MAXPATHLEN]; struct str_message msg; + + caddr_t sg; + struct str_inject injects[SYSTR_MAXINJECTS]; + int injectind; }; struct lock systrace_lck; @@ -145,6 +155,8 @@ int systrace_detach(struct str_process *); int systrace_answer(struct str_process *, struct systrace_answer *); int systrace_setscriptname(struct str_process *, struct systrace_scriptname *); +int systrace_prepinject(struct str_process *, struct systrace_inject *); +int systrace_inject(struct str_process *, int); int systrace_io(struct str_process *, struct systrace_io *); int systrace_policy(struct fsystrace *, struct systrace_policy *); int systrace_preprepl(struct str_process *, struct systrace_replace *); @@ -293,6 +305,11 @@ systracef_ioctl(fp, cmd, data, p) if (!pid) ret = EINVAL; break; + case STRIOCINJECT: + pid = ((struct systrace_inject *)data)->stri_pid; + if (!pid) + ret = EINVAL; + break; case STRIOCGETCWD: pid = *(pid_t *)data; if (!pid) @@ -351,6 +368,9 @@ systracef_ioctl(fp, cmd, data, p) ret = systrace_setscriptname(strp, (struct systrace_scriptname *)data); break; + case STRIOCINJECT: + ret = systrace_prepinject(strp, (struct systrace_inject *)data); + break; case STRIOCPOLICY: ret = systrace_policy(fst, (struct systrace_policy *)data); break; @@ -755,6 +775,14 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) return (error); } + /* + * Reset our stackgap allocation. Note that when resetting + * the stackgap allocation, we expect to get the same address + * base; i.e. that stackgap_init() is idempotent. + */ + systrace_inject(strp, 0 /* Just reset internal state */); + strp->sg = stackgap_init(p->p_emul); + /* Puts the current process to sleep, return unlocked */ error = systrace_msg_ask(fst, strp, code, callp->sy_argsize, v); /* lock has been released in systrace_msg_ask() */ @@ -784,12 +812,12 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) report = 1; } + error = systrace_inject(strp, 1/* Perform copies */); /* Replace the arguments if necessary */ - if (strp->replace != NULL) { + if (!error && strp->replace != NULL) error = systrace_replace(strp, callp->sy_argsize, v); - if (error) - goto out_unlock; - } + if (error) + goto out_unlock; oldemul = p->p_emul; pc = p->p_cred; @@ -879,9 +907,9 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) goto out; } - out_unlock: +out_unlock: lockmgr(&fst->lock, LK_RELEASE, NULL, curproc); - out: +out: return (error); } @@ -982,6 +1010,57 @@ systrace_setscriptname(struct str_process *strp, struct systrace_scriptname *ans } int +systrace_inject(struct str_process *strp, int docopy) +{ + int ind, ret = 0; + + for (ind = 0; ind < strp->injectind; ind++) { + struct str_inject *inject = &strp->injects[ind]; + if (!ret && docopy && + copyout(inject->kaddr, inject->uaddr, inject->len)) + ret = EINVAL; + free(inject->kaddr, M_XDATA); + } + + strp->injectind = 0; + return (ret); +} + +int +systrace_prepinject(struct str_process *strp, struct systrace_inject *inj) +{ + caddr_t udata, kaddr = NULL; + int ret = 0; + struct str_inject *inject; + + if (strp->injectind >= SYSTR_MAXINJECTS) + return (ENOBUFS); + + udata = stackgap_alloc(&strp->sg, inj->stri_len); + if (udata == NULL) + return (ENOMEM); + + /* + * We have infact forced a maximum length on stri_len because + * of the stackgap. + */ + + kaddr = malloc(inj->stri_len, M_XDATA, M_WAITOK); + ret = copyin(inj->stri_addr, kaddr, inj->stri_len); + if (ret) { + free(kaddr, M_XDATA); + return (ret); + } + + inject = &strp->injects[strp->injectind++]; + inject->kaddr = kaddr; + inject->uaddr = inj->stri_addr = udata; + inject->len = inj->stri_len; + + return (0); +} + +int systrace_policy(struct fsystrace *fst, struct systrace_policy *pol) { struct str_policy *strpol; @@ -1323,13 +1402,11 @@ systrace_replace(struct str_process *strp, size_t argsize, register_t args[]) { struct systrace_replace *repl = strp->replace; caddr_t kdata, kbase; - struct proc *p = strp->proc; - caddr_t sg, udata, ubase; + caddr_t udata, ubase; int i, maxarg, ind, ret = 0; maxarg = argsize/sizeof(register_t); - sg = stackgap_init(p->p_emul); - ubase = stackgap_alloc(&sg, repl->strr_len); + ubase = stackgap_alloc(&strp->sg, repl->strr_len); kbase = repl->strr_base; for (i = 0; i < maxarg && i < repl->strr_nrepl; i++) { diff --git a/sys/dev/systrace.h b/sys/dev/systrace.h index 3926cb9b2c0..7b063e9fa9e 100644 --- a/sys/dev/systrace.h +++ b/sys/dev/systrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.h,v 1.17 2004/07/07 07:31:40 marius Exp $ */ +/* $OpenBSD: systrace.h,v 1.18 2004/11/07 20:39:31 marius Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -52,6 +52,7 @@ struct str_msg_execve { #define SYSTR_MAX_POLICIES 64 #define SYSTR_MAXARGS 64 #define SYSTR_MAXFNAME 8 +#define SYSTR_MAXINJECTS 8 struct str_msg_ask { int code; @@ -74,7 +75,6 @@ struct str_msg_child { #define SYSTR_MSG_UGID 5 #define SYSTR_MSG_POLICYFREE 6 #define SYSTR_MSG_EXECVE 7 -#define SYSTR_MSG_SCRIPTNAME 8 #define SYSTR_MSG_NOPROCESS(x) \ ((x)->msg.msg_type == SYSTR_MSG_CHILD || \ @@ -158,6 +158,13 @@ struct systrace_replace { int32_t strr_flags[SYSTR_MAXARGS]; }; +struct systrace_inject { + /* On return, this contains the stackgap address. */ + caddr_t stri_addr; + size_t stri_len; + pid_t stri_pid; +}; + #define STRIOCCLONE _IOR('s', 100, int) #define SYSTR_CLONE STRIOCCLONE #define STRIOCATTACH _IOW('s', 101, pid_t) @@ -170,6 +177,7 @@ struct systrace_replace { #define STRIOCREPORT _IOW('s', 108, pid_t) #define STRIOCREPLACE _IOW('s', 109, struct systrace_replace) #define STRIOCSCRIPTNAME _IOW('s', 110, struct systrace_scriptname) +#define STRIOCINJECT _IOWR('s', 111, struct systrace_inject) #define SYSTR_POLICY_ASK 0 #define SYSTR_POLICY_PERMIT 1 |