summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoritojun <itojun@openbsd.org>2003-06-16 06:36:40 +0000
committeritojun <itojun@openbsd.org>2003-06-16 06:36:40 +0000
commitcd1e39b59e15fb65a1ae03ebde716ef9fc29dd7f (patch)
tree3bb16ac32c4655e410047a9e0953f9c996c82c1e
parentadd supported device; (diff)
downloadwireguard-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.c20
-rw-r--r--bin/systrace/intercept.c25
-rw-r--r--bin/systrace/intercept.h4
-rw-r--r--bin/systrace/lex.l50
-rw-r--r--bin/systrace/openbsd-syscalls.c7
-rw-r--r--bin/systrace/policy.c43
-rw-r--r--bin/systrace/register.c3
-rw-r--r--bin/systrace/systrace.c16
-rw-r--r--bin/systrace/systrace.h4
-rw-r--r--bin/systrace/util.c34
-rw-r--r--bin/systrace/util.h3
-rw-r--r--sys/dev/systrace.c47
-rw-r--r--sys/dev/systrace.h16
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;