diff options
author | marius eriksen <marius@cvs.openbsd.org> | 2004-11-07 20:39:32 +0000 |
---|---|---|
committer | marius eriksen <marius@cvs.openbsd.org> | 2004-11-07 20:39:32 +0000 |
commit | c95753471734848d40f6959da38867a89ad78cf7 (patch) | |
tree | 0131e6973d46999b95e124da11f3be34c63cb092 /sys/dev | |
parent | 025bfd95b1c7beb6d9b7e9e54b55e87a79282c81 (diff) |
add a new message: inject. this allows the tracer to to inject buffers into
the stackgap. this in turn allows for argument replacement with indirection.
for example replacing an entire envp or struct pollfd.
ok provos@ millert@
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 |