diff options
author | 2003-06-16 06:36:40 +0000 | |
---|---|---|
committer | 2003-06-16 06:36:40 +0000 | |
commit | cd1e39b59e15fb65a1ae03ebde716ef9fc29dd7f (patch) | |
tree | 3bb16ac32c4655e410047a9e0953f9c996c82c1e | |
parent | add supported device; (diff) | |
download | wireguard-openbsd-cd1e39b59e15fb65a1ae03ebde716ef9fc29dd7f.tar.xz wireguard-openbsd-cd1e39b59e15fb65a1ae03ebde716ef9fc29dd7f.zip |
- limited number of processes per systrace
- escape fixes for special characters
markus, sturm ok. from provos
-rw-r--r-- | bin/systrace/filter.c | 20 | ||||
-rw-r--r-- | bin/systrace/intercept.c | 25 | ||||
-rw-r--r-- | bin/systrace/intercept.h | 4 | ||||
-rw-r--r-- | bin/systrace/lex.l | 50 | ||||
-rw-r--r-- | bin/systrace/openbsd-syscalls.c | 7 | ||||
-rw-r--r-- | bin/systrace/policy.c | 43 | ||||
-rw-r--r-- | bin/systrace/register.c | 3 | ||||
-rw-r--r-- | bin/systrace/systrace.c | 16 | ||||
-rw-r--r-- | bin/systrace/systrace.h | 4 | ||||
-rw-r--r-- | bin/systrace/util.c | 34 | ||||
-rw-r--r-- | bin/systrace/util.h | 3 | ||||
-rw-r--r-- | sys/dev/systrace.c | 47 | ||||
-rw-r--r-- | sys/dev/systrace.h | 16 |
13 files changed, 233 insertions, 39 deletions
diff --git a/bin/systrace/filter.c b/bin/systrace/filter.c index 94f815dce92..1d9c10255a7 100644 --- a/bin/systrace/filter.c +++ b/bin/systrace/filter.c @@ -1,4 +1,4 @@ -/* $OpenBSD: filter.c,v 1.26 2003/05/29 00:39:12 itojun Exp $ */ +/* $OpenBSD: filter.c,v 1.27 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -46,6 +46,7 @@ #include "intercept.h" #include "systrace.h" #include "filter.h" +#include "util.h" extern int allow; extern int noalias; @@ -171,7 +172,7 @@ filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, struct intercept_pid *icpid) { struct filter *filter, *last = NULL; - short action, laction = 0; + short action; TAILQ_FOREACH(filter, fls, next) { action = filter->match_action; @@ -198,7 +199,6 @@ filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, /* Keep track of last processed filtered in a group */ last = filter; - laction = action; } return (ICPOLICY_ASK); @@ -300,13 +300,11 @@ filter_policyrecord(struct policy *policy, struct filter *filter, const char *emulation, const char *name, char *rule) { /* Record the filter in the policy */ - if (filter == NULL) { - filter = calloc(1, sizeof(struct filter)); - if (filter == NULL) - err(1, "%s:%d: calloc", __func__, __LINE__); - if ((filter->rule = strdup(rule)) == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - } + filter = calloc(1, sizeof(struct filter)); + if (filter == NULL) + err(1, "%s:%d: calloc", __func__, __LINE__); + if ((filter->rule = strdup(rule)) == NULL) + err(1, "%s:%d: strdup", __func__, __LINE__); strlcpy(filter->name, name, sizeof(filter->name)); strlcpy(filter->emulation, emulation, sizeof(filter->emulation)); @@ -526,7 +524,7 @@ filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls, "%s%s eq \"%s\"", tl->name, lst && !strcmp(tl->name, lst) ? "[1]" : "", - l); + strescape(l)); lst = tl->name; diff --git a/bin/systrace/intercept.c b/bin/systrace/intercept.c index e5b23123d99..e1bf867753d 100644 --- a/bin/systrace/intercept.c +++ b/bin/systrace/intercept.c @@ -1,4 +1,4 @@ -/* $OpenBSD: intercept.c,v 1.39 2003/05/17 03:09:59 sturm Exp $ */ +/* $OpenBSD: intercept.c,v 1.40 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -79,6 +79,8 @@ void (*intercept_newimagecb)(int, pid_t, int, const char *, const char *, void * void *intercept_newimagecbarg = NULL; short (*intercept_gencb)(int, pid_t, int, const char *, int, const char *, void *, int, void *) = NULL; void *intercept_gencbarg = NULL; +void (*intercept_pfreecb)(int, void*); +void *intercept_pfreearg = NULL; int sccompare(struct intercept_syscall *a, struct intercept_syscall *b) @@ -225,6 +227,15 @@ intercept_register_execcb(void (*cb)(int, pid_t, int, const char *, const char * return (0); } +int +intercept_register_pfreecb(void (*cb)(int, void *), void *arg) +{ + intercept_pfreecb = cb; + intercept_pfreearg = arg; + + return (0); +} + static void sigusr1_handler(int signum) { @@ -903,3 +914,15 @@ intercept_isvalidsystemcall(char *emulation, char *name) return (res != -1); } + +/* + * Call back when a user has exhausted the number of allowed policies + * in the kernel. The kernel returns the policy number of a policy + * that has been purged. + */ + +void +intercept_policy_free(int policynr) +{ + (*intercept_pfreecb)(policynr, intercept_pfreearg); +} diff --git a/bin/systrace/intercept.h b/bin/systrace/intercept.h index 89ca11fd9fa..84fd8b49c0f 100644 --- a/bin/systrace/intercept.h +++ b/bin/systrace/intercept.h @@ -1,4 +1,4 @@ -/* $OpenBSD: intercept.h,v 1.16 2003/02/20 22:03:31 art Exp $ */ +/* $OpenBSD: intercept.h,v 1.17 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -145,6 +145,7 @@ int intercept_newpolicy(int); int intercept_assignpolicy(int, pid_t, int); int intercept_modifypolicy(int, int, const char *, const char *, short); void intercept_child_info(pid_t, pid_t); +void intercept_policy_free(int); int intercept_replace_init(struct intercept_replace *); int intercept_replace_add(struct intercept_replace *, int, u_char *, size_t); @@ -158,6 +159,7 @@ void *intercept_sccb_cbarg(char *, char *); int intercept_register_gencb(short (*)(int, pid_t, int, const char *, int, const char *, void *, int, void *), void *); int intercept_register_execcb(void (*)(int, pid_t, int, const char *, const char *, void *), void *); +int intercept_register_pfreecb(void (*)(int, void *), void *); struct intercept_translate *intercept_register_translation(char *, char *, int, struct intercept_translate *); diff --git a/bin/systrace/lex.l b/bin/systrace/lex.l index c9b24b3d659..6369e737236 100644 --- a/bin/systrace/lex.l +++ b/bin/systrace/lex.l @@ -1,4 +1,4 @@ -/* $OpenBSD: lex.l,v 1.13 2003/05/29 00:39:12 itojun Exp $ */ +/* $OpenBSD: lex.l,v 1.14 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> @@ -29,7 +29,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -%x incl +%x quote %{ #include <sys/types.h> @@ -53,6 +53,9 @@ int yylex(void); char *mystring; int myoff; +char quotestr[8192]; +int quoteescape; + #define YY_INPUT(buf,result,max_size) \ { \ int len = strlen(mystring + myoff); \ @@ -99,11 +102,44 @@ as { return AS; } ">" { return GREATER; } [\$A-Za-z][\.\(\)\/A-Za-z_\-0-9]* { yylval.string = strdup(yytext); return STRING; } [0-9]+ { yylval.number = atoi(yytext); return NUMBER; } -\"[^\"]*\" { char line[1024]; - strlcpy(line, yytext + 1, sizeof(line)); - line[strlen(line)-1] = '\0'; - yylval.string = strdup(line); - return CMDSTRING; } +\" { BEGIN(quote); + *quotestr = '\0'; + quoteescape = 0; + } +<quote>[^\\\"]+ { + if (quoteescape) { + switch (yytext[0]) { + case 'n': + yytext[0] = '\n'; + break; + case 'r': + yytext[0] = '\r'; + break; + default: + break; + } + } + strlcat(quotestr, yytext, sizeof(quotestr)); + quoteescape = 0; + } +<quote>\\ { + if (!quoteescape) + quoteescape = 1; + else { + strlcat(quotestr, "\\", sizeof(quotestr)); + quoteescape = 0; + } + } +<quote>\" { + if (!quoteescape) { + BEGIN(INITIAL); + yylval.string = strdup(quotestr); + return CMDSTRING; + } else { + strlcat(quotestr, "\"", sizeof(quotestr)); + quoteescape = 0; + } + } \[ { return LSQBRACE; } \] { return RSQBRACE; } \ { ; } diff --git a/bin/systrace/openbsd-syscalls.c b/bin/systrace/openbsd-syscalls.c index 6c188ef8f34..4cba9bcad71 100644 --- a/bin/systrace/openbsd-syscalls.c +++ b/bin/systrace/openbsd-syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: openbsd-syscalls.c,v 1.18 2002/12/04 17:40:06 mickey Exp $ */ +/* $OpenBSD: openbsd-syscalls.c,v 1.19 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -614,6 +614,11 @@ obsd_read(int fd) intercept_child_info(msg.msg_pid, msg.msg_data.msg_child.new_pid); break; +#ifdef SYSTR_MSG_POLICYFREE + case SYSTR_MSG_POLICYFREE: + intercept_policy_free(msg.msg_policy); + break; +#endif } return (0); } diff --git a/bin/systrace/policy.c b/bin/systrace/policy.c index a8be78a2f83..0600ac01830 100644 --- a/bin/systrace/policy.c +++ b/bin/systrace/policy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: policy.c,v 1.26 2003/06/02 02:03:51 itojun Exp $ */ +/* $OpenBSD: policy.c,v 1.27 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -233,6 +233,47 @@ systrace_newpolicy(const char *emulation, const char *name) return (tmp); } +void +systrace_freepolicy(struct policy *policy) +{ + struct filter *filter; + struct policy_syscall *pflq; + + if (policy->flags & POLICY_CHANGED) { + if (systrace_writepolicy(policy) == -1) + fprintf(stderr, "Failed to write policy for %s\n", + policy->name); + } + + while ((filter = TAILQ_FIRST(&policy->prefilters)) != NULL) { + TAILQ_REMOVE(&policy->prefilters, filter, policy_next); + filter_free(filter); + } + + while ((filter = TAILQ_FIRST(&policy->filters)) != NULL) { + TAILQ_REMOVE(&policy->filters, filter, policy_next); + filter_free(filter); + } + + while ((pflq = SPLAY_ROOT(&policy->pflqs)) != NULL) { + SPLAY_REMOVE(syscalltree, &policy->pflqs, pflq); + + while ((filter = TAILQ_FIRST(&pflq->flq)) != NULL) { + TAILQ_REMOVE(&pflq->flq, filter, next); + filter_free(filter); + } + + free(pflq); + } + + SPLAY_REMOVE(policytree, &policyroot, policy); + if (policy->policynr != -1) + SPLAY_REMOVE(polnrtree, &polnrroot, policy); + + free((char *)policy->name); + free(policy); +} + struct filterq * systrace_policyflq(struct policy *policy, const char *emulation, const char *name) diff --git a/bin/systrace/register.c b/bin/systrace/register.c index d68ddc22117..c21b7296491 100644 --- a/bin/systrace/register.c +++ b/bin/systrace/register.c @@ -1,4 +1,4 @@ -/* $OpenBSD: register.c,v 1.14 2003/05/17 03:09:59 sturm Exp $ */ +/* $OpenBSD: register.c,v 1.15 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -202,4 +202,5 @@ systrace_initcb(void) intercept_register_translation("linux", "chmod", 1, &ic_modeflags); X(intercept_register_execcb(execres_cb, NULL)); + X(intercept_register_pfreecb(policyfree_cb, NULL)); } diff --git a/bin/systrace/systrace.c b/bin/systrace/systrace.c index 5eaca041569..9b5bd1c2be2 100644 --- a/bin/systrace/systrace.c +++ b/bin/systrace/systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.c,v 1.42 2002/12/12 00:39:14 avsm Exp $ */ +/* $OpenBSD: systrace.c,v 1.43 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -124,7 +124,7 @@ make_output(char *output, size_t outlen, const char *binname, if (line == NULL) continue; - snprintf(p, size, ", %s: %s", tl->name, line); + snprintf(p, size, ", %s: %s", tl->name, strescape(line)); p = output + strlen(output); size = outlen - strlen(output); @@ -377,6 +377,18 @@ execres_cb(int fd, pid_t pid, int policynr, const char *emulation, fprintf(stderr, "Terminating %d: %s\n", pid, name); } +void +policyfree_cb(int policynr, void *arg) +{ + struct policy *policy; + + if ((policy = systrace_findpolnr(policynr)) == NULL) + errx(1, "%s:%d: find %d", __func__, __LINE__, + policynr); + + systrace_freepolicy(policy); +} + static void child_handler(int sig) { diff --git a/bin/systrace/systrace.h b/bin/systrace/systrace.h index 2a81d430ed8..9b676afcaef 100644 --- a/bin/systrace/systrace.h +++ b/bin/systrace/systrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.h,v 1.21 2003/05/29 00:39:12 itojun Exp $ */ +/* $OpenBSD: systrace.h,v 1.22 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -137,6 +137,7 @@ struct template *systrace_readtemplate(char *, struct policy *, struct template *); void systrace_initcb(void); struct policy *systrace_newpolicy(const char *, const char *); +void systrace_freepolicy(struct policy *); int systrace_newpolicynr(int, struct policy *); int systrace_modifypolicy(int, int, const char *, short); struct policy *systrace_findpolicy(const char *); @@ -214,6 +215,7 @@ short trans_cb(int, pid_t, int, const char *, int, const char *, void *, short gen_cb(int, pid_t, int, const char *, int, const char *, void *, int, void *); void execres_cb(int, pid_t, int, const char *, const char *, void *); +void policyfree_cb(int, void *); extern struct intercept_translate ic_oflags; extern struct intercept_translate ic_modeflags; diff --git a/bin/systrace/util.c b/bin/systrace/util.c index b6bd8b17cd2..563c2757098 100644 --- a/bin/systrace/util.c +++ b/bin/systrace/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.9 2002/10/09 03:52:10 itojun Exp $ */ +/* $OpenBSD: util.c,v 1.10 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -33,10 +33,42 @@ #include <string.h> #include <ctype.h> #include <stdio.h> +#include <err.h> #include "util.h" char * +strescape(char *str) +{ + static char escape[8192]; + int i, p; + + for (p = i = 0; i < strlen(str) && p < sizeof(escape) - 1; i++) { + char a = str[i]; + switch (a) { + case '\r': + a = 'r'; + goto doescape; + case '\n': + a = 'n'; + goto doescape; + case '\\': + case '\"': + doescape: + escape[p++] = '\\'; + if (p >= sizeof(escape) - 1) + errx(1, "%s: string too long: %s", + __func__, str); + default: + escape[p++] = a; + } + } + + escape[p] = '\0'; + return (escape); +} + +char * strrpl(char *str, size_t size, char *match, char *value) { char *p, *e; diff --git a/bin/systrace/util.h b/bin/systrace/util.h index 8e4fdb22d2a..c37315d1201 100644 --- a/bin/systrace/util.h +++ b/bin/systrace/util.h @@ -1,4 +1,4 @@ -/* $OpenBSD: util.h,v 1.2 2002/10/09 03:52:10 itojun Exp $ */ +/* $OpenBSD: util.h,v 1.3 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> @@ -34,6 +34,7 @@ #define _UTIL_H_ void simplify_path(char *); +char *strescape(char *); char *strrpl(char *, size_t, char *, char *); #endif /* !_UTIL_H_ */ diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c index 04cdb3dfa8e..d31b6914da3 100644 --- a/sys/dev/systrace.c +++ b/sys/dev/systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.c,v 1.29 2003/03/28 12:40:01 henning Exp $ */ +/* $OpenBSD: systrace.c,v 1.30 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -139,6 +139,7 @@ void systrace_closepolicy(struct fsystrace *, struct str_policy *); int systrace_insert_process(struct fsystrace *, struct proc *); struct str_policy *systrace_newpolicy(struct fsystrace *, int); int systrace_msg_child(struct fsystrace *, struct str_process *, pid_t); +int systrace_msg_policyfree(struct fsystrace *, struct str_policy *); int systrace_msg_ask(struct fsystrace *, struct str_process *, int, size_t, register_t []); int systrace_msg_result(struct fsystrace *, struct str_process *, @@ -1374,8 +1375,23 @@ systrace_newpolicy(struct fsystrace *fst, int maxents) struct str_policy *pol; int i; - if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) - return (NULL); + if (fst->npolicies > SYSTR_MAX_POLICIES && !fst->issuser) { + struct str_policy *tmp; + + /* Try to find a policy for freeing */ + TAILQ_FOREACH(tmp, &fst->policies, next) { + if (tmp->refcount == 1) + break; + } + + if (tmp == NULL) + return (NULL); + + /* Notify userland about freed policy */ + systrace_msg_policyfree(fst, tmp); + /* Free this policy */ + systrace_closepolicy(fst, tmp); + } pol = pool_get(&systr_policy_pl, PR_NOWAIT); if (pol == NULL) @@ -1490,7 +1506,7 @@ systrace_make_msg(struct str_process *strp, int type) while (1) { st = tsleep(strp, PWAIT | PCATCH, "systrmsg", 0); if (st != 0) - return (EINTR); + return (ERESTART); /* If we detach, then everything is permitted */ if ((strp = curproc->p_systrace) == NULL) return (0); @@ -1531,3 +1547,26 @@ systrace_msg_child(struct fsystrace *fst, struct str_process *strp, pid_t npid) return (0); } + +int +systrace_msg_policyfree(struct fsystrace *fst, struct str_policy *strpol) +{ + struct str_process *nstrp; + struct str_message *msg; + + nstrp = pool_get(&systr_proc_pl, PR_WAITOK); + memset(nstrp, 0, sizeof(struct str_process)); + + DPRINTF(("%s: free %d\n", __func__, strpol->nr)); + + msg = &nstrp->msg; + + msg->msg_type = SYSTR_MSG_POLICYFREE; + msg->msg_policy = strpol->nr; + + TAILQ_INSERT_TAIL(&fst->messages, nstrp, msg_next); + + systrace_wakeup(fst); + + return (0); +} diff --git a/sys/dev/systrace.h b/sys/dev/systrace.h index ddafb5d9947..fafc68721a0 100644 --- a/sys/dev/systrace.h +++ b/sys/dev/systrace.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.h,v 1.13 2003/03/28 11:52:05 mickey Exp $ */ +/* $OpenBSD: systrace.h,v 1.14 2003/06/16 06:36:40 itojun Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -62,14 +62,16 @@ struct str_msg_child { pid_t new_pid; }; -#define SYSTR_MSG_ASK 1 -#define SYSTR_MSG_RES 2 -#define SYSTR_MSG_EMUL 3 -#define SYSTR_MSG_CHILD 4 -#define SYSTR_MSG_UGID 5 +#define SYSTR_MSG_ASK 1 +#define SYSTR_MSG_RES 2 +#define SYSTR_MSG_EMUL 3 +#define SYSTR_MSG_CHILD 4 +#define SYSTR_MSG_UGID 5 +#define SYSTR_MSG_POLICYFREE 6 #define SYSTR_MSG_NOPROCESS(x) \ - ((x)->msg.msg_type == SYSTR_MSG_CHILD) + ((x)->msg.msg_type == SYSTR_MSG_CHILD || \ + (x)->msg.msg_type == SYSTR_MSG_POLICYFREE) struct str_message { int msg_type; |