diff options
author | 2016-04-25 19:09:24 +0000 | |
---|---|---|
committer | 2016-04-25 19:09:24 +0000 | |
commit | 3d79448d119e42e1c033c386d497cd7418738986 (patch) | |
tree | 0c03c5118480797b5b9611f0965c6efc0f1100e5 | |
parent | unlink systrace from the build. pledge is the glorious future that awaits. (diff) | |
download | wireguard-openbsd-3d79448d119e42e1c033c386d497cd7418738986.tar.xz wireguard-openbsd-3d79448d119e42e1c033c386d497cd7418738986.zip |
boom goes the dynamite
-rw-r--r-- | bin/systrace/Makefile | 17 | ||||
-rw-r--r-- | bin/systrace/alias.c | 200 | ||||
-rw-r--r-- | bin/systrace/cradle.c | 386 | ||||
-rw-r--r-- | bin/systrace/filter.c | 868 | ||||
-rw-r--r-- | bin/systrace/filter.h | 40 | ||||
-rw-r--r-- | bin/systrace/intercept-translate.c | 445 | ||||
-rw-r--r-- | bin/systrace/intercept.c | 1172 | ||||
-rw-r--r-- | bin/systrace/intercept.h | 218 | ||||
-rw-r--r-- | bin/systrace/lex.l | 162 | ||||
-rw-r--r-- | bin/systrace/openbsd-syscalls.c | 651 | ||||
-rw-r--r-- | bin/systrace/parse.y | 524 | ||||
-rw-r--r-- | bin/systrace/policy.c | 907 | ||||
-rw-r--r-- | bin/systrace/register.c | 273 | ||||
-rw-r--r-- | bin/systrace/systrace-errno.h | 128 | ||||
-rw-r--r-- | bin/systrace/systrace-error.c | 156 | ||||
-rw-r--r-- | bin/systrace/systrace-translate.c | 606 | ||||
-rw-r--r-- | bin/systrace/systrace.1 | 358 | ||||
-rw-r--r-- | bin/systrace/systrace.c | 826 | ||||
-rw-r--r-- | bin/systrace/systrace.h | 250 | ||||
-rw-r--r-- | bin/systrace/util.c | 213 | ||||
-rw-r--r-- | bin/systrace/util.h | 40 |
21 files changed, 0 insertions, 8440 deletions
diff --git a/bin/systrace/Makefile b/bin/systrace/Makefile deleted file mode 100644 index a614d8c68e8..00000000000 --- a/bin/systrace/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -# $OpenBSD: Makefile,v 1.16 2016/03/01 16:26:06 naddy Exp $ - -PROG= systrace -CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../sys -CFLAGS+=-Wall -Wstrict-prototypes -Wmissing-prototypes -Wpointer-arith \ - -Wno-uninitialized -CFLAGS+=-DYY_NO_UNPUT -DPADD+= ${LIBEVENT} -LDADD+= -levent - -SRCS= cradle.c filter.c intercept-translate.c intercept.c \ - openbsd-syscalls.c util.c \ - policy.c systrace-errno.h systrace-error.c \ - systrace-translate.c systrace.c alias.c register.c \ - parse.y lex.l - -.include <bsd.prog.mk> diff --git a/bin/systrace/alias.c b/bin/systrace/alias.c deleted file mode 100644 index ba874342705..00000000000 --- a/bin/systrace/alias.c +++ /dev/null @@ -1,200 +0,0 @@ -/* $OpenBSD: alias.c,v 1.7 2014/11/16 22:09:21 guenther Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/tree.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <grp.h> -#include <stdio.h> -#include <fcntl.h> -#include <ctype.h> -#include <err.h> - -#include "intercept.h" -#include "systrace.h" - -static SPLAY_HEAD(alitr, systrace_alias) aliasroot; -static SPLAY_HEAD(revtr, systrace_revalias) revroot; - -static int aliascompare(struct systrace_alias *, struct systrace_alias *); -static int revcompare(struct systrace_revalias *, struct systrace_revalias *); - -static int -aliascompare(struct systrace_alias *a, struct systrace_alias *b) -{ - int diff; - - diff = strcmp(a->emulation, b->emulation); - if (diff) - return (diff); - return (strcmp(a->name, b->name)); -} - -static int -revcompare(struct systrace_revalias *a, struct systrace_revalias *b) -{ - int diff; - - diff = strcmp(a->emulation, b->emulation); - if (diff) - return (diff); - return (strcmp(a->name, b->name)); -} - -SPLAY_PROTOTYPE(alitr, systrace_alias, node, aliascompare) -SPLAY_GENERATE(alitr, systrace_alias, node, aliascompare) - -SPLAY_PROTOTYPE(revtr, systrace_revalias, node, revcompare) -SPLAY_GENERATE(revtr, systrace_revalias, node, revcompare) - -int -systrace_initalias(void) -{ - SPLAY_INIT(&aliasroot); - SPLAY_INIT(&revroot); - - return (0); -} - -struct systrace_alias * -systrace_find_alias(const char *emulation, const char *name) -{ - struct systrace_alias tmp; - - strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation)); - strlcpy(tmp.name, name, sizeof(tmp.name)); - - return (SPLAY_FIND(alitr, &aliasroot, &tmp)); -} - -struct systrace_revalias * -systrace_find_reverse(const char *emulation, const char *name) -{ - struct systrace_revalias tmp; - - strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation)); - strlcpy(tmp.name, name, sizeof(tmp.name)); - - return (SPLAY_FIND(revtr, &revroot, &tmp)); -} - -struct systrace_revalias * -systrace_reverse(const char *emulation, const char *name) -{ - struct systrace_revalias tmp, *reverse; - - strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation)); - strlcpy(tmp.name, name, sizeof(tmp.name)); - - reverse = SPLAY_FIND(revtr, &revroot, &tmp); - if (reverse != NULL) - return (reverse); - - reverse = calloc(1, sizeof(*reverse)); - if (reverse == NULL) - err(1, "%s: %s-%s: malloc", __func__, emulation, name); - - strlcpy(reverse->emulation, emulation, sizeof(reverse->emulation)); - strlcpy(reverse->name, name, sizeof(reverse->name)); - - TAILQ_INIT(&reverse->revl); - - if (SPLAY_INSERT(revtr, &revroot, reverse) != NULL) - errx(1, "%s: %s-%s: double revalias", - __func__, emulation, name); - - return (reverse); -} - -struct systrace_alias * -systrace_new_alias(const char *emulation, const char *name, - char *aemul, char *aname) -{ - struct systrace_alias *alias; - struct systrace_revalias *reverse; - - alias = malloc(sizeof(*alias)); - if (alias == NULL) - err(1, "%s: %s-%s: malloc", __func__, emulation, name); - - strlcpy(alias->emulation, emulation, sizeof(alias->emulation)); - strlcpy(alias->name, name, sizeof(alias->name)); - strlcpy(alias->aemul, aemul, sizeof(alias->aemul)); - strlcpy(alias->aname, aname, sizeof(alias->aname)); - alias->nargs = 0; - - if (SPLAY_INSERT(alitr, &aliasroot, alias) != NULL) - errx(1, "%s: %s-%s: double alias", __func__, emulation, name); - - reverse = systrace_reverse(aemul, aname); - alias->reverse = reverse; - TAILQ_INSERT_TAIL(&reverse->revl, alias, next); - - return (alias); -} - -void -systrace_switch_alias(const char *emulation, const char *name, - char *aemul, char *aname) -{ - struct systrace_alias *alias; - struct systrace_revalias *reverse; - - if ((alias = systrace_find_alias(emulation, name)) == NULL) - errx(1, "%s: unknown alias %s-%s", __func__, emulation, name); - - /* Switch to a different alias */ - reverse = alias->reverse; - TAILQ_REMOVE(&reverse->revl, alias, next); - - strlcpy(alias->aemul, aemul, sizeof(alias->aemul)); - strlcpy(alias->aname, aname, sizeof(alias->aname)); - - reverse = systrace_reverse(aemul, aname); - alias->reverse = reverse; - TAILQ_INSERT_TAIL(&reverse->revl, alias, next); -} - -/* Add an already translated argument to this alias */ - -void -systrace_alias_add_trans(struct systrace_alias *alias, - struct intercept_translate *tl) -{ - if (alias->nargs >= SYSTRACE_MAXALIAS) - errx(1, "%s: too many arguments", __func__); - - alias->arguments[alias->nargs++] = tl; -} diff --git a/bin/systrace/cradle.c b/bin/systrace/cradle.c deleted file mode 100644 index d7bc1c38fce..00000000000 --- a/bin/systrace/cradle.c +++ /dev/null @@ -1,386 +0,0 @@ -/* $OpenBSD: cradle.c,v 1.9 2015/09/29 20:11:36 tedu Exp $ */ - -/* - * Copyright (c) 2003 Marius Aamodt Eriksen <marius@monkey.org> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <sys/un.h> -#include <sys/queue.h> -#include <sys/tree.h> - -#include <netinet/in.h> - -#include <err.h> -#include <errno.h> -#include <event.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -#include <signal.h> -#include <unistd.h> -#include <limits.h> - -#include "intercept.h" -#include "systrace.h" - -extern int connected; -extern char dirpath[]; - -static struct event listen_ev; -static struct event uilisten_ev; - -static int cradle_server(char *, char *, char *); -static void listen_cb(int, short, void *); -static void msg_cb(int, short, void *); -static void ui_cb(int, short, void *); -static void gensig_cb(int, short, void *); - -static FILE *ui_fl = NULL; -static struct event ui_ev, sigterm_ev, sigint_ev; -static char buffer[4096]; -static char *xuipath, *xpath; -static volatile int got_sigusr1 = 0; - -struct client { - struct event ev; - FILE *fl; - int buffered; - TAILQ_ENTRY(client) next; -}; - -TAILQ_HEAD(client_head, client) clientq; - -/* fake signal handler */ -/* ARGSUSED */ -static void -sigusr1_handler(int sig) -{ - got_sigusr1 = 1; -} - -/* ARGSUSED */ -static void -gensig_cb(int sig, short ev, void *data) -{ - unlink(xpath); - unlink(xuipath); - - rmdir(dirpath); - - exit(1); -} - -static int -mkunserv(char *path) -{ - int s; - mode_t old_umask; - struct sockaddr_un sun; - - if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) - err(1, "socket()"); - - memset(&sun, 0, sizeof (sun)); - sun.sun_family = AF_UNIX; - - if (strlcpy(sun.sun_path, path, sizeof (sun.sun_path)) >= - sizeof (sun.sun_path)) - errx(1, "Path too long: %s", path); - - old_umask = umask(S_IRUSR | S_IWUSR); - if (bind(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) - err(1, "bind()"); - umask(old_umask); - - if (chmod(path, S_IRUSR | S_IWUSR) == -1) - err(1, "chmod()"); - - if (listen(s, 10) == -1) - err(1, "listen()"); - - return (s); -} - -static int -cradle_server(char *path, char *uipath, char *guipath) -{ - int s, uis; - pid_t pid, newpid; - sigset_t none, set, oldset; - sig_t oldhandler; - - sigemptyset(&none); - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &set, &oldset) == -1) - err(1, "sigprocmask()"); - oldhandler = signal(SIGUSR1, sigusr1_handler); - if (oldhandler == SIG_ERR) - err(1, "signal()"); - - xpath = path; - xuipath = uipath; - - pid = getpid(); - newpid = fork(); - - switch (newpid) { - case -1: - err(1, "fork()"); - case 0: - break; - default: - /* - * Parent goes to sleep waiting for server to start. - * When it wakes up, we can start the GUI. - */ - sigsuspend(&none); - if (signal(SIGUSR1, oldhandler) == SIG_ERR) - err(1, "signal()"); - if (sigprocmask(SIG_SETMASK, &oldset, NULL) == -1) - err(1, "sigprocmask()"); - if (got_sigusr1) { - requestor_start(guipath, 1); - return (0); - } else - return (-1); - } - - setsid(); - setproctitle("cradle server for UID %d", getuid()); - - TAILQ_INIT(&clientq); - - event_init(); - - s = mkunserv(path); - uis = mkunserv(uipath); - - signal_set(&sigterm_ev, SIGTERM, gensig_cb, NULL); - if (signal_add(&sigterm_ev, NULL) == -1) - err(1, "signal_add()"); - - signal_set(&sigint_ev, SIGINT, gensig_cb, NULL); - if (signal_add(&sigint_ev, NULL) == -1) - err(1, "signal_add()"); - - event_set(&listen_ev, s, EV_READ, listen_cb, NULL); - if (event_add(&listen_ev, NULL) == -1) - err(1, "event_add()"); - - event_set(&uilisten_ev, uis, EV_READ, listen_cb, &listen_cb); - if (event_add(&uilisten_ev, NULL) == -1) - err(1, "event_add()"); - - kill(pid, SIGUSR1); - - event_dispatch(); - errx(1, "event_dispatch()"); - /* NOTREACHED */ - /* gcc fodder */ - return (-1); -} - -void -cradle_start(char *path, char *uipath, char *guipath) -{ - int s; - struct sockaddr_un sun; - - s = socket(AF_UNIX, SOCK_STREAM, 0); - if (s == -1) - err(1, "socket()"); - - memset(&sun, 0, sizeof(sun)); - sun.sun_family = AF_UNIX; - - if (strlcpy(sun.sun_path, path, sizeof (sun.sun_path)) >= - sizeof (sun.sun_path)) - errx(1, "Path too long: %s", path); - - while (connect(s, (struct sockaddr *)&sun, sizeof(sun)) == -1) { - if (errno != ENOENT) - err(1, "connect()"); - - if (cradle_server(path, uipath, guipath) == -1) - errx(1, "failed contacting or starting cradle server"); - } - - if (dup2(s, fileno(stdin)) == -1) - err(1, "dup2"); - if (dup2(s, fileno(stdout)) == -1) - err(1, "dup2"); - setvbuf(stdout, NULL, _IOLBF, 0); - - connected = 1; -} - -/* ARGSUSED */ -static void -listen_cb(int fd, short which, void *arg) -{ - int s, ui = arg != NULL; - struct sockaddr sa; - struct client *cli; - socklen_t salen = sizeof(sa); - struct event *ev; - - s = accept(fd, &sa, &salen); - if (s == -1) { - if (errno != EINTR && errno != EWOULDBLOCK && - errno != ECONNABORTED) - warn("accept()"); - goto out; - } - - if (ui) { - if (ui_fl != NULL) - goto out; - - if ((ui_fl = fdopen(s, "w+")) == NULL) - err(1, "fdopen()"); - setvbuf(ui_fl, NULL, _IONBF, 0); - event_set(&ui_ev, s, EV_READ | EV_PERSIST, ui_cb, NULL); - - /* Dequeue UI-pending events */ - while ((cli = TAILQ_FIRST(&clientq)) != NULL) { - TAILQ_REMOVE(&clientq, cli, next); - msg_cb(fileno(cli->fl), EV_READ, cli); - if (ui_fl == NULL) - break; - } - - if (event_add(&ui_ev, NULL) == -1) - err(1, "event_add()"); - } else { - if ((cli = calloc(1, sizeof(*cli))) == NULL) - err(1, "calloc()"); - - if ((cli->fl = fdopen(s, "w+")) == NULL) - err(1, "fdopen()"); - - setvbuf(cli->fl, NULL, _IONBF, 0); - event_set(&cli->ev, s, EV_READ, msg_cb, cli); - if (event_add(&cli->ev, NULL) == -1) - err(1, "event_add()"); - } - out: - ev = ui ? &uilisten_ev : &listen_ev; - if (event_add(ev, NULL) == -1) - err(1, "event_add()"); -} - -/* ARGSUSED */ -static void -msg_cb(int fd, short which, void *arg) -{ - struct client *cli = arg; - char line[4096]; - - if (ui_fl == NULL) { - TAILQ_INSERT_TAIL(&clientq, cli, next); - return; - } - - /* Policy question from systrace */ - if (!cli->buffered) - if (fgets(buffer, sizeof(buffer), cli->fl) == NULL) - goto out_eof; - cli->buffered = 0; - - if (fputs(buffer, ui_fl) == EOF) - goto out_uieof0; - again_answer: - /* Policy answer from UI */ - if (fgets(line, sizeof(line), ui_fl) == NULL) - goto out_uieof0; - if (fputs(line, cli->fl) == EOF) - goto out_eof; - /* Status from systrace */ - while (1) { - if (fgets(line, sizeof(line), cli->fl) == NULL) - goto out_eof; - if (fputs(line, ui_fl) == EOF) - goto out_uieof1; - if (strcmp(line, "WRONG\n") == 0) - goto again_answer; - if (strcmp(line, "OKAY\n") == 0) - break; - } - - out_event: - if (event_add(&cli->ev, NULL) == -1) - err(1, "event_add()"); - return; - - out_eof: - fclose(cli->fl); - free(cli); - return; - - out_uieof0: - fclose(ui_fl); - ui_fl = NULL; - cli->buffered = 1; - TAILQ_INSERT_HEAD(&clientq, cli, next); - return; - - out_uieof1: - fclose(ui_fl); - ui_fl = NULL; - while (1) { - /* We have a line coming in... */ - if (strcmp(line, "WRONG\n") == 0) - if (fputs("kill\n", cli->fl) == EOF) - goto out_eof; - if (strcmp(line, "OKAY\n") == 0) - break; - if (fgets(line, sizeof(line), cli->fl) == NULL) - goto out_eof; - } - - goto out_event; -} - -/* - * Hack to catch "idle" EOFs from the UI - */ -/* ARGSUSED */ -static void -ui_cb(int fd, short which, void *arg) -{ - char c; - - fread(&c, sizeof(c), 1, ui_fl); - - if (feof(ui_fl)) { - ui_fl = NULL; - event_del(&ui_ev); - } else - warnx("Junk from UI"); -} diff --git a/bin/systrace/filter.c b/bin/systrace/filter.c deleted file mode 100644 index 32dd8b2dc01..00000000000 --- a/bin/systrace/filter.c +++ /dev/null @@ -1,868 +0,0 @@ -/* $OpenBSD: filter.c,v 1.37 2015/12/09 19:36:17 mmcc Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/tree.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <regex.h> -#include <errno.h> -#include <fnmatch.h> -#include <err.h> - -#include "intercept.h" -#include "systrace.h" -#include "filter.h" -#include "util.h" - -extern int allow; -extern int noalias; -extern int connected; -extern int cradle; -extern char cwd[]; -extern char home[]; -extern char username[]; -extern char *guipath; - -int requestor_restart = 0; - -static void logic_free(struct logic *); -static int filter_match(struct intercept_pid *, struct intercept_tlq *, - struct logic *); -static void filter_review(struct filterq *); -static void filter_templates(const char *); -static int filter_template(int, struct policy *, int); -static int filter_quickpredicate(struct filter *); -static void filter_policyrecord(struct policy *, struct filter *, const char *, - const char *, char *); -static void filter_replace(char *, size_t, char *, char *); - -static int -filter_match(struct intercept_pid *icpid, struct intercept_tlq *tls, - struct logic *logic) -{ - struct intercept_translate *tl; - int off = 0, res; - - switch (logic->op) { - case LOGIC_NOT: - return (!filter_match(icpid, tls, logic->left)); - case LOGIC_OR: - if (filter_match(icpid, tls, logic->left)) - return (1); - return (filter_match(icpid, tls, logic->right)); - case LOGIC_AND: - if (!filter_match(icpid, tls, logic->left)) - return (0); - return (filter_match(icpid, tls, logic->right)); - default: - break; - } - - /* Now we just have a logic single */ - if (logic->type == NULL) - goto match; - - if (tls == NULL) - errx(1, "filter_match has no translators"); - - TAILQ_FOREACH(tl, tls, next) { - if (!tl->trans_valid) - continue; - - if (strcasecmp(tl->name, logic->type)) - continue; - - if (logic->typeoff == -1 || logic->typeoff == off) - break; - - off++; - } - - if (tl == NULL) - return (0); - - match: - /* We need to do dynamic expansion on the data */ - if (logic->filterdata && (logic->flags & LOGIC_NEEDEXPAND)) { - char *old = logic->filterdata; - size_t oldlen = logic->filterlen; - - logic->filterdata = filter_dynamicexpand(icpid, old); - logic->filterlen = strlen(logic->filterdata) + 1; - - res = logic->filter_match(tl, logic); - - logic->filterdata = old; - logic->filterlen = oldlen; - } else - res = logic->filter_match(tl, logic); - - return (res); -} - -/* Evaluate filter predicate */ - -int -filter_predicate(struct intercept_pid *icpid, struct predicate *pdc) -{ - id_t pidnr, pdcnr; - int res = 0; - - if (!pdc->p_flags) - return (1); - - if (pdc->p_flags & PREDIC_UID) { - pidnr = icpid->uid; - pdcnr = pdc->p_uid; - } else { - pidnr = icpid->gid; - pdcnr = pdc->p_gid; - } - - switch (pdc->p_flags & PREDIC_MASK) { - case PREDIC_NEGATIVE: - res = pidnr != pdcnr; - break; - case PREDIC_LESSER: - res = pidnr < pdcnr; - break; - case PREDIC_GREATER: - res = pidnr > pdcnr; - break; - default: - res = pidnr == pdcnr; - break; - } - - return (res); -} - -short -filter_evaluate(struct intercept_tlq *tls, struct filterq *fls, - struct intercept_pid *icpid) -{ - struct filter *filter, *last = NULL; - short action; - - TAILQ_FOREACH(filter, fls, next) { - action = filter->match_action; - - if (filter_predicate(icpid, &filter->match_predicate) && - filter_match(icpid, tls, filter->logicroot)) { - /* Profile feedback optimization */ - filter->match_count++; - if (last != NULL && last->match_action == action && - last->match_flags == filter->match_flags && - filter->match_count > last->match_count) { - TAILQ_REMOVE(fls, last, next); - TAILQ_INSERT_AFTER(fls, filter, last, next); - } - - if (action == ICPOLICY_NEVER) - action = filter->match_error; - icpid->uflags = filter->match_flags; - - /* Policy requests privilege elevation */ - if (filter->elevate.e_flags) - icpid->elevate = &filter->elevate; - return (action); - } - - /* Keep track of last processed filtered in a group */ - last = filter; - } - - return (ICPOLICY_ASK); -} - -static void -logic_free(struct logic *logic) -{ - if (logic->left) - logic_free(logic->left); - if (logic->right) - logic_free(logic->right); - free(logic->type); - free(logic->filterdata); - free(logic); -} - -void -filter_free(struct filter *filter) -{ - if (filter->logicroot) - logic_free(filter->logicroot); - free(filter->rule); - free(filter); -} - -static void -filter_review(struct filterq *fls) -{ - struct filter *filter; - int i = 0; - - printf("Filter review:\n"); - - TAILQ_FOREACH(filter, fls, next) { - i++; - printf("%d. %s\n", i, filter->rule); - } -} - -static void -filter_templates(const char *emulation) -{ - extern struct tmplqueue templates; - struct template *template; - int i = 0; - - printf("Available Templates:\n"); - - TAILQ_FOREACH(template, &templates, next) { - if (strcmp(template->emulation, emulation)) - continue; - - i++; - printf("%d. %s - %s\n", i, - template->name, template->description); - } -} - -/* Inserts a policy from a template */ - -static int -filter_template(int fd, struct policy *policy, int count) -{ - extern struct tmplqueue templates; - struct template *template; - int i = 0; - - TAILQ_FOREACH(template, &templates, next) { - if (strcmp(template->emulation, policy->emulation)) - continue; - - i++; - if (i == count) - break; - } - - if (i != count) - return (-1); - - template = systrace_readtemplate(template->filename, policy, template); - if (template == NULL) - return (-1); - - if (filter_prepolicy(fd, policy) == -1) - return (-1); - - /* We inserted new statements into the policy */ - policy->flags |= POLICY_CHANGED; - - return (0); -} - -static void -filter_policyrecord(struct policy *policy, struct filter *filter, - const char *emulation, const char *name, char *rule) -{ - /* Record the filter in the policy */ - 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)); - - TAILQ_INSERT_TAIL(&policy->filters, filter, policy_next); - policy->nfilters++; - - policy->flags |= POLICY_CHANGED; -} - -int -filter_parse(char *line, struct filter **pfilter) -{ - char *rule; - - if (parse_filter(line, pfilter) == -1) - return (-1); - - if ((rule = strdup(line)) == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - - (*pfilter)->rule = rule; - - return (0); -} - -/* Translate a simple action like "permit" or "deny[einval]" to numbers */ - -int -filter_parse_simple(char *rule, short *paction, short *pfuture) -{ - char buf[_POSIX2_LINE_MAX]; - int isfuture = 1; - char *line, *p; - - if (strlcpy(buf, rule, sizeof(buf)) >= sizeof(buf)) - return (-1); - - line = buf; - - if (!strcmp("permit", line)) { - *paction = *pfuture = ICPOLICY_PERMIT; - return (0); - } else if (!strcmp("permit-now", line)) { - *paction = ICPOLICY_PERMIT; - return (0); - } else if (strncmp("deny", line, 4)) - return (-1); - - line +=4 ; - if (!strncmp("-now", line, 4)) { - line += 4; - isfuture = 0; - } - - *paction = ICPOLICY_NEVER; - - switch (line[0]) { - case '\0': - break; - case '[': - line++; - p = strsep(&line, "]"); - if (line == NULL || *line != '\0') - return (-1); - - *paction = systrace_error_translate(p); - if (*paction == -1) - return (-1); - break; - default: - return (-1); - } - - if (isfuture) - *pfuture = *paction; - - return (0); -} - -void -filter_modifypolicy(int fd, int policynr, const char *emulation, - const char *name, short future) -{ - struct systrace_revalias *reverse = NULL; - - /* - * Check if we are dealing with a system call that really - * is an alias for something else. - */ - if (!noalias) - reverse = systrace_find_reverse(emulation, name); - if (reverse == NULL) { - if (systrace_modifypolicy(fd, policynr, name, future) == -1) - errx(1, "%s:%d: modify policy for %s-%s", - __func__, __LINE__, emulation, name); - } else { - struct systrace_alias *alias; - - /* For every system call associated with this alias - * set the permanent in-kernel policy. - */ - TAILQ_FOREACH(alias, &reverse->revl, next) { - if(systrace_modifypolicy(fd, policynr, - alias->name, future) == -1) - errx(1, "%s:%d: modify policy for %s-%s", - __func__, __LINE__, - emulation, alias->name); - } - } -} - -/* In non-root case, evaluate predicates early */ - -static int -filter_quickpredicate(struct filter *filter) -{ - struct predicate *pdc; - struct intercept_pid icpid; - - pdc = &filter->match_predicate; - if (!pdc->p_flags) - return (1); - - intercept_setpid(&icpid, getuid(), getgid()); - - if (!filter_predicate(&icpid, pdc)) - return (0); - - memset(pdc, 0, sizeof(filter->match_predicate)); - - return (1); -} - -/* - * Processes the filters for a policy that have not been applied yet. - * Pre-filters get installed when reading a policy. This function - * installs a fast-path in the kernel. - */ - -int -filter_prepolicy(int fd, struct policy *policy) -{ - int res; - struct filter *filter, *parsed; - struct filterq *fls; - short action, future; - extern int iamroot; - - /* Commit all matching pre-filters */ - for (filter = TAILQ_FIRST(&policy->prefilters); - filter; filter = TAILQ_FIRST(&policy->prefilters)) { - future = ICPOLICY_ASK; - - TAILQ_REMOVE(&policy->prefilters, filter, policy_next); - - res = 0; - parsed = NULL; - /* Special rules that are not real filters */ - if (filter_parse_simple(filter->rule, &action, &future) == -1) - res = filter_parse(filter->rule, &parsed); - if (res == -1) - errx(1, "%s:%d: can not parse \"%s\"", - __func__, __LINE__, filter->rule); - - if (future == ICPOLICY_ASK) { - if (iamroot || filter_quickpredicate(parsed)) { - fls = systrace_policyflq(policy, - policy->emulation, filter->name); - TAILQ_INSERT_TAIL(fls, parsed, next); - } - } else { - filter_modifypolicy(fd, policy->policynr, - policy->emulation, filter->name, future); - } - filter_policyrecord(policy, parsed, policy->emulation, - filter->name, filter->rule); - - filter_free(filter); - } - - /* Existing policy applied undo changed flag */ - policy->flags &= ~POLICY_CHANGED; - - return (0); -} - -short -filter_ask(int fd, struct intercept_tlq *tls, struct filterq *fls, - int policynr, const char *emulation, const char *name, - char *output, short *pfuture, struct intercept_pid *icpid) -{ - char line[2*PATH_MAX], *p; - char compose[2*PATH_MAX]; - struct filter *filter; - struct policy *policy; - short action; - int first = 1, isalias, isprompt = 0; - - *pfuture = ICPOLICY_ASK; - - isalias = systrace_find_reverse(emulation, name) != NULL; - - if ((policy = systrace_findpolnr(policynr)) == NULL) - errx(1, "%s:%d: no policy %d", __func__, __LINE__, policynr); - - if (!allow) - printf("%s\n", output); - else { - /* Automatically allow */ - if (tls != NULL) { - struct intercept_translate *tl; - char *l, *lst = NULL; - int set = 0; - - /* Explicitly match every component */ - line[0] = '\0'; - TAILQ_FOREACH(tl, tls, next) { - if (!tl->trans_valid) - continue; - l = intercept_translate_print(tl); - if (l == NULL) - continue; - - snprintf(compose, sizeof(compose), - "%s%s eq \"%s\"", - tl->name, - lst && !strcmp(tl->name, lst) ? "[1]" : "", - strescape(l)); - - lst = tl->name; - - if (set) - strlcat(line, " and ", - sizeof(line)); - else - set = 1; - strlcat(line, compose, sizeof(line)); - } - if (!set) - strlcpy(line, "true", sizeof(line)); - strlcat(line, " then permit", sizeof(line)); - } else - strlcpy(line, "permit", sizeof(line)); - } - - while (1) { - /* Special policy active that allows only yes or no */ - if (icpid->uflags & PROCESS_PROMPT) - isprompt = 1; - filter = NULL; - - if (!allow) { - /* Ask for a policy */ - if (!connected) - printf("Answer: "); - else { - /* Do not prompt the first time */ - if (!first) { - printf("WRONG\n"); - } - } - - if (fgets(line, sizeof(line), stdin) == NULL) { - if (connected && !cradle && errno == EPIPE && - !requestor_restart) { - requestor_start(guipath, 0); - clearerr(stdin); - clearerr(stdout); - requestor_restart = 1; - printf("%s\n", output); - continue; - } - err(1, "EOF on policy input request"); - } - p = line; - strsep(&p, "\n"); - } else if (!first) { - /* Error with filter */ - errx(1, "Filter generation error: %s", line); - } - first = 0; - requestor_restart = 0; - - /* Simple keywords */ - if (!strcasecmp(line, "detach")) { - if (policy->nfilters) { - policy->flags |= POLICY_UNSUPERVISED; - action = ICPOLICY_NEVER; - } else { - policy->flags |= POLICY_DETACHED; - policy->flags |= POLICY_CHANGED; - action = ICPOLICY_PERMIT; - } - goto out; - } else if (!strcasecmp(line, "kill")) { - action = ICPOLICY_KILL; - goto out; - } else if (!strcasecmp(line, "review") && fls != NULL) { - filter_review(fls); - continue; - } else if (!strcasecmp(line, "templates")) { - filter_templates(emulation); - continue; - } else if (!strncasecmp(line, "template ", 9)) { - const char *errstr; - int count = strtonum(line + 9, 1, INT_MAX, &errstr); - - if (errstr || - filter_template(fd, policy, count) == -1) { - printf("Syntax error.\n"); - continue; - } - - if (fls != NULL) - action = filter_evaluate(tls, fls, icpid); - else - action = ICPOLICY_PERMIT; - if (action == ICPOLICY_ASK) { - printf("Filter unmatched.\n"); - continue; - } - - goto out; - } - - if (filter_parse_simple(line, &action, pfuture) != -1) { - /* Yes or no, no in-kernel policy allowed */ - if (isprompt) - *pfuture = ICPOLICY_ASK; - if (*pfuture == ICPOLICY_ASK) - goto out; - /* We have a policy decision */ - if (!isalias) - break; - - /* No in-kernel policy for aliases */ - strlcpy(compose, line, sizeof(compose)); - - /* Change into userland rule */ - snprintf(line, sizeof(line), "true then %s", compose); - } - - if (isprompt) { - printf("Answer only \"permit\" or \"deny\". " - "This is a prompt.\n"); - continue; - } - - if (fls == NULL) { - printf("Syntax error.\n"); - continue; - } - - if (filter_parse(line, &filter) == -1) { - printf("Parse error.\n"); - continue; - } - - TAILQ_INSERT_TAIL(fls, filter, next); - action = filter_evaluate(tls, fls, icpid); - - /* If we get a prompt flag here, we ask again */ - if (icpid->uflags & PROCESS_PROMPT) { - filter_policyrecord(policy, filter, emulation, name, line); - printf("Answer only \"permit\" or \"deny\". " - "This is a prompt.\n"); - continue; - } - if (action == ICPOLICY_ASK) { - TAILQ_REMOVE(fls, filter, next); - printf("Filter unmatched. Freeing it\n"); - filter_free(filter); - continue; - } - - break; - } - - filter_policyrecord(policy, filter, emulation, name, line); - - out: - if (connected) - printf("OKAY\n"); - return (action); - -} - -static void -filter_replace(char *buf, size_t buflen, char *match, char *repl) -{ - while (strrpl(buf, buflen, match, repl) != NULL) - ; -} - -char * -filter_expand(char *data) -{ - static char expand[2*PATH_MAX]; - - strlcpy(expand, data, sizeof(expand)); - - filter_replace(expand, sizeof(expand), "$HOME", home); - filter_replace(expand, sizeof(expand), "$USER", username); - filter_replace(expand, sizeof(expand), "$CWD", cwd); - - return (expand); -} - -char * -filter_dynamicexpand(struct intercept_pid *icpid, char *data) -{ - extern char cwd[]; - static char expand[2*PATH_MAX]; - - strlcpy(expand, data, sizeof(expand)); - - filter_replace(expand, sizeof(expand), "$HOME", icpid->home); - filter_replace(expand, sizeof(expand), "$USER", icpid->username); - filter_replace(expand, sizeof(expand), "$CWD", cwd); - - return (expand); -} - -/* Checks if the string needs expansion */ - -int -filter_needexpand(char *data) -{ - if (strstr(data, "$HOME") != NULL) - return (1); - if (strstr(data, "$USER") != NULL) - return (1); - if (strstr(data, "$CWD") != NULL) - return (1); - - return (0); -} - -int -filter_fnmatch(struct intercept_translate *tl, struct logic *logic) -{ - int res; - char *line; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - res = fnmatch(logic->filterdata, line, FNM_PATHNAME | FNM_LEADING_DIR); - - return (res == 0); -} - -int -filter_substrmatch(struct intercept_translate *tl, struct logic *logic) -{ - char *line; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - - return (strstr(line, logic->filterdata) != NULL); -} - -int -filter_negsubstrmatch(struct intercept_translate *tl, struct logic *logic) -{ - char *line; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - - return (strstr(line, logic->filterdata) == NULL); -} - -int -filter_stringmatch(struct intercept_translate *tl, struct logic *logic) -{ - char *line; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - - return (!strcasecmp(line, logic->filterdata)); -} - -int -filter_negstringmatch(struct intercept_translate *tl, struct logic *logic) -{ - char *line; - - if ((line = intercept_translate_print(tl)) == NULL) - return (1); - - return (strcasecmp(line, logic->filterdata) != 0); -} - -int -filter_inpath(struct intercept_translate *tl, struct logic *logic) -{ - char *line, c; - int len; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - - len = strlen(line); - if (len == 0 || len > strlen(logic->filterdata)) - return (0); - - /* Root is always in path */ - if (len == 1) - return (line[0] == '/'); - - /* Complete filename needs to fit */ - if (strncmp(line, logic->filterdata, len)) - return (0); - - /* Termination has to be \0 or / */ - c = ((char *)logic->filterdata)[len]; - if (c != '/' && c != '\0') - return (0); - - return (1); -} - -int -filter_regex(struct intercept_translate *tl, struct logic *logic) -{ - regex_t tmpre, *re; - char *line; - int res; - - if ((line = intercept_translate_print(tl)) == NULL) - return (0); - - re = logic->filterarg; - if (re == NULL) { - /* If regex does not compute, we just do not match */ - if (regcomp(&tmpre, logic->filterdata, - REG_EXTENDED | REG_NOSUB) != 0) - return (0); - re = &tmpre; - } - - res = regexec(re, line, 0, NULL, 0); - - /* Clean up temporary memory associated with regex */ - if (re == &tmpre) - regfree(re); - - return (res == 0); -} - -/* ARGSUSED */ -int -filter_true(struct intercept_translate *tl, struct logic *logic) -{ - return (1); -} diff --git a/bin/systrace/filter.h b/bin/systrace/filter.h deleted file mode 100644 index eff0a17e6ae..00000000000 --- a/bin/systrace/filter.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $OpenBSD: filter.h,v 1.2 2002/12/09 07:24:56 itojun Exp $ */ - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -int filter_fnmatch(struct intercept_translate *, struct logic *); -int filter_stringmatch(struct intercept_translate *, struct logic *); -int filter_negstringmatch(struct intercept_translate *, struct logic *); -int filter_substrmatch(struct intercept_translate *, struct logic *); -int filter_negsubstrmatch(struct intercept_translate *, struct logic *); -int filter_inpath(struct intercept_translate *, struct logic *); -int filter_regex(struct intercept_translate *, struct logic *); -int filter_true(struct intercept_translate *, struct logic *); diff --git a/bin/systrace/intercept-translate.c b/bin/systrace/intercept-translate.c deleted file mode 100644 index 60c207cec5c..00000000000 --- a/bin/systrace/intercept-translate.c +++ /dev/null @@ -1,445 +0,0 @@ -/* $OpenBSD: intercept-translate.c,v 1.18 2015/12/09 19:36:17 mmcc Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/tree.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <stdint.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <netdb.h> -#include <err.h> - -#include "intercept.h" - -char *error_msg = "error"; - -static void ic_trans_free(struct intercept_translate *); -static int ic_print_filename(char *, size_t, struct intercept_translate *); -static int ic_get_filename(struct intercept_translate *, int, pid_t, void *); -static int ic_get_string(struct intercept_translate *, int, pid_t, void *); -static int ic_get_linkname(struct intercept_translate *, int, pid_t, void *); -static int ic_get_sockaddr(struct intercept_translate *, int, pid_t, void *); -static int ic_print_sockaddr(char *, size_t, struct intercept_translate *); - -static void -ic_trans_free(struct intercept_translate *trans) -{ - free(trans->trans_data); - free(trans->trans_print); - trans->trans_valid = 0; - trans->trans_data = NULL; - trans->trans_print = NULL; - trans->trans_size = 0; - trans->trans_addr = NULL; -} - -extern struct intercept_system intercept; - -/* Takes a translation structure and retrieves the right data */ - -int -intercept_translate(struct intercept_translate *trans, - int fd, pid_t pid, int off, void *args, int argsize) -{ - void *addr, *addr2, *addrend; - - ic_trans_free(trans); - - if (intercept.getarg(off, args, argsize, &addr) == -1) - return (-1); - if (trans->off2) { - if (intercept.getarg(trans->off + trans->off2, - args, argsize, &addr2) == -1) - return (-1); - trans->trans_addr2 = addr2; - } - if (trans->offend) { - /* XXX: Abstraction violation. */ - int numargs = argsize / sizeof(register_t); - - if (intercept.getarg(numargs + trans->offend, - args, argsize, &addrend) == -1) - return (-1); - trans->trans_addrend = addrend; - } - - trans->trans_valid = 1; - trans->trans_addr = addr; - - if (trans->translate == NULL) - return (0); - - if ((*trans->translate)(trans, fd, pid, addr) == -1) { - trans->trans_valid = 0; - return (-1); - } - - return (0); -} - -char * -intercept_translate_print(struct intercept_translate *trans) -{ - char line[_POSIX2_LINE_MAX]; - - if (trans->trans_print == NULL) { - if (trans->print(line, sizeof(line), trans) == -1) - return (error_msg); - - if ((trans->trans_print = strdup(line)) == NULL) - return (error_msg); - } - - return (trans->trans_print); -} - -static int -ic_print_filename(char *buf, size_t buflen, struct intercept_translate *tl) -{ - strlcpy(buf, tl->trans_data, buflen); - - return (0); -} - -static int -ic_get_filename(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - char *name; - size_t len; - - name = intercept_filename(fd, pid, addr, ICLINK_ALL, NULL); - if (name == NULL) - return (-1); - - len = strlen(name) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - trans->trans_size = len; - memcpy(trans->trans_data, name, len); - trans->trans_flags = ICTRANS_NOLINKS; - - return (0); -} - -static int -ic_get_string(struct intercept_translate *trans, int fd, pid_t pid, void *addr) -{ - char *name; - size_t len; - - if (addr == NULL) - return (-1); - - name = intercept_get_string(fd, pid, addr); - if (name == NULL) - return (-1); - - len = strlen(name) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - trans->trans_size = len; - memcpy(trans->trans_data, name, len); - - return (0); -} - -static int -ic_get_linkname(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - char *name; - size_t len; - - name = intercept_filename(fd, pid, addr, ICLINK_NONE, NULL); - if (name == NULL) - return (-1); - - len = strlen(name) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - trans->trans_size = len; - memcpy(trans->trans_data, name, len); - - return (0); -} - -/* Resolves all symlinks but for the last component */ - -static int -ic_get_unlinkname(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - char *name; - size_t len; - - name = intercept_filename(fd, pid, addr, ICLINK_NOLAST, NULL); - if (name == NULL) - return (-1); - - len = strlen(name) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - trans->trans_size = len; - memcpy(trans->trans_data, name, len); - trans->trans_flags = ICTRANS_NOLINKS; - - return (0); -} - -static int -ic_get_filenameat(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - char *name; - size_t len; - int atfd = (intptr_t)trans->trans_addr2; - int follow = (intptr_t)trans->user; - int userp; - - if (trans->offend) { - int flag = (intptr_t)trans->trans_addrend; - if ((flag & ~(AT_SYMLINK_FOLLOW | AT_SYMLINK_NOFOLLOW)) != 0) - return (-1); - if ((flag & follow) != 0) - return (-1); - if (flag != 0) - follow = flag; - } - - userp = (follow == AT_SYMLINK_FOLLOW) ? ICLINK_ALL : ICLINK_NOLAST; - name = intercept_filenameat(fd, pid, atfd, addr, userp, NULL); - if (name == NULL) - return (-1); - - len = strlen(name) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - trans->trans_size = len; - memcpy(trans->trans_data, name, len); - trans->trans_flags = ICTRANS_NOLINKS; - - return (0); -} - -static int -ic_get_sockaddr(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - struct sockaddr_storage sa; - socklen_t len; - - len = (intptr_t)trans->trans_addr2; - if (len == 0 || len > sizeof(struct sockaddr_storage)) - return (-1); - - if (intercept.io(fd, pid, INTERCEPT_READ, addr, - (void *)&sa, len) == -1) - return (-1); - - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - trans->trans_size = len; - memcpy(trans->trans_data, &sa, len); - - return (0); -} - -#ifndef offsetof -#define offsetof(s, e) ((size_t)&((s *)0)->e) -#endif - -static int -ic_print_sockaddr(char *buf, size_t buflen, struct intercept_translate *tl) -{ - char host[NI_MAXHOST]; - char serv[NI_MAXSERV]; - struct sockaddr *sa = tl->trans_data; - socklen_t len = (socklen_t)tl->trans_size; - - buf[0] = '\0'; - - switch (sa->sa_family) { - case PF_LOCAL: - if (len <= offsetof(struct sockaddr, sa_data)) - return (-1); - len -= offsetof(struct sockaddr, sa_data); - if (buflen < len + 1) - len = buflen - 1; - memcpy(buf, sa->sa_data, len); - buf[len] = '\0'; - return (0); - case PF_INET: - case PF_INET6: - break; - default: - snprintf(buf, buflen, "family(%d)", sa->sa_family); - return (0); - } - - sa->sa_len = len; - if (getnameinfo(sa, len, - host, sizeof(host), serv, sizeof(serv), - NI_NUMERICHOST | NI_NUMERICSERV)) { - warn("getnameinfo"); - return (-1); - } - - snprintf(buf, buflen, "inet-[%s]:%s", host, serv); - - return (0); -} - -static int -ic_get_msghdr(struct intercept_translate *trans, int fd, pid_t pid, - void *addr) -{ - struct msghdr msg; - int len = sizeof(struct msghdr); - - if (intercept.io(fd, pid, INTERCEPT_READ, addr, - (void *)&msg, len) == -1) - return (-1); - - len = msg.msg_namelen; - if (msg.msg_name == NULL || len <= 0 || len > 2048) { - trans->trans_data = NULL; - trans->trans_size = 0; - return (0); - } - - trans->trans_size = len; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - if (intercept.io(fd, pid, INTERCEPT_READ, msg.msg_name, - (void *)trans->trans_data, trans->trans_size) == -1) - return (-1); - - return (0); -} - -static int -ic_print_msghdr(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int res = 0; - - if (tl->trans_size == 0) { - snprintf(buf, buflen, "<unknown>"); - } else { - res = ic_print_sockaddr(buf, buflen, tl); - /* - * disable replacement of this argument because it's two levels - * deep and we cant replace that fast. - */ - tl->trans_size = 0; - - /* TODO: make this less of a hack */ - } - - return (res); -} - -struct intercept_translate ic_translate_string = { - "string", - ic_get_string, ic_print_filename, -}; - -struct intercept_translate ic_translate_filename = { - "filename", - ic_get_filename, ic_print_filename, -}; - -struct intercept_translate ic_translate_linkname = { - "filename", - ic_get_linkname, ic_print_filename, -}; - -struct intercept_translate ic_translate_unlinkname = { - "filename", - ic_get_unlinkname, ic_print_filename, -}; - -struct intercept_translate ic_translate_filenameat = { - "filename", - ic_get_filenameat, ic_print_filename, - .off2 = -1, - .user = (void *)AT_SYMLINK_FOLLOW, -}; - -struct intercept_translate ic_translate_unlinknameat = { - "filename", - ic_get_filenameat, ic_print_filename, - .off2 = -1, - .user = (void *)AT_SYMLINK_NOFOLLOW, -}; - -struct intercept_translate ic_translate_filenameatflag = { - "filename", - ic_get_filenameat, ic_print_filename, - .off2 = -1, - .offend = -1, - .user = (void *)AT_SYMLINK_FOLLOW, -}; - -struct intercept_translate ic_translate_unlinknameatflag = { - "filename", - ic_get_filenameat, ic_print_filename, - .off2 = -1, - .offend = -1, - .user = (void *)AT_SYMLINK_NOFOLLOW, -}; - -struct intercept_translate ic_translate_connect = { - "sockaddr", - ic_get_sockaddr, ic_print_sockaddr, - /* XXX - Special handling */ 1, -}; - -struct intercept_translate ic_translate_sendmsg = { - "sockaddr", - ic_get_msghdr, ic_print_msghdr, -}; diff --git a/bin/systrace/intercept.c b/bin/systrace/intercept.c deleted file mode 100644 index c0bf39a147f..00000000000 --- a/bin/systrace/intercept.c +++ /dev/null @@ -1,1172 +0,0 @@ -/* $OpenBSD: intercept.c,v 1.65 2015/12/09 19:36:17 mmcc Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - - -#include <sys/types.h> -#include <sys/tree.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <limits.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include <poll.h> -#include <fcntl.h> -#include <stdio.h> -#include <unistd.h> -#include <limits.h> -#include <errno.h> -#include <err.h> -#include <libgen.h> -#include <pwd.h> - -#include "intercept.h" - -void simplify_path(char *); -char *intercept_realpath(const char *, char *); - -struct intercept_syscall { - SPLAY_ENTRY(intercept_syscall) node; - - char name[64]; - char emulation[16]; - - short (*cb)(int, pid_t, int, const char *, int, const char *, void *, - int, struct intercept_replace *, struct intercept_tlq *, void *); - void *cb_arg; - - struct intercept_tlq tls; -}; - -static int sccompare(struct intercept_syscall *, struct intercept_syscall *); -static int pidcompare(struct intercept_pid *, struct intercept_pid *); -static struct intercept_syscall *intercept_sccb_find(const char *, - const char *); -static void sigusr1_handler(int); - -static SPLAY_HEAD(pidtree, intercept_pid) pids; -static SPLAY_HEAD(sctree, intercept_syscall) scroot; - -static volatile int got_sigusr1 = 0; - -/* Generic callback functions */ - -void (*intercept_newimagecb)(int, pid_t, int, const char *, const char *, void *) = NULL; -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) -{ - int diff; - - diff = strcmp(a->emulation, b->emulation); - if (diff) - return (diff); - return (strcmp(a->name, b->name)); -} - -int -pidcompare(struct intercept_pid *a, struct intercept_pid *b) -{ - int diff = a->pid - b->pid; - - if (diff == 0) - return (0); - if (diff > 0) - return (1); - return (-1); -} - -SPLAY_PROTOTYPE(sctree, intercept_syscall, node, sccompare) -SPLAY_GENERATE(sctree, intercept_syscall, node, sccompare) - -SPLAY_PROTOTYPE(pidtree, intercept_pid, next, pidcompare) -SPLAY_GENERATE(pidtree, intercept_pid, next, pidcompare) - -extern struct intercept_system intercept; -int ic_abort; - -int -intercept_init(void) -{ - SPLAY_INIT(&pids); - SPLAY_INIT(&scroot); - - intercept_newimagecb = NULL; - intercept_gencb = NULL; - - return (intercept.init()); -} - -struct intercept_syscall * -intercept_sccb_find(const char *emulation, const char *name) -{ - struct intercept_syscall tmp; - - strlcpy(tmp.name, name, sizeof(tmp.name)); - strlcpy(tmp.emulation, emulation, sizeof(tmp.emulation)); - return (SPLAY_FIND(sctree, &scroot, &tmp)); -} - -struct intercept_translate * -intercept_register_translation(char *emulation, char *name, int offset, - struct intercept_translate *tl) -{ - struct intercept_syscall *tmp; - struct intercept_translate *tlnew; - - if (offset >= INTERCEPT_MAXSYSCALLARGS) - errx(1, "%s: %s-%s: offset too large", - __func__, emulation, name); - - tmp = intercept_sccb_find(emulation, name); - if (tmp == NULL) - errx(1, "%s: %s-%s: can't find call back", - __func__, emulation, name); - - tlnew = malloc(sizeof(struct intercept_translate)); - if (tlnew == NULL) - err(1, "%s: %s-%s: malloc", - __func__, emulation, name); - - memcpy(tlnew, tl, sizeof(struct intercept_translate)); - tlnew->off = offset; - - TAILQ_INSERT_TAIL(&tmp->tls, tlnew, next); - - return (tlnew); -} - -void * -intercept_sccb_cbarg(char *emulation, char *name) -{ - struct intercept_syscall *tmp; - - if ((tmp = intercept_sccb_find(emulation, name)) == NULL) - return (NULL); - - return (tmp->cb_arg); -} - -int -intercept_register_sccb(char *emulation, char *name, - short (*cb)(int, pid_t, int, const char *, int, const char *, void *, int, - struct intercept_replace *, struct intercept_tlq *, void *), - void *cbarg) -{ - struct intercept_syscall *tmp; - - if (intercept_sccb_find(emulation, name)) - return (-1); - - if (intercept.getsyscallnumber(emulation, name) == -1) { - warnx("%s: %d: unknown syscall: %s-%s", __func__, __LINE__, - emulation, name); - return (-1); - } - - if ((tmp = calloc(1, sizeof(struct intercept_syscall))) == NULL) { - warn("%s:%d: calloc", __func__, __LINE__); - return (-1); - } - - TAILQ_INIT(&tmp->tls); - strlcpy(tmp->name, name, sizeof(tmp->name)); - strlcpy(tmp->emulation, emulation, sizeof(tmp->emulation)); - tmp->cb = cb; - tmp->cb_arg = cbarg; - - SPLAY_INSERT(sctree, &scroot, tmp); - - return (0); -} - -int -intercept_register_gencb(short (*cb)(int, pid_t, int, const char *, int, const char *, void *, int, void *), void *arg) -{ - intercept_gencb = cb; - intercept_gencbarg = arg; - - return (0); -} - -int -intercept_register_execcb(void (*cb)(int, pid_t, int, const char *, const char *, void *), void *arg) -{ - intercept_newimagecb = cb; - intercept_newimagecbarg = arg; - - return (0); -} - -int -intercept_register_pfreecb(void (*cb)(int, void *), void *arg) -{ - intercept_pfreecb = cb; - intercept_pfreearg = arg; - - return (0); -} - -/* ARGSUSED */ -static void -sigusr1_handler(int signum) -{ - /* all we need to do is pretend to handle it */ - got_sigusr1 = 1; -} - -void -intercept_setpid(struct intercept_pid *icpid, uid_t uid, gid_t gid) -{ - struct passwd *pw; - - icpid->uid = uid; - icpid->gid = gid; - if ((pw = getpwuid(icpid->uid)) == NULL) { - snprintf(icpid->username, sizeof(icpid->username), - "unknown(%d)", icpid->uid); - strlcpy(icpid->home, "/var/empty", sizeof(icpid->home)); - } else { - strlcpy(icpid->username, pw->pw_name, sizeof(icpid->username)); - strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home)); - } -} - -pid_t -intercept_run(int bg, int *fdp, uid_t uid, gid_t gid, - char *path, char *const argv[]) -{ - struct intercept_pid *icpid; - sigset_t none, set, oset; - sig_t ohandler; - pid_t pid, cpid; - int status; - - /* Block signals so that timing on signal delivery does not matter */ - sigemptyset(&none); - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - if (sigprocmask(SIG_BLOCK, &set, &oset) == -1) - err(1, "sigprocmask"); - ohandler = signal(SIGUSR1, sigusr1_handler); - if (ohandler == SIG_ERR) - err(1, "signal"); - - /* - * If systrace process will be the child then we must reopen - * the fd in the child after the fork - */ - if (bg) - close(*fdp); - - pid = getpid(); - cpid = fork(); - if (cpid == -1) - return (-1); - - /* - * If the systrace process should be in the background and we're - * the parent, or vice versa. - */ - if ((!bg && cpid == 0) || (bg && cpid != 0)) { - if (bg) { - /* Wait for child to "detach" */ - cpid = wait(&status); - if (cpid == -1) - err(1, "wait"); - if (status != 0) - errx(1, "wait: child gave up"); - } - - /* Sleep */ - sigsuspend(&none); - - if (!got_sigusr1) - errx(1, "wrong signal"); - - /* - * Woken up, restore signal handling state. - * - * Note that there is either no child or we have no idea - * what pid it might have at this point. If we fail. - */ - if (signal(SIGUSR1, ohandler) == SIG_ERR) - err(1, "signal"); - if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) - err(1, "sigprocmask"); - - /* Change to different user */ - if (uid || gid) { - if (setresgid(gid, gid, gid) == -1) - err(1, "setresgid"); - if (setgroups(1, &gid) == -1) - err(1, "setgroups"); - if (setresuid(uid, uid, uid) == -1) - err(1, "setresuid"); - } - execvp(path, argv); - - /* Error */ - err(1, "execvp"); - } - - /* Choose the pid of the systraced process */ - pid = bg ? pid : cpid; - - icpid = intercept_getpid(pid); - - /* Set up user related information */ - if (!uid && !gid) { - uid = getuid(); - gid = getgid(); - } - intercept_setpid(icpid, uid, gid); - - /* Setup done, restore signal handling state */ - if (signal(SIGUSR1, ohandler) == SIG_ERR) { - int saved_errno = errno; - kill(pid, SIGKILL); - errc(1, saved_errno, "signal"); - } - if (sigprocmask(SIG_SETMASK, &oset, NULL) == -1) { - int saved_errno = errno; - kill(pid, SIGKILL); - errc(1, saved_errno, "sigprocmask"); - } - - if (bg) { - if (daemon(1, 1) == -1) { - int saved_errno = errno; - kill(pid, SIGKILL); - errc(1, saved_errno, "daemon"); - } - if ((*fdp = intercept_open()) == -1) { - int saved_errno = errno; - kill(pid, SIGKILL); - errc(1, saved_errno, "intercept_open"); - } - } - - return (pid); -} - -int -intercept_existpids(void) -{ - return (SPLAY_ROOT(&pids) != NULL); -} - -void -intercept_freepid(pid_t pidnr) -{ - struct intercept_pid *pid, tmp2; - - tmp2.pid = pidnr; - pid = SPLAY_FIND(pidtree, &pids, &tmp2); - if (pid == NULL) - return; - - intercept.freepid(pid); - - SPLAY_REMOVE(pidtree, &pids, pid); - free(pid->name); - free(pid->newname); - free(pid); -} - -struct intercept_pid * -intercept_findpid(pid_t pid) -{ - struct intercept_pid *tmp, tmp2; - - tmp2.pid = pid; - tmp = SPLAY_FIND(pidtree, &pids, &tmp2); - - return (tmp); -} - -struct intercept_pid * -intercept_getpid(pid_t pid) -{ - struct intercept_pid *tmp, tmp2; - - tmp2.pid = pid; - tmp = SPLAY_FIND(pidtree, &pids, &tmp2); - - if (tmp) - return (tmp); - - if ((tmp = calloc(1, sizeof(struct intercept_pid))) == NULL) - err(1, "%s: calloc", __func__); - - tmp->pid = pid; - - SPLAY_INSERT(pidtree, &pids, tmp); - - return (tmp); -} - -int -intercept_open(void) -{ - int fd; - - if ((fd = intercept.open()) == -1) - return (-1); - - if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) - warn("fcntl(O_NONBLOCK)"); - - return (fd); -} - -int -intercept_attach(int fd, pid_t pid) -{ - return (intercept.attach(fd, pid)); -} - -int -intercept_attachpid(int fd, pid_t pid, char *name) -{ - struct intercept_pid *icpid; - int res; - - res = intercept.attach(fd, pid); - if (res == -1) - return (-1); - - icpid = intercept_getpid(pid); - - if ((icpid->newname = strdup(name)) == NULL) - err(1, "strdup"); - - if (intercept.report(fd, pid) == -1) - return (-1); - - /* Indicates a running attach */ - icpid->execve_code = -1; - - return (0); -} - -int -intercept_detach(int fd, pid_t pid) -{ - int res; - - res = intercept.detach(fd, pid); - if (res != -1) - intercept_freepid(pid); - return (res); -} - -int -intercept_read(int fd) -{ - struct pollfd pollfd; - int n; - - pollfd.fd = fd; - pollfd.events = POLLIN; - - do { - n = poll(&pollfd, 1, -1); - if (n == -1) { - if (errno != EINTR && errno != EAGAIN) - return (-1); - } - } while (n <= 0); - - if (!(pollfd.revents & (POLLIN|POLLRDNORM))) - return (-1); - - return (intercept.read(fd)); -} - -int -intercept_replace_init(struct intercept_replace *repl) -{ - memset(repl, 0, sizeof(struct intercept_replace)); - - return (0); -} - -int -intercept_replace_add(struct intercept_replace *repl, int off, - u_char *addr, size_t len, u_int flags) -{ - int ind = repl->num; - - if (ind >= INTERCEPT_MAXSYSCALLARGS) - return (-1); - - repl->ind[ind] = off; - repl->address[ind] = addr; - repl->len[ind] = len; - repl->flags[ind] = flags; - - repl->num++; - - return (0); -} - -int -intercept_replace(int fd, pid_t pid, u_int16_t seqnr, - struct intercept_replace *repl) -{ - if (repl->num == 0) - return (0); - - return (intercept.replace(fd, pid, seqnr, repl)); -} - -char * -intercept_get_string(int fd, pid_t pid, void *addr) -{ - static char name[ARG_MAX]; - int off = 0, done = 0, stride; - - if (addr == NULL) - return (NULL); - - stride = 32; - do { - if (intercept.io(fd, pid, INTERCEPT_READ, (char *)addr + off, - &name[off], stride) == -1) { - /* Did the current system call get interrupted? */ - if (errno == EBUSY) - return (NULL); - if (errno != EINVAL || stride == 1) { - warn("%s: ioctl", __func__); - return (NULL); - } - - /* Try smaller stride */ - stride /= 2; - continue; - } - - off += stride; - name[off] = '\0'; - if (strlen(name) < off) - done = 1; - - } while (!done && off + stride + 1 < sizeof(name)); - - if (!done) { - warnx("%s: string too long", __func__); - return (NULL); - } - - return (name); -} - -char * -intercept_filename(int fd, pid_t pid, void *addr, int userp, char *before) -{ - return (intercept_filenameat(fd, pid, AT_FDCWD, addr, userp, before)); -} - -char * -intercept_filenameat(int fd, pid_t pid, int atfd, void *addr, int userp, char *before) -{ - char *name; - - if ((name = intercept_get_string(fd, pid, addr)) == NULL) - goto abort; - - if (before != NULL) - strlcpy(before, name, PATH_MAX); - - if ((name = normalize_filenameat(fd, pid, atfd, name, userp)) == NULL) - goto abort; - - return (name); - - abort: - ic_abort = 1; - return (NULL); -} - -/* - * Normalizes a pathname so that Systrace policies entries are - * invariant to symlinks. - */ - -char * -normalize_filename(int fd, pid_t pid, char *name, int userp) -{ - return (normalize_filenameat(fd, pid, AT_FDCWD, name, userp)); -} - -char * -normalize_filenameat(int fd, pid_t pid, int atfd, char *name, int userp) -{ - static char cwd[2*PATH_MAX]; - int havecwd = 0; - - /* - * The empty filename does not receive normalization. - * System calls are supposed to fail on it. - */ - if (strcmp(name, "") == 0) - return (name); - - if (fd != -1 && intercept.setcwd(fd, pid, atfd) == -1) { - if (errno == EBUSY) - return (NULL); - getcwderr: - if (strcmp(name, "/") == 0) - return (name); - - err(1, "%s: getcwd", __func__); - } - - if (userp == ICLINK_NONE) { - if (getcwd(cwd, sizeof(cwd)) == NULL) - goto getcwderr; - havecwd = 1; - } - - if (havecwd && name[0] != '/') { - if (strlcat(cwd, "/", sizeof(cwd)) >= sizeof(cwd)) - return (NULL); - if (strlcat(cwd, name, sizeof(cwd)) >= sizeof(cwd)) - return (NULL); - } else { - if (strlcpy(cwd, name, sizeof(cwd)) >= sizeof(cwd)) - return (NULL); - } - - if (userp != ICLINK_NONE) { - static char rcwd[2*PATH_MAX]; - char *base = basename(cwd); - int failed = 0; - - /* The dot maybe used by rmdir("/tmp/something/.") */ - if (strcmp(base, ".") == 0) - goto nolast; - - if (userp == ICLINK_NOLAST) { - /* Check if the last component has special meaning */ - if (strcmp(base, "..") == 0 || strcmp(base, "/") == 0) - userp = ICLINK_ALL; - else - goto nolast; - } - - /* If realpath fails then the filename does not exist, - * or we are supposed to not resolve the last component */ - if (intercept_realpath(cwd, rcwd) == NULL) { - char *dir, last_char; - struct stat st; - int base_is_dir; - - if (errno != EACCES) { - failed = 1; - goto out; - } - - nolast: - /* Component of path could not be entered */ - if (strlcpy(rcwd, cwd, sizeof(rcwd)) >= sizeof(rcwd)) - goto error; - last_char = rcwd[strlen(rcwd)-1]; - if (last_char == '/') - base_is_dir = 1; - else - base_is_dir = 0; - if ((base = basename(rcwd)) == NULL) - goto error; - if ((dir = dirname(rcwd)) == NULL) - goto error; - - /* So, try again */ - if (intercept_realpath(dir, rcwd) == NULL) { - failed = 1; - goto out; - } - /* If path is not "/" append a "/" */ - if (strlen(rcwd) > 1 && - strlcat(rcwd, "/", sizeof(rcwd)) >= sizeof(rcwd)) - goto error; - if (strlcat(rcwd, base, sizeof(rcwd)) >= sizeof(rcwd)) - goto error; - if (base_is_dir && - strlcat(rcwd, "/", sizeof(rcwd)) >= sizeof(rcwd)) - goto error; - /* - * At this point, filename has to exist and has to - * be a directory. - */ - if (userp != ICLINK_NOLAST) { - if (lstat(rcwd, &st) == -1 || - !S_ISDIR(st.st_mode)) - failed = 1; - } - } - out: - if (failed) - snprintf(rcwd, sizeof(rcwd), - "/<non-existent filename>: %s", cwd); - name = rcwd; - } else { - simplify_path(cwd); - name = cwd; - } - - - /* Restore working directory and change root space after realpath */ - if (fd != -1 && intercept.restcwd(fd) == -1) - err(1, "%s: restcwd", __func__); - - return (name); - - error: - errx(1, "%s: filename too long", __func__); - /* NOTREACHED */ -} - -void -intercept_syscall(int fd, pid_t pid, u_int16_t seqnr, int policynr, - const char *name, int code, const char *emulation, void *args, int argsize) -{ - short action, flags = 0; - struct intercept_syscall *sc; - struct intercept_pid *icpid; - struct elevate *elevate = NULL; - int error = 0; - - action = ICPOLICY_PERMIT; - flags = 0; - - icpid = intercept_getpid(pid); - - /* Special handling for the exec call */ - if (!strcmp(name, "execve")) { - void *addr; - char *argname, before[PATH_MAX]; - - icpid->execve_code = code; - icpid->policynr = policynr; - - free(icpid->newname); - - intercept.getarg(0, args, argsize, &addr); - argname = intercept_filename(fd, pid, addr, ICLINK_ALL, before); - if (argname == NULL) - err(1, "%s:%d: intercept_filename", - __func__, __LINE__); - - if (intercept.scriptname(fd, pid, before) != 0) - err(1, "%s:%d: ioctl", __func__, __LINE__); - - icpid->newname = strdup(argname); - if (icpid->newname == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - - /* We need to know the result from this system call */ - flags = ICFLAGS_RESULT; - } - - icpid->elevate = NULL; - - sc = intercept_sccb_find(emulation, name); - if (sc != NULL) { - struct intercept_translate *tl; - - ic_abort = 0; - TAILQ_FOREACH(tl, &sc->tls, next) { - if (intercept_translate(tl, fd, pid, tl->off, - args, argsize) == -1) - break; - } - - if (!ic_abort) { - struct intercept_replace repl; - - intercept_replace_init(&repl); - - action = (*sc->cb)(fd, pid, policynr, name, code, - emulation, args, argsize, &repl, - &sc->tls, sc->cb_arg); - - if (action < ICPOLICY_NEVER) { - /* if we can not rewrite the arguments, - * system call fails. - */ - if (intercept_replace(fd, pid, seqnr, &repl) == -1) - action = ICPOLICY_NEVER; - } - } else - action = ICPOLICY_NEVER; - } else if (intercept_gencb != NULL) - action = (*intercept_gencb)(fd, pid, policynr, name, code, - emulation, args, argsize, intercept_gencbarg); - - if (action > 0) { - error = action; - action = ICPOLICY_NEVER; - } else { - icpid = intercept_findpid(pid); - if (icpid != NULL) - elevate = icpid->elevate; - else - elevate = NULL; - } - - /* Resume execution of the process */ - intercept.answer(fd, pid, seqnr, action, error, flags, elevate); -} - -void -intercept_syscall_result(int fd, pid_t pid, u_int16_t seqnr, int policynr, - const char *name, int code, const char *emulation, void *args, int argsize, - int result, void *rval) -{ - struct intercept_pid *icpid; - - if (result > 0) - goto out; - - icpid = intercept_getpid(pid); - if (!strcmp("execve", name)) { - intercept_newimage(fd, pid, policynr, - emulation, icpid->newname, icpid); - /* we might have detached by now */ - if (intercept_findpid(pid) == NULL) - return; - } - - out: - /* Resume execution of the process */ - intercept.answer(fd, pid, seqnr, 0, 0, 0, NULL); -} - -void -intercept_newimage(int fd, pid_t pid, int policynr, - const char *emulation, char *newname, struct intercept_pid *icpid) -{ - if (icpid == NULL) - icpid = intercept_getpid(pid); - - free(icpid->name); - if ((icpid->name = strdup(newname)) == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - - free(icpid->newname); - icpid->newname = NULL; - - if (intercept_newimagecb != NULL) - (*intercept_newimagecb)(fd, pid, policynr, emulation, - icpid->name, intercept_newimagecbarg); -} - -int -intercept_newpolicy(int fd) -{ - int policynr; - - policynr = intercept.newpolicy(fd); - - return (policynr); -} - -int -intercept_assignpolicy(int fd, pid_t pid, int policynr) -{ - return (intercept.assignpolicy(fd, pid, policynr)); -} - -int -intercept_modifypolicy_nr(int fd, int policynr, int code, short policy) -{ - return (intercept.policy(fd, policynr, code, policy)); -} - -int -intercept_modifypolicy(int fd, int policynr, const char *emulation, - const char *name, short policy) -{ - int code; - - code = intercept.getsyscallnumber(emulation, name); - if (code == -1) - return (-1); - - return (intercept.policy(fd, policynr, code, policy)); -} - -void -intercept_child_info(pid_t opid, pid_t npid) -{ - struct intercept_pid *ipid, *inpid, tmp; - - /* A child just died on us */ - if (npid == -1) { - intercept_freepid(opid); - return; - } - - tmp.pid = opid; - ipid = SPLAY_FIND(pidtree, &pids, &tmp); - if (ipid == NULL) - return; - - inpid = intercept_getpid(npid); - - inpid->policynr = ipid->policynr; - if (ipid->name != NULL) { - inpid->name = strdup(ipid->name); - if (inpid->name == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - } - - /* Process tree */ - inpid->ppid = opid; - - /* Copy some information */ - inpid->uid = ipid->uid; - inpid->gid = ipid->gid; - strlcpy(inpid->username, ipid->username, sizeof(inpid->username)); - strlcpy(inpid->home, ipid->home, sizeof(inpid->home)); - - /* XXX - keeps track of emulation */ - intercept.clonepid(ipid, inpid); -} - -void -intercept_ugid(struct intercept_pid *icpid, uid_t uid, gid_t gid) -{ - /* Update current home dir */ - if (icpid->uid != uid) { - struct passwd *pw; - - if ((pw = getpwuid(uid)) == NULL) { - snprintf(icpid->username, sizeof(icpid->username), - "uid %d", uid); - strlcpy(icpid->home, "/", sizeof(icpid->home)); - } else { - strlcpy(icpid->username, pw->pw_name, - sizeof(icpid->username)); - strlcpy(icpid->home, pw->pw_dir, sizeof(icpid->home)); - } - } - - icpid->uid = uid; - icpid->gid = gid; -} - -/* - * Returns the number of a system call - */ - -int -intercept_getsyscallnumber(const char *emulation, const char *name) -{ - int nr = intercept.getsyscallnumber(emulation, name); - - if (nr >= INTERCEPT_MAXSYSCALLNR) - err(1, "%s: system call number too high: %d", __func__, nr); - - return (nr); -} - -/* - * Checks if the given emulation has a certain system call. - * This is a very slow function. - */ - -int -intercept_isvalidsystemcall(const char *emulation, const char *name) -{ - int res; - - res = intercept.getsyscallnumber(emulation, 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); -} - -char * -intercept_realpath(const char *path, char *resolved) -{ - struct stat sb; - int idx = 0, n, nlnk = 0, serrno = errno; - const char *q; - char *p, wbuf[2][PATH_MAX]; - size_t len; - - /* - * Build real path one by one with paying an attention to ., - * .. and symbolic link. - */ - - /* - * `p' is where we'll put a new component with prepending - * a delimiter. - */ - p = resolved; - - if (*path == 0) { - *p = 0; - errno = ENOENT; - return (NULL); - } - - /* If relative path, start from current working directory. */ - if (*path != '/') { - if (getcwd(resolved, PATH_MAX) == NULL) { - p[0] = '.'; - p[1] = 0; - return (NULL); - } - len = strlen(resolved); - if (len > 1) - p += len; - } - -loop: - /* Skip any slash. */ - while (*path == '/') - path++; - - if (*path == 0) { - if (p == resolved) - *p++ = '/'; - *p = 0; - return (resolved); - } - - /* Find the end of this component. */ - q = path; - do - q++; - while (*q != '/' && *q != 0); - - /* Test . or .. */ - if (path[0] == '.') { - if (q - path == 1) { - path = q; - goto loop; - } - if (path[1] == '.' && q - path == 2) { - /* Trim the last component. */ - if (p != resolved) - while (*--p != '/') - ; - path = q; - goto loop; - } - } - - /* Append this component. */ - if (p - resolved + 1 + q - path + 1 > PATH_MAX) { - errno = ENAMETOOLONG; - if (p == resolved) - *p++ = '/'; - *p = 0; - return (NULL); - } - p[0] = '/'; - memcpy(&p[1], path, q - path); - p[1 + q - path] = 0; - - /* - * If this component is a symlink, toss it and prepend link - * target to unresolved path. - */ - if (lstat(resolved, &sb) == -1) { - /* Allow nonexistent component if this is the last one. */ - while (*q == '/') - q++; - - if (*q == 0 && errno == ENOENT) { - errno = serrno; - return (resolved); - } - - return (NULL); - } - if (S_ISLNK(sb.st_mode)) { - if (nlnk++ >= SYMLOOP_MAX) { - errno = ELOOP; - return (NULL); - } - n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1); - if (n < 0) - return (NULL); - if (n == 0) { - errno = ENOENT; - return (NULL); - } - - /* Append unresolved path to link target and switch to it. */ - if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) { - errno = ENAMETOOLONG; - return (NULL); - } - memcpy(&wbuf[idx][n], q, len + 1); - path = wbuf[idx]; - idx ^= 1; - - /* If absolute symlink, start from root. */ - if (*path == '/') - p = resolved; - goto loop; - } - if (*q == '/' && !S_ISDIR(sb.st_mode)) { - errno = ENOTDIR; - return (NULL); - } - - /* Advance both resolved and unresolved path. */ - p += 1 + q - path; - path = q; - goto loop; -} diff --git a/bin/systrace/intercept.h b/bin/systrace/intercept.h deleted file mode 100644 index 6d1715161be..00000000000 --- a/bin/systrace/intercept.h +++ /dev/null @@ -1,218 +0,0 @@ -/* $OpenBSD: intercept.h,v 1.27 2015/01/16 00:19:12 deraadt Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _INTERCEPT_H_ -#define _INTERCEPT_H_ -#include <sys/types.h> -#include <sys/queue.h> - -struct intercept_pid; -struct intercept_replace; -struct elevate; - -struct intercept_system { - char *name; - int (*init)(void); - int (*open)(void); - int (*attach)(int, pid_t); - int (*detach)(int, pid_t); - int (*report)(int, pid_t); - int (*read)(int); - int (*getsyscallnumber)(const char *, const char *); - int (*setcwd)(int, pid_t, int); - int (*restcwd)(int); - int (*io)(int, pid_t, int, void *, u_char *, size_t); - int (*getarg)(int, void *, int, void **); - int (*answer)(int, pid_t, u_int16_t, short, int, short, - struct elevate *); - int (*newpolicy)(int); - int (*assignpolicy)(int, pid_t, int); - int (*policy)(int, int, int, short); - int (*replace)(int, pid_t, u_int16_t, struct intercept_replace *); - void (*clonepid)(struct intercept_pid *, struct intercept_pid *); - void (*freepid)(struct intercept_pid *); - int (*scriptname)(int, pid_t, char *); -}; - -#define INTERCEPT_READ 1 -#define INTERCEPT_WRITE 2 - -#define ICPOLICY_ASK 0 -#define ICPOLICY_PERMIT -1 -#define ICPOLICY_KILL -2 -#define ICPOLICY_NEVER 1 /* overloaded with errno values > 1 */ - -#define ICLINK_NONE 0 /* do not resolve symlinks */ -#define ICLINK_ALL 1 /* resolve all symlinks */ -#define ICLINK_NOLAST 2 /* do not resolve last component */ - -#define ICFLAGS_RESULT 1 - -#define ICTRANS_NOLINKS 1 /* translation should have no symlinks */ - -/* Privilege elevation */ -struct elevate { -#define ELEVATE_UID 0x01 -#define ELEVATE_GID 0x02 - int e_flags; - uid_t e_uid; - gid_t e_gid; -}; - -struct intercept_pid { - SPLAY_ENTRY(intercept_pid) next; - pid_t pid; - pid_t ppid; /* parent pid */ - - int policynr; - int execve_code; - short execve_policy; - char *name; /* name of current process image */ - char *newname; /* image name to be committed by execve */ - - uid_t uid; /* current uid */ - gid_t gid; /* current gid */ - - char username[LOGIN_NAME_MAX]; - char home[PATH_MAX]; /* current home dir for uid */ - - void *data; - - int uflags; /* Flags that can be used by external application */ - struct elevate *elevate; /* privilege elevation request */ -}; - -#define INTERCEPT_MAXSYSCALLNR 512 -#define INTERCEPT_MAXSYSCALLARGS 10 - -struct intercept_translate { - char *name; - int (*translate)(struct intercept_translate *, int, pid_t, void *); - int (*print)(char *, size_t, struct intercept_translate *); - int off2; - int offend; - int off; - u_char trans_valid; - void *trans_addr; - void *trans_addr2; - void *trans_addrend; - void *trans_data; - size_t trans_size; - char *trans_print; - u_int trans_flags; - void *user; - TAILQ_ENTRY(intercept_translate) next; -}; - -struct intercept_replace { - int num; - int ind[INTERCEPT_MAXSYSCALLARGS]; - u_char *address[INTERCEPT_MAXSYSCALLARGS]; - size_t len[INTERCEPT_MAXSYSCALLARGS]; - u_int flags[INTERCEPT_MAXSYSCALLARGS]; -}; - -TAILQ_HEAD(intercept_tlq, intercept_translate); - -int intercept_init(void); -pid_t intercept_run(int, int *, uid_t, gid_t, char *, char * const *); -int intercept_open(void); -int intercept_attach(int, pid_t); -int intercept_attachpid(int, pid_t, char *); -int intercept_detach(int, pid_t); -int intercept_read(int); -int intercept_newpolicy(int); -int intercept_assignpolicy(int, pid_t, int); -int intercept_modifypolicy(int, int, const char *, const char *, short); -int intercept_modifypolicy_nr(int, int, int, 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, u_int); -int intercept_replace(int, pid_t, u_int16_t, struct intercept_replace *); - -int intercept_register_sccb(char *, char *, - short (*)(int, pid_t, int, const char *, int, const char *, void *, int, - struct intercept_replace *, struct intercept_tlq *, void *), - void *); -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 *); -int intercept_translate(struct intercept_translate *, int, pid_t, int, void *, int); -char *intercept_translate_print(struct intercept_translate *); - -#define intercept_register_transstring(x,y,z) \ - intercept_register_translation(x, y, z, &ic_translate_string) -#define intercept_register_transfn(x,y,z) \ - intercept_register_translation(x, y, z, &ic_translate_filename) -#define intercept_register_translink(x,y,z) \ - intercept_register_translation(x, y, z, &ic_translate_linkname) - -extern struct intercept_translate ic_translate_string; -extern struct intercept_translate ic_translate_filename; -extern struct intercept_translate ic_translate_linkname; -extern struct intercept_translate ic_translate_unlinkname; -extern struct intercept_translate ic_translate_filenameat; -extern struct intercept_translate ic_translate_unlinknameat; -extern struct intercept_translate ic_translate_filenameatflag; -extern struct intercept_translate ic_translate_unlinknameatflag; -extern struct intercept_translate ic_translate_connect; -extern struct intercept_translate ic_translate_sendmsg; - -void intercept_freepid(pid_t); -struct intercept_pid *intercept_findpid(pid_t); -struct intercept_pid *intercept_getpid(pid_t); -int intercept_existpids(void); - -char *intercept_get_string(int, pid_t, void *); -char *normalize_filename(int, pid_t, char *, int); -char *normalize_filenameat(int, pid_t, int, char *, int); -char *intercept_filename(int, pid_t, void *, int, char *); -char *intercept_filenameat(int, pid_t, int, void *, int, char *); -void intercept_syscall(int, pid_t, u_int16_t, int, const char *, int, - const char *, void *, int); -void intercept_syscall_result(int, pid_t, u_int16_t, int, const char *, int, - const char *, void *, int, int, void *); -void intercept_newimage(int, pid_t, int, - const char *, char *, struct intercept_pid *); -void intercept_ugid(struct intercept_pid *, uid_t, gid_t); -void intercept_setpid(struct intercept_pid *, uid_t, gid_t); - -int intercept_getsyscallnumber(const char *, const char *); -int intercept_isvalidsystemcall(const char *, const char *); - -#endif /* _INTERCEPT_H_ */ diff --git a/bin/systrace/lex.l b/bin/systrace/lex.l deleted file mode 100644 index e23d68f0b36..00000000000 --- a/bin/systrace/lex.l +++ /dev/null @@ -1,162 +0,0 @@ -/* $OpenBSD: lex.l,v 1.20 2015/04/18 18:28:37 deraadt Exp $ */ - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (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 quote - -%{ -#include <sys/types.h> -#include <sys/tree.h> - -#include <sys/time.h> - -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <err.h> -#include <stdarg.h> -#include <string.h> - -#include "intercept.h" -#include "systrace.h" -#include "y.tab.h" - -extern int yyerror(const char *fmt, ...); -int yylex(void); - -char *mystring; -int myoff; - -char quotestr[8192]; -int quoteescape; - -#define YY_INPUT(buf,result,max_size) \ -{ \ - int len = strlen(mystring + myoff); \ - if (max_size < len) \ - len = max_size; \ - if (len == 0) \ - result = YY_NULL; \ - else { \ - memcpy(buf, mystring + myoff, len); \ - myoff += len; \ - result = len; \ - } \ -} -%} - -%% -ask { return ASK; } -deny { return DENY; } -permit { return PERMIT; } -and { return AND; } -or { return OR; } -not { return NOT; } -match { return MATCH; } -then { return THEN; } -eq { return EQ; } -neq { return NEQ; } -sub { return SUB; } -nsub { return NSUB; } -inpath { return INPATH; } -re { return RE; } -log { return LOG; } -true { return TRUE; } -"->" { return THEN; } -\( { return LBRACE; } -\) { return RBRACE; } -if { return IF; } -user { return USER; } -group { return GROUP; } -as { return AS; } -":" { return COLON; } -"," { return COMMA; } -"=" { return EQUAL; } -"!=" { return NEQUAL; } -"<" { return LESSER; } -">" { return GREATER; } -[\_\$A-Za-z][\.\(\)\/A-Za-z_\-0-9]*\$? { yylval.string = strdup(yytext); return STRING; } -[0-9]+ { - const char *errstr; - yylval.number = strtonum(yytext, 0, INT_MAX, &errstr); - if (errstr) { - yyerror("number %s: %s", yytext, errstr); - } - return NUMBER; - } -\" { 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; } -\ { ; } -\n { ; } -\t { ; } -"#".*\n { ; } -. { yyerror("illegal token"); } -%% -#ifndef yywrap -int yywrap() { return 1; } -#endif diff --git a/bin/systrace/openbsd-syscalls.c b/bin/systrace/openbsd-syscalls.c deleted file mode 100644 index 1dc71d22e59..00000000000 --- a/bin/systrace/openbsd-syscalls.c +++ /dev/null @@ -1,651 +0,0 @@ -/* $OpenBSD: openbsd-syscalls.c,v 1.47 2016/03/01 16:26:06 naddy Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include <sys/types.h> - -#include <sys/syscall.h> - -#define KTRACE -#define PTRACE -#define NFSCLIENT -#define NFSSERVER -#define SYSVSEM -#define SYSVMSG -#define SYSVSHM -#include <kern/syscalls.c> -#undef KTRACE -#undef PTRACE -#undef NFSCLIENT -#undef NFSSERVER -#undef SYSVSEM -#undef SYSVMSG -#undef SYSVSHM - -#include <limits.h> - -#include <sys/ioctl.h> -#include <sys/tree.h> -#include <dev/systrace.h> - -#include <stdio.h> -#include <stdlib.h> -#include <fcntl.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <err.h> - -#include "intercept.h" - -struct emulation { - const char *name; /* Emulation name */ - char **sysnames; /* Array of system call names */ - int nsysnames; /* Number of */ -}; - -static struct emulation emulations[] = { - { "native", syscallnames, SYS_MAXSYSCALL }, - { NULL, NULL, 0 } -}; - -struct obsd_data { - struct emulation *current; - struct emulation *commit; -}; - -static int obsd_init(void); -static int obsd_attach(int, pid_t); -static int obsd_report(int, pid_t); -static int obsd_detach(int, pid_t); -static int obsd_open(void); -static struct intercept_pid *obsd_getpid(pid_t); -static void obsd_freepid(struct intercept_pid *); -static void obsd_clonepid(struct intercept_pid *, struct intercept_pid *); -static struct emulation *obsd_find_emulation(const char *); -static int obsd_set_emulation(pid_t, const char *); -static struct emulation *obsd_switch_emulation(struct obsd_data *); -static const char *obsd_syscall_name(pid_t, int); -static int obsd_syscall_number(const char *, const char *); -static short obsd_translate_policy(short); -static short obsd_translate_flags(short); -static int obsd_translate_errno(int); -static int obsd_answer(int, pid_t, u_int16_t, short, int, short, - struct elevate *); -static int obsd_newpolicy(int); -static int obsd_assignpolicy(int, pid_t, int); -static int obsd_modifypolicy(int, int, int, short); -static int obsd_replace(int, pid_t, u_int16_t, struct intercept_replace *); -static int obsd_io(int, pid_t, int, void *, u_char *, size_t); -static int obsd_setcwd(int, pid_t, int); -static int obsd_restcwd(int); -static int obsd_argument(int, void *, int, void **); -static int obsd_read(int); -static int obsd_scriptname(int, pid_t, char *); - -static int -obsd_init(void) -{ - return (0); -} - -static int -obsd_attach(int fd, pid_t pid) -{ - if (ioctl(fd, STRIOCATTACH, &pid) == -1) - return (-1); - - return (0); -} - -static int -obsd_report(int fd, pid_t pid) -{ - if (ioctl(fd, STRIOCREPORT, &pid) == -1) - return (-1); - - return (0); -} - -static int -obsd_detach(int fd, pid_t pid) -{ - if (ioctl(fd, STRIOCDETACH, &pid) == -1) - return (-1); - - return (0); -} - -static int -obsd_open(void) -{ - char *path = "/dev/systrace"; - int fd, cfd = -1; - - fd = open(path, O_RDONLY, 0); - if (fd == -1) { - warn("open: %s", path); - return (-1); - } - - if (ioctl(fd, STRIOCCLONE, &cfd) == -1) { - warn("ioctl(STRIOCCLONE)"); - goto out; - } - - if (fcntl(cfd, F_SETFD, FD_CLOEXEC) == -1) - warn("fcntl(F_SETFD)"); - - out: - close (fd); - return (cfd); -} - -static struct intercept_pid * -obsd_getpid(pid_t pid) -{ - struct intercept_pid *icpid; - struct obsd_data *data; - - icpid = intercept_getpid(pid); - if (icpid == NULL) - return (NULL); - if (icpid->data != NULL) - return (icpid); - - if ((icpid->data = malloc(sizeof(struct obsd_data))) == NULL) - err(1, "%s:%d: malloc", __func__, __LINE__); - - data = icpid->data; - data->current = &emulations[0]; - data->commit = NULL; - - return (icpid); -} - -static void -obsd_freepid(struct intercept_pid *ipid) -{ - free(ipid->data); -} - -static void -obsd_clonepid(struct intercept_pid *opid, struct intercept_pid *npid) -{ - if (opid->data == NULL) { - npid->data = NULL; - return; - } - - if ((npid->data = malloc(sizeof(struct obsd_data))) == NULL) - err(1, "%s:%d: malloc", __func__, __LINE__); - memcpy(npid->data, opid->data, sizeof(struct obsd_data)); -} - -static struct emulation * -obsd_find_emulation(const char *name) -{ - struct emulation *tmp; - - tmp = emulations; - while (tmp->name) { - if (!strcmp(tmp->name, name)) - break; - tmp++; - } - - if (!tmp->name) - return (NULL); - - return (tmp); -} - -static int -obsd_set_emulation(pid_t pidnr, const char *name) -{ - struct emulation *tmp; - struct intercept_pid *pid; - struct obsd_data *data; - - if ((tmp = obsd_find_emulation(name)) == NULL) - return (-1); - - pid = intercept_getpid(pidnr); - if (pid == NULL) - return (-1); - data = pid->data; - - data->commit = tmp; - - return (0); -} - -static struct emulation * -obsd_switch_emulation(struct obsd_data *data) -{ - data->current = data->commit; - data->commit = NULL; - - return (data->current); -} - -static const char * -obsd_syscall_name(pid_t pidnr, int number) -{ - struct intercept_pid *pid; - struct emulation *current; - - pid = obsd_getpid(pidnr); - if (pid == NULL) - return (NULL); - current = ((struct obsd_data *)pid->data)->current; - - if (number < 0 || number >= current->nsysnames) - return (NULL); - - return (current->sysnames[number]); -} - -static int -obsd_syscall_number(const char *emulation, const char *name) -{ - struct emulation *current; - int i; - - current = obsd_find_emulation(emulation); - if (current == NULL) - return (-1); - - for (i = 0; i < current->nsysnames; i++) - if (!strcmp(name, current->sysnames[i])) - return (i); - - return (-1); -} - -static short -obsd_translate_policy(short policy) -{ - switch (policy) { - case ICPOLICY_ASK: - return (SYSTR_POLICY_ASK); - case ICPOLICY_PERMIT: - return (SYSTR_POLICY_PERMIT); - case ICPOLICY_NEVER: - default: - return (SYSTR_POLICY_NEVER); - } -} - -static short -obsd_translate_flags(short flags) -{ - switch (flags) { - case ICFLAGS_RESULT: - return (SYSTR_FLAGS_RESULT); - default: - return (0); - } -} - -static int -obsd_translate_errno(int nerrno) -{ - return (nerrno); -} - -static int -obsd_answer(int fd, pid_t pid, u_int16_t seqnr, short policy, int nerrno, - short flags, struct elevate *elevate) -{ - struct systrace_answer ans; - - memset(&ans, 0, sizeof(ans)); - ans.stra_pid = pid; - ans.stra_seqnr = seqnr; - ans.stra_policy = obsd_translate_policy(policy); - ans.stra_flags = obsd_translate_flags(flags); - ans.stra_error = obsd_translate_errno(nerrno); - - if (elevate != NULL) { - if (elevate->e_flags & ELEVATE_UID) { - ans.stra_flags |= SYSTR_FLAGS_SETEUID; - ans.stra_seteuid = elevate->e_uid; - } - if (elevate->e_flags & ELEVATE_GID) { - ans.stra_flags |= SYSTR_FLAGS_SETEGID; - ans.stra_setegid = elevate->e_gid; - } - } - - if (ioctl(fd, STRIOCANSWER, &ans) == -1) - return (-1); - - return (0); -} - -static int -obsd_scriptname(int fd, pid_t pid, char *scriptname) -{ - struct systrace_scriptname sn; - - sn.sn_pid = pid; - strlcpy(sn.sn_scriptname, scriptname, sizeof(sn.sn_scriptname)); - - return (ioctl(fd, STRIOCSCRIPTNAME, &sn)); -} - -static int -obsd_newpolicy(int fd) -{ - struct systrace_policy pol; - - pol.strp_op = SYSTR_POLICY_NEW; - pol.strp_num = -1; - pol.strp_maxents = 512; - - if (ioctl(fd, STRIOCPOLICY, &pol) == -1) - return (-1); - - return (pol.strp_num); -} - -static int -obsd_assignpolicy(int fd, pid_t pid, int num) -{ - struct systrace_policy pol; - - pol.strp_op = SYSTR_POLICY_ASSIGN; - pol.strp_num = num; - pol.strp_pid = pid; - - if (ioctl(fd, STRIOCPOLICY, &pol) == -1) - return (-1); - - return (0); -} - -static int -obsd_modifypolicy(int fd, int num, int code, short policy) -{ - struct systrace_policy pol; - - pol.strp_op = SYSTR_POLICY_MODIFY; - pol.strp_num = num; - pol.strp_code = code; - pol.strp_policy = obsd_translate_policy(policy); - - if (ioctl(fd, STRIOCPOLICY, &pol) == -1) - return (-1); - - return (0); -} - -static int -obsd_replace(int fd, pid_t pid, u_int16_t seqnr, - struct intercept_replace *repl) -{ - struct systrace_replace replace; - size_t len, off; - int i, ret; - - memset(&replace, 0, sizeof(replace)); - - for (i = 0, len = 0; i < repl->num; i++) { - len += repl->len[i]; - } - - replace.strr_pid = pid; - replace.strr_seqnr = seqnr; - replace.strr_nrepl = repl->num; - replace.strr_base = malloc(len); - replace.strr_len = len; - if (replace.strr_base == NULL) - err(1, "%s: malloc", __func__); - - for (i = 0, off = 0; i < repl->num; i++) { - replace.strr_argind[i] = repl->ind[i]; - replace.strr_offlen[i] = repl->len[i]; - if (repl->len[i] == 0) { - replace.strr_off[i] = (size_t)repl->address[i]; - continue; - } - - replace.strr_off[i] = off; - memcpy(replace.strr_base + off, - repl->address[i], repl->len[i]); - if (repl->flags[i] & ICTRANS_NOLINKS) { - replace.strr_flags[i] = SYSTR_NOLINKS; - } else - replace.strr_flags[i] = 0; - - off += repl->len[i]; - } - - ret = ioctl(fd, STRIOCREPLACE, &replace); - if (ret == -1 && errno != EBUSY) { - warn("%s: ioctl", __func__); - } - - free(replace.strr_base); - - return (ret); -} - -static int -obsd_io(int fd, pid_t pid, int op, void *addr, u_char *buf, size_t size) -{ - struct systrace_io io; - extern int ic_abort; - - memset(&io, 0, sizeof(io)); - io.strio_pid = pid; - io.strio_addr = buf; - io.strio_len = size; - io.strio_offs = addr; - io.strio_op = (op == INTERCEPT_READ ? SYSTR_READ : SYSTR_WRITE); - if (ioctl(fd, STRIOCIO, &io) == -1) { - if (errno == EBUSY) - ic_abort = 1; - return (-1); - } - - return (0); -} - -static int -obsd_setcwd(int fd, pid_t pid, int atfd) -{ - struct systrace_getcwd gd; - gd.strgd_pid = pid; - gd.strgd_atfd = atfd; - return (ioctl(fd, STRIOCGETCWD, &gd)); -} - -static int -obsd_restcwd(int fd) -{ - int res; - if ((res = ioctl(fd, STRIOCRESCWD, 0)) == -1) - warn("%s: ioctl", __func__); /* XXX */ - - return (res); -} - -static int -obsd_argument(int off, void *pargs, int argsize, void **pres) -{ - register_t *args = (register_t *)pargs; - - if (off >= argsize / sizeof(register_t)) - return (-1); - - *pres = (void *)args[off]; - - return (0); -} - -static int -obsd_read(int fd) -{ - struct str_message msg; - struct intercept_pid *icpid; - struct obsd_data *data; - struct emulation *current; - - char name[SYSTR_EMULEN+1]; - const char *sysname; - u_int16_t seqnr; - pid_t pid; - int code; - - if (read(fd, &msg, sizeof(msg)) != sizeof(msg)) - return (-1); - - icpid = obsd_getpid(msg.msg_pid); - if (icpid == NULL) - return (-1); - data = icpid->data; - - current = data->current; - - seqnr = msg.msg_seqnr; - pid = msg.msg_pid; - switch (msg.msg_type) { - case SYSTR_MSG_ASK: - code = msg.msg_data.msg_ask.code; - sysname = obsd_syscall_name(pid, code); - - intercept_syscall(fd, pid, seqnr, msg.msg_policy, - sysname, code, current->name, - (void *)msg.msg_data.msg_ask.args, - msg.msg_data.msg_ask.argsize); - break; - - case SYSTR_MSG_RES: - code = msg.msg_data.msg_ask.code; - sysname = obsd_syscall_name(pid, code); - - /* Switch emulation around at the right time */ - if (data->commit != NULL) { - current = obsd_switch_emulation(data); - } - - intercept_syscall_result(fd, pid, seqnr, msg.msg_policy, - sysname, code, current->name, - (void *)msg.msg_data.msg_ask.args, - msg.msg_data.msg_ask.argsize, - msg.msg_data.msg_ask.result, - msg.msg_data.msg_ask.rval); - break; - - case SYSTR_MSG_EMUL: - memcpy(name, msg.msg_data.msg_emul.emul, SYSTR_EMULEN); - name[SYSTR_EMULEN] = '\0'; - - if (obsd_set_emulation(pid, name) == -1) - errx(1, "%s:%d: set_emulation(%s)", - __func__, __LINE__, name); - - if (icpid->execve_code == -1) { - icpid->execve_code = 0; - - /* A running attach fake a exec cb */ - current = obsd_switch_emulation(data); - - intercept_syscall_result(fd, - pid, seqnr, msg.msg_policy, - "execve", 0, current->name, - NULL, 0, 0, NULL); - break; - } - - if (obsd_answer(fd, pid, seqnr, 0, 0, 0, NULL) == -1) - err(1, "%s:%d: answer", __func__, __LINE__); - break; - - case SYSTR_MSG_UGID: { - struct str_msg_ugid *msg_ugid; - - msg_ugid = &msg.msg_data.msg_ugid; - - intercept_ugid(icpid, msg_ugid->uid, msg_ugid->uid); - - if (obsd_answer(fd, pid, seqnr, 0, 0, 0, NULL) == -1) - err(1, "%s:%d: answer", __func__, __LINE__); - break; - } - case SYSTR_MSG_CHILD: - intercept_child_info(msg.msg_pid, - msg.msg_data.msg_child.new_pid); - break; -#ifdef SYSTR_MSG_EXECVE - case SYSTR_MSG_EXECVE: { - struct str_msg_execve *msg_execve = &msg.msg_data.msg_execve; - - intercept_newimage(fd, pid, msg.msg_policy, current->name, - msg_execve->path, NULL); - - if (obsd_answer(fd, pid, seqnr, 0, 0, 0, NULL) == -1) - err(1, "%s:%d: answer", __func__, __LINE__); - break; - } -#endif - -#ifdef SYSTR_MSG_POLICYFREE - case SYSTR_MSG_POLICYFREE: - intercept_policy_free(msg.msg_policy); - break; -#endif - } - return (0); -} - -struct intercept_system intercept = { - "openbsd", - obsd_init, - obsd_open, - obsd_attach, - obsd_detach, - obsd_report, - obsd_read, - obsd_syscall_number, - obsd_setcwd, - obsd_restcwd, - obsd_io, - obsd_argument, - obsd_answer, - obsd_newpolicy, - obsd_assignpolicy, - obsd_modifypolicy, - obsd_replace, - obsd_clonepid, - obsd_freepid, - obsd_scriptname, -}; diff --git a/bin/systrace/parse.y b/bin/systrace/parse.y deleted file mode 100644 index bc8cad56df2..00000000000 --- a/bin/systrace/parse.y +++ /dev/null @@ -1,524 +0,0 @@ -/* $OpenBSD: parse.y,v 1.19 2015/01/16 00:19:12 deraadt Exp $ */ - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -%{ -#include <sys/types.h> - -#include <sys/time.h> -#include <sys/tree.h> - -#include <stdio.h> -#include <stdlib.h> -#include <err.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> -#include <limits.h> -#include <pwd.h> -#include <grp.h> -#include <regex.h> - -#include "intercept.h" -#include "systrace.h" -#include "systrace-errno.h" -#include "filter.h" - -void yyrestart(FILE *); - -struct logic *parse_newsymbol(char *, int, char *); - -int yylex(void); -int yyparse(void); -int yyerror(const char *, ...); - -int errors = 0; -struct filter *myfilter; -extern char *mystring; -extern int myoff; -extern int iamroot; - -%} - -%token AND OR NOT LBRACE RBRACE LSQBRACE RSQBRACE THEN MATCH PERMIT DENY ASK -%token EQ NEQ TRUE SUB NSUB INPATH LOG COMMA IF USER GROUP EQUAL NEQUAL AS -%token COLON RE LESSER GREATER -%token <string> STRING -%token <string> CMDSTRING -%token <number> NUMBER -%type <logic> expression -%type <logic> symbol -%type <action> action -%type <number> typeoff -%type <number> logcode -%type <uid> uid -%type <gid> gid -%type <string> errorcode -%type <predicate> predicate -%type <elevate> elevate; -%union { - int number; - char *string; - short action; - struct logic *logic; - struct predicate predicate; - struct elevate elevate; - uid_t uid; - gid_t gid; -} -%% - -fullexpression : expression THEN action errorcode logcode elevate predicate - { - int flags = 0, errorcode = SYSTRACE_EPERM; - - switch ($3) { - case ICPOLICY_NEVER: - if ($4 == NULL) - break; - errorcode = systrace_error_translate($4); - if (errorcode == -1) - yyerror("Unknown error code: %s", $4); - break; - case ICPOLICY_PERMIT: - if ($4 == NULL) - break; - if (!strcasecmp($4, "inherit")) - flags = PROCESS_INHERIT_POLICY; - else if (!strcasecmp($4, "detach")) - flags = PROCESS_DETACH; - else - yyerror("Unknown flag: %s", $4); - break; - } - - if ($5) - flags |= SYSCALL_LOG; - - /* Special policy that allows only yes or no */ - if ($3 == ICPOLICY_ASK) - flags |= PROCESS_PROMPT; - - if ($4 != NULL) - free($4); - - myfilter = calloc(1, sizeof(struct filter)); - if (myfilter == NULL) { - yyerror("calloc"); - break; - } - myfilter->logicroot = $1; - myfilter->match_action = $3; - myfilter->match_error = errorcode; - myfilter->match_flags = flags; - myfilter->match_predicate = $7; - myfilter->elevate = $6; - } -; - -errorcode : /* Empty */ -{ - $$ = NULL; -} - | LSQBRACE STRING RSQBRACE -{ - $$ = $2; -} -; - -logcode : /* Empty */ -{ - $$ = 0; -} - | LOG -{ - $$ = 1; -} -; - - -uid : NUMBER -{ - $$ = $1; -} - | STRING -{ - struct passwd *pw; - if ((pw = getpwnam($1)) == NULL) { - yyerror("Unknown user %s", $1); - break; - } - - $$ = pw->pw_uid; -} - -gid : NUMBER -{ - $$ = $1; -} - | STRING -{ - struct group *gr; - if ((gr = getgrnam($1)) == NULL) { - yyerror("Unknown group %s", $1); - break; - } - - $$ = gr->gr_gid; -} - -elevate: /* Empty */ -{ - memset(&$$, 0, sizeof($$)); -} - | AS uid -{ - if (!iamroot) { - yyerror("Privilege elevation not allowed."); - break; - } - - $$.e_flags = ELEVATE_UID; - $$.e_uid = $2; -} - | AS uid COLON gid -{ - if (!iamroot) { - yyerror("Privilege elevation not allowed."); - break; - } - - $$.e_flags = ELEVATE_UID|ELEVATE_GID; - $$.e_uid = $2; - $$.e_gid = $4; -} - | AS COLON gid -{ - if (!iamroot) { - yyerror("Privilege elevation not allowed."); - break; - } - - $$.e_flags = ELEVATE_GID; - $$.e_gid = $3; -} - -predicate : /* Empty */ -{ - memset(&$$, 0, sizeof($$)); -} - | COMMA IF USER EQUAL uid -{ - memset(&$$, 0, sizeof($$)); - $$.p_uid = $5; - $$.p_flags = PREDIC_UID; -} - | COMMA IF USER NEQUAL uid -{ - memset(&$$, 0, sizeof($$)); - $$.p_uid = $5; - $$.p_flags = PREDIC_UID | PREDIC_NEGATIVE; -} - | COMMA IF USER LESSER uid -{ - memset(&$$, 0, sizeof($$)); - $$.p_uid = $5; - $$.p_flags = PREDIC_UID | PREDIC_LESSER; -} - | COMMA IF USER GREATER uid -{ - memset(&$$, 0, sizeof($$)); - $$.p_uid = $5; - $$.p_flags = PREDIC_UID | PREDIC_GREATER; -} - | COMMA IF GROUP EQUAL gid -{ - memset(&$$, 0, sizeof($$)); - $$.p_gid = $5; - $$.p_flags = PREDIC_GID; -} - | COMMA IF GROUP NEQUAL gid -{ - memset(&$$, 0, sizeof($$)); - $$.p_gid = $5; - $$.p_flags = PREDIC_GID | PREDIC_NEGATIVE; -} - | COMMA IF GROUP LESSER gid -{ - memset(&$$, 0, sizeof($$)); - $$.p_gid = $5; - $$.p_flags = PREDIC_GID | PREDIC_LESSER; -} - | COMMA IF GROUP GREATER gid -{ - memset(&$$, 0, sizeof($$)); - $$.p_gid = $5; - $$.p_flags = PREDIC_GID | PREDIC_GREATER; -} - -expression : symbol -{ - $$ = $1; -} - | NOT expression -{ - struct logic *node; - node = calloc(1, sizeof(struct logic)); - if (node == NULL) { - yyerror("calloc"); - break; - } - node->op = LOGIC_NOT; - node->left = $2; - $$ = node; -} - | LBRACE expression RBRACE -{ - $$ = $2; -} - | expression AND expression -{ - struct logic *node; - node = calloc(1, sizeof(struct logic)); - if (node == NULL) { - yyerror("calloc"); - break; - } - node->op = LOGIC_AND; - node->left = $1; - node->right = $3; - $$ = node; -} - | expression OR expression -{ - struct logic *node; - node = calloc(1, sizeof(struct logic)); - if (node == NULL) { - yyerror("calloc"); - break; - } - node->op = LOGIC_OR; - node->left = $1; - node->right = $3; - $$ = node; -} -; - -symbol : STRING typeoff MATCH CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_fnmatch; - $$ = node; -} - | STRING typeoff EQ CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_stringmatch; - $$ = node; -} - | STRING typeoff NEQ CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_negstringmatch; - $$ = node; -} - | STRING typeoff SUB CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_substrmatch; - $$ = node; -} - | STRING typeoff NSUB CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_negsubstrmatch; - $$ = node; -} - | STRING typeoff INPATH CMDSTRING -{ - struct logic *node; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - node->filter_match = filter_inpath; - $$ = node; -} - | STRING typeoff RE CMDSTRING -{ - struct logic *node; - regex_t re; - - if ((node = parse_newsymbol($1, $2, $4)) == NULL) - break; - - /* Precompute regexp here, otherwise we need to compute it - * on the fly which is fairly expensive. - */ - if (!(node->flags & LOGIC_NEEDEXPAND)) { - if (regcomp(&re, node->filterdata, - REG_EXTENDED | REG_NOSUB) != 0) { - yyerror("Invalid regular expression: %s", - node->filterdata); - break; - } - if ((node->filterarg = malloc(sizeof(re))) == NULL) { - yyerror("malloc"); - break; - } - memcpy(node->filterarg, &re, sizeof(re)); - } else - node->filterarg = NULL; - - node->filter_match = filter_regex; - $$ = node; -} - | TRUE -{ - struct logic *node; - - if ((node = parse_newsymbol(NULL, -1, NULL)) == NULL) - break; - - node->filter_match = filter_true; - $$ = node; -} -; - -typeoff : /* empty */ -{ - $$ = -1; -} - | LSQBRACE NUMBER RSQBRACE -{ - if ($2 < 0 || $2 >= INTERCEPT_MAXSYSCALLARGS) { - yyerror("Bad offset: %d", $2); - break; - } - $$ = $2; -} -; -action : PERMIT -{ - $$ = ICPOLICY_PERMIT; -} - | ASK -{ - $$ = ICPOLICY_ASK; -} - | DENY -{ - $$ = ICPOLICY_NEVER; -} -%% - -int -yyerror(const char *fmt, ...) -{ - va_list ap; - errors = 1; - - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - fprintf(stderr, "\n"); - va_end(ap); - return (0); -} - -struct logic * -parse_newsymbol(char *type, int typeoff, char *data) -{ - struct logic *node; - - node = calloc(1, sizeof(struct logic)); - - if (node == NULL) { - yyerror("calloc"); - return (NULL); - } - node->op = LOGIC_SINGLE; - node->type = type; - node->typeoff = typeoff; - if (data) { - /* For the root user, variable expansion may change */ - if (iamroot) { - node->filterdata = data; - if (filter_needexpand(data)) - node->flags |= LOGIC_NEEDEXPAND; - } else { - node->filterdata = strdup(filter_expand(data)); - free(data); - } - if (node->filterdata == NULL) { - yyerror("strdup"); - free(node); - return (NULL); - } - node->filterlen = strlen(node->filterdata) + 1; - } - - return (node); -} - -int -parse_filter(char *name, struct filter **pfilter) -{ - - errors = 0; - - myfilter = NULL; - mystring = name; - myoff = 0; - - yyparse(); - yyrestart(NULL); - *pfilter = myfilter; - return (errors ? -1 : 0); -} diff --git a/bin/systrace/policy.c b/bin/systrace/policy.c deleted file mode 100644 index a933b9ee4ca..00000000000 --- a/bin/systrace/policy.c +++ /dev/null @@ -1,907 +0,0 @@ -/* $OpenBSD: policy.c,v 1.36 2015/12/30 14:59:10 tedu Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/tree.h> -#include <dirent.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <grp.h> -#include <stdio.h> -#include <fcntl.h> -#include <ctype.h> -#include <err.h> -#include <libgen.h> - -#include "intercept.h" -#include "systrace.h" - -static int psccompare(struct policy_syscall *, struct policy_syscall *); -static int policycompare(struct policy *, struct policy *); -static int polnrcompare(struct policy *, struct policy *); -static char *systrace_policyfilename(char *, const char *); -static char *systrace_policyline(char *line); -static int systrace_policyprocess(struct policy *, - char *); -static int systrace_writepolicy(struct policy *); - -int systrace_templatedir(void); - -static int -psccompare(struct policy_syscall *a, struct policy_syscall *b) -{ - int diff; - diff = strcmp(a->emulation, b->emulation); - if (diff) - return (diff); - return (strcmp(a->name, b->name)); -} - -SPLAY_PROTOTYPE(syscalltree, policy_syscall, node, psccompare) -SPLAY_GENERATE(syscalltree, policy_syscall, node, psccompare) - -static SPLAY_HEAD(policytree, policy) policyroot; -static SPLAY_HEAD(polnrtree, policy) polnrroot; - -int -policycompare(struct policy *a, struct policy *b) -{ - return (strcmp(a->name, b->name)); -} - -int -polnrcompare(struct policy *a, struct policy *b) -{ - int diff = a->policynr - b->policynr; - - if (diff == 0) - return (0); - if (diff > 0 ) - return (1); - return (-1); -} - -SPLAY_PROTOTYPE(policytree, policy, node, policycompare) -SPLAY_GENERATE(policytree, policy, node, policycompare) - -SPLAY_PROTOTYPE(polnrtree, policy, nrnode, polnrcompare) -SPLAY_GENERATE(polnrtree, policy, nrnode, polnrcompare) - -extern int userpolicy; - -static char policydir[PATH_MAX]; - -struct tmplqueue templates; - -void -systrace_setupdir(char *path) -{ - char *home; - struct stat sb; - - if (path == NULL) { - home = getenv("HOME"); - - if (home == NULL) - errx(1, "No HOME environment set"); - - if (strlcpy(policydir, home, sizeof(policydir)) >= sizeof(policydir)) - errx(1, "HOME too long"); - - if (strlcat(policydir, "/.systrace", sizeof(policydir)) >= sizeof(policydir)) - errx(1, "HOME too long"); - } else if (strlcpy(policydir, path, sizeof(policydir)) >= sizeof(policydir)) - errx(1, "policy directory too long"); - - - if (stat(policydir, &sb) != -1) { - if (!S_ISDIR(sb.st_mode)) - errx(1, "Not a directory: \"%s\"", policydir); - } else if (mkdir(policydir, 0700) == -1) - err(1, "mkdir(%s)", policydir); -} - -int -systrace_initpolicy(char *file, char *path) -{ - SPLAY_INIT(&policyroot); - SPLAY_INIT(&polnrroot); - - if (userpolicy) { - systrace_setupdir(path); - systrace_templatedir(); - } - - if (file != NULL) - return (systrace_readpolicy(file) != NULL ? 0 : -1); - - return (0); -} - -struct policy * -systrace_findpolicy(const char *name) -{ - struct policy tmp; - - tmp.name = name; - - return (SPLAY_FIND(policytree, &policyroot, &tmp)); -} - -struct policy * -systrace_findpolicy_wildcard(const char *name) -{ - struct policy tmp, *res; - static char path[PATH_MAX], lookup[PATH_MAX]; - - if (strlcpy(path, name, sizeof(path)) >= sizeof(path)) - errx(1, "%s: path name overflow", __func__); - - strlcpy(lookup, "*/", sizeof(lookup)); - strlcat(lookup, basename(path), sizeof(lookup)); - - tmp.name = lookup; - res = SPLAY_FIND(policytree, &policyroot, &tmp); - if (res == NULL) - return (NULL); - - /* we found the wildcarded policy; now remove it and bind it */ - SPLAY_REMOVE(policytree, &policyroot, res); - - free((char *)res->name); - if ((res->name = strdup(name)) == NULL) - err(1, "%s: strdup", __func__); - - SPLAY_INSERT(policytree, &policyroot, res); - return (res); -} - -struct policy * -systrace_findpolnr(int nr) -{ - struct policy tmp; - - tmp.policynr = nr; - - return (SPLAY_FIND(polnrtree, &polnrroot, &tmp)); -} - -int -systrace_newpolicynr(int fd, struct policy *tmp) -{ - if (tmp->policynr != -1) - return (-1); - - if ((tmp->policynr = intercept_newpolicy(fd)) == -1) { - /* XXX - maybe free policy structure here */ - return (-1); - } - - SPLAY_INSERT(polnrtree, &polnrroot, tmp); - - return (tmp->policynr); -} - -struct policy * -systrace_newpolicy(const char *emulation, const char *name) -{ - int i; - struct policy *tmp; - - if ((tmp = systrace_findpolicy(name)) != NULL) - return (tmp); - - if ((tmp = systrace_findpolicy_wildcard(name)) != NULL) - return (tmp); - - tmp = calloc(1, sizeof(struct policy)); - if (tmp == NULL) - return (NULL); - - tmp->policynr = -1; - - /* New policies requires initialization */ - if ((tmp->name = strdup(name)) == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - strlcpy(tmp->emulation, emulation, sizeof(tmp->emulation)); - - SPLAY_INSERT(policytree, &policyroot, tmp); - SPLAY_INIT(&tmp->pflqs); - TAILQ_INIT(&tmp->filters); - TAILQ_INIT(&tmp->prefilters); - - /* Set the default policy to ask */ - for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++) - tmp->kerneltable[i] = ICPOLICY_ASK; - - return (tmp); -} - -void -systrace_cleanpolicy(struct policy *policy) -{ - struct filter *filter; - struct policy_syscall *pflq; - int i; - - /* Set the default policy to ask */ - for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++) - policy->kerneltable[i] = ICPOLICY_ASK; - - 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); - } -} - -void -systrace_freepolicy(struct policy *policy) -{ - if (policy->flags & POLICY_CHANGED) { - if (systrace_writepolicy(policy) == -1) - fprintf(stderr, "Failed to write policy for %s\n", - policy->name); - } - - systrace_cleanpolicy(policy); - - 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) -{ - struct policy_syscall tmp2, *tmp; - - strlcpy(tmp2.emulation, emulation, sizeof(tmp2.emulation)); - strlcpy(tmp2.name, name, sizeof(tmp2.name)); - - tmp = SPLAY_FIND(syscalltree, &policy->pflqs, &tmp2); - if (tmp != NULL) - return (&tmp->flq); - - if ((tmp = calloc(1, sizeof(struct policy_syscall))) == NULL) - err(1, "%s:%d: out of memory", __func__, __LINE__); - - strlcpy(tmp->emulation, emulation, sizeof(tmp->emulation)); - strlcpy(tmp->name, name, sizeof(tmp->name)); - TAILQ_INIT(&tmp->flq); - - SPLAY_INSERT(syscalltree, &policy->pflqs, tmp); - - return (&tmp->flq); -} - -int -systrace_modifypolicy(int fd, int policynr, const char *name, short action) -{ - struct policy *policy; - int res, nr; - - if ((policy = systrace_findpolnr(policynr)) == NULL) - return (-1); - - res = intercept_modifypolicy(fd, policynr, policy->emulation, - name, action); - - /* Remember the kernel policy */ - if (res != -1 && - (nr = intercept_getsyscallnumber(policy->emulation, name)) != -1) - policy->kerneltable[nr] = action; - - return (res); -} - -char * -systrace_policyfilename(char *dir, const char *name) -{ - static char file[2*PATH_MAX]; - const char *p; - int i, plen; - - if (strlen(name) + strlen(dir) + 1 >= sizeof(file)) - return (NULL); - - strlcpy(file, dir, sizeof(file)); - i = strlen(file); - file[i++] = '/'; - plen = i; - - p = name; - while (*p) { - if (!isalnum((unsigned char)*p)) { - if (i != plen) - file[i++] = '_'; - } else - file[i++] = *p; - p++; - } - - file[i] = '\0'; - - return (file); -} - -/* - * Converts a executeable name into the corresponding filename - * that contains the security policy. - */ - -char * -systrace_getpolicyname(const char *name) -{ - char *file = NULL; - - if (userpolicy) { - file = systrace_policyfilename(policydir, name); - /* Check if the user policy file exists */ - if (file != NULL && access(file, R_OK) == -1) - file = NULL; - } - - /* Read global policy */ - if (file == NULL) - file = systrace_policyfilename(POLICY_PATH, name); - - return (file); -} - -int -systrace_addpolicy(const char *name) -{ - char *file; - - if ((file = systrace_getpolicyname(name)) == NULL) - return (-1); - - return (systrace_readpolicy(file) != NULL ? 0 : -1); -} - -/* - * Reads policy templates from the template directory. - * These policies can be inserted during interactive policy - * generation. - */ - -int -systrace_templatedir(void) -{ - char filename[PATH_MAX]; - DIR *dir = NULL; - struct stat sb; - struct dirent *dp; - struct template *template; - int off; - - TAILQ_INIT(&templates); - - if (userpolicy) { - if (strlcpy(filename, policydir, sizeof(filename)) >= - sizeof(filename)) - goto error; - if (strlcat(filename, "/templates", sizeof(filename)) >= - sizeof(filename)) - goto error; - - /* Check if template directory exists */ - if (stat(filename, &sb) != -1 && S_ISDIR(sb.st_mode)) - dir = opendir(filename); - } - - /* Read global policy */ - if (dir == NULL) { - strlcpy(filename, POLICY_PATH, sizeof(filename)); - strlcat(filename, "/templates", sizeof(filename)); - if (stat(filename, &sb) != -1 && S_ISDIR(sb.st_mode)) - dir = opendir(filename); - if (dir == NULL) - return (-1); - } - - if (strlcat(filename, "/", sizeof(filename)) >= sizeof(filename)) - goto error; - off = strlen(filename); - - while ((dp = readdir(dir)) != NULL) { - filename[off] = '\0'; - if (strlcat(filename, dp->d_name, sizeof(filename)) >= - sizeof(filename)) - goto error; - - if (stat(filename, &sb) == -1 || !S_ISREG(sb.st_mode)) - continue; - - template = systrace_readtemplate(filename, NULL, NULL); - if (template == NULL) - continue; - - TAILQ_INSERT_TAIL(&templates, template, next); - } - closedir(dir); - - return (0); - - error: - errx(1, "%s: template name too long", __func__); - - /* NOTREACHED */ -} - -struct template * -systrace_readtemplate(char *filename, struct policy *policy, - struct template *template) -{ - FILE *fp; - char line[_POSIX2_LINE_MAX], *p; - char *emulation, *name, *description; - int linenumber = 0; - - if ((fp = fopen(filename, "r")) == NULL) - return (NULL); - - /* Set up pid with current information */ - while (fgets(line, sizeof(line), fp)) { - linenumber++; - - if ((p = systrace_policyline(line)) == NULL) { - fprintf(stderr, "%s:%d: input line too long.\n", - filename, linenumber); - template = NULL; - goto out; - } - - if (strlen(p) == 0) - continue; - - if (!strncasecmp(p, "Template: ", 10)) { - p += 10; - name = strsep(&p, ","); - if (p == NULL) - goto error; - if (strncasecmp(p, " Emulation: ", 12)) - goto error; - p += 12; - emulation = strsep(&p, ", "); - if (p == NULL) - goto error; - if (strncasecmp(p, " Description: ", 14)) - goto error; - p += 14; - description = p; - - if (template != NULL) - continue; - - template = calloc(1, sizeof(struct template)); - if (template == NULL) - err(1, "calloc"); - - template->filename = strdup(filename); - template->name = strdup(name); - template->emulation = strdup(emulation); - template->description = strdup(description); - - if (template->filename == NULL || - template->name == NULL || - template->emulation == NULL || - template->description == NULL) - err(1, "strdup"); - - continue; - } - - if (policy == NULL) - goto out; - - if (systrace_policyprocess(policy, p) == -1) - goto error; - } - - out: - fclose(fp); - return (template); - - error: - fprintf(stderr, "%s:%d: syntax error.\n", filename, linenumber); - goto out; -} - -/* - * Removes trailing whitespace and comments from the input line - */ - -static char * -systrace_policyline(char *line) -{ - char *p; - int quoted = 0; - - if ((p = strchr(line, '\n')) == NULL) - return (NULL); - *p = '\0'; - - /* Remove comments from the input line but ignore # that are part - * of the system call name or within quotes. - */ - for (p = line; *p; p++) { - if (*p == '"') - quoted = quoted ? 0 : 1; - if (*p == '#') { - if (quoted) - continue; - if (p != line && *(p-1) == '-') - continue; - *p = '\0'; - break; - } - } - - /* Remove trailing white space */ - p = line + strlen(line) - 1; - while (p > line) { - if (!isspace((unsigned char)*p)) - break; - *p-- = '\0'; - } - - /* Ignore white space at start of line */ - p = line; - p += strspn(p, " \t"); - - return (p); -} - -/* - * Parse a single line from a policy and convert it into a policy filter. - * Predicates are matched. - */ - -static int -systrace_policyprocess(struct policy *policy, char *p) -{ - char line[_POSIX2_LINE_MAX]; - char *name, *emulation, *rule; - struct filter *filter, *parsed; - short action, future; - int resolved = 0, res, isvalid; - - /* Delay predicate evaluation if we are root */ - - emulation = strsep(&p, "-"); - if (p == NULL || *p == '\0') - return (-1); - - if (strcmp(emulation, policy->emulation)) - return (-1); - - name = strsep(&p, ":"); - if (p == NULL || *p != ' ') - return (-1); - - isvalid = intercept_isvalidsystemcall(emulation, name); - - p++; - rule = p; - - if ((p = strrchr(p, ',')) != NULL && !strncasecmp(p, ", if", 4)) { - *p = '\0'; - res = filter_parse_simple(rule, &action, &future); - *p = ','; - if (res == 0) { - /* Need to make a real policy out of it */ - snprintf(line, sizeof(line), "true then %s", rule); - rule = line; - } - } else if (filter_parse_simple(rule, &action, &future) == 0) - resolved = 1; - - /* - * For now, everything that does not seem to be a valid syscall - * does not get fast kernel policies even though the aliasing - * system supports it. - */ - if (resolved && !isvalid) { - resolved = 0; - snprintf(line, sizeof(line), "true then %s", rule); - rule = line; - } - - /* If the simple parser did not match, try real parser */ - if (!resolved) { - if (parse_filter(rule, &parsed) == -1) - return (-1); - - filter_free(parsed); - } - - filter = calloc(1, sizeof(struct filter)); - if (filter == NULL) - err(1, "%s:%d: calloc", __func__, __LINE__); - - filter->rule = strdup(rule); - if (filter->rule == NULL) - err(1, "%s:%d: strdup", __func__, __LINE__); - - strlcpy(filter->name, name, sizeof(filter->name)); - strlcpy(filter->emulation, emulation, sizeof(filter->emulation)); - - TAILQ_INSERT_TAIL(&policy->prefilters, filter, policy_next); - - return (0); -} - -/* - * Reads security policy from specified file. - * If policy exists already, this function appends new statements from the - * file to the existing policy. - */ - -struct policy * -systrace_readpolicy(const char *filename) -{ - FILE *fp; - struct policy *policy; - char line[_POSIX2_LINE_MAX], *p; - char *emulation, *name; - int linenumber = 0; - int res = -1; - - if ((fp = fopen(filename, "r")) == NULL) - return (NULL); - - policy = NULL; - while (fgets(line, sizeof(line), fp)) { - linenumber++; - - if ((p = systrace_policyline(line)) == NULL) { - fprintf(stderr, "%s:%d: input line too long.\n", - filename, linenumber); - goto out; - } - - if (strlen(p) == 0) - continue; - - if (!strncasecmp(p, "Policy: ", 8)) { - struct timeval now; - - p += 8; - name = strsep(&p, ","); - if (p == NULL) - goto error; - if (strncasecmp(p, " Emulation: ", 12)) - goto error; - p += 12; - emulation = p; - - policy = systrace_newpolicy(emulation, name); - if (policy == NULL) - goto error; - - /* Update access time */ - gettimeofday(&now, NULL); - TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last); - continue; - } - - if (policy == NULL) - goto error; - - if (!strncasecmp(p, "detached", 8)) { - policy->flags |= POLICY_DETACHED; - policy = NULL; - continue; - } - - if (systrace_policyprocess(policy, p) == -1) - goto error; - } - res = 0; - - out: - fclose(fp); - return (res == -1 ? NULL : policy); - - error: - fprintf(stderr, "%s:%d: syntax error.\n", filename, linenumber); - goto out; -} - -/* - * Appends new policy statements if the policy has been updated by - * another process. Assumes that policies are append-only. - * - * Returns: - * -1 if the policy could not be updated. - * 0 if the policy has been updated. - */ - -int -systrace_updatepolicy(int fd, struct policy *policy) -{ - struct stat sb; - struct timespec mtimespec; - int i, policynr = policy->policynr; - char *file; - - if ((file = systrace_getpolicyname(policy->name)) == NULL) - return (-1); - - if (stat(file, &sb) == -1) - return (-1); - - mtimespec = sb.st_mtimespec; - - /* Policy does not need updating */ - if (timespeccmp(&mtimespec, &policy->ts_last, <=)) - return (-1); - - /* Reset the existing policy */ - for (i = 0; i < INTERCEPT_MAXSYSCALLNR; i++) { - if (policy->kerneltable[i] == ICPOLICY_ASK) - continue; - if (intercept_modifypolicy_nr(fd, policynr, i, - ICPOLICY_ASK) == -1) - errx(1, "%s: failed to modify policy for %d", - __func__, i); - } - - /* Now clean up all filter structures in this policy */ - systrace_cleanpolicy(policy); - - /* XXX - This does not deal with Detached and Automatic */ - if (systrace_readpolicy(file) == NULL) - return (-1); - - /* Resets the changed flag */ - filter_prepolicy(fd, policy); - - return (0); -} - -int -systrace_writepolicy(struct policy *policy) -{ - FILE *fp; - int fd; - char *p; - char tmpname[2*PATH_MAX]; - char finalname[2*PATH_MAX]; - struct filter *filter; - struct timeval now; - - if ((p = systrace_policyfilename(policydir, policy->name)) == NULL) - return (-1); - strlcpy(finalname, p, sizeof(finalname)); - if ((p = systrace_policyfilename(policydir, "tmpXXXXXXXX")) == NULL) - return (-1); - strlcpy(tmpname, p, sizeof(tmpname)); - if ((fd = mkstemp(tmpname)) == -1 || - (fp = fdopen(fd, "w+")) == NULL) { - if (fd != -1) { - unlink(tmpname); - close(fd); - } - return (-1); - } - - - fprintf(fp, "Policy: %s, Emulation: %s\n", - policy->name, policy->emulation); - if (policy->flags & POLICY_DETACHED) { - fprintf(fp, "detached\n"); - } else { - TAILQ_FOREACH(filter, &policy->prefilters, policy_next) { - fprintf(fp, "\t%s-%s: %s\n", - filter->emulation, filter->name, filter->rule); - } - TAILQ_FOREACH(filter, &policy->filters, policy_next) { - fprintf(fp, "\t%s-%s: %s\n", - filter->emulation, filter->name, filter->rule); - } - } - fprintf(fp, "\n"); - fclose(fp); - - if (rename(tmpname, finalname) == -1) { - warn("rename(%s, %s)", tmpname, finalname); - return (-1); - } - - /* Update access time */ - gettimeofday(&now, NULL); - TIMEVAL_TO_TIMESPEC(&now, &policy->ts_last); - - return (0); -} - -int -systrace_updatepolicies(int fd) -{ - struct policy *policy; - - SPLAY_FOREACH(policy, policytree, &policyroot) { - /* Check if the policy has been updated */ - systrace_updatepolicy(fd, policy); - } - - return (0); -} - -/* - * Write policy to disk if it has been changed. We need to - * call systrace_updatepolicies() before this, so that we - * don't clobber changes. - */ - -int -systrace_dumppolicies(int fd) -{ - struct policy *policy; - - SPLAY_FOREACH(policy, policytree, &policyroot) { - if (!(policy->flags & POLICY_CHANGED)) - continue; - - if (systrace_writepolicy(policy) == -1) - fprintf(stderr, "Failed to write policy for %s\n", - policy->name); - else - policy->flags &= ~POLICY_CHANGED; - } - - return (0); -} diff --git a/bin/systrace/register.c b/bin/systrace/register.c deleted file mode 100644 index 5b18a946f27..00000000000 --- a/bin/systrace/register.c +++ /dev/null @@ -1,273 +0,0 @@ -/* $OpenBSD: register.c,v 1.27 2016/03/01 16:26:06 naddy Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/tree.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <stdio.h> -#include <err.h> - -#include "intercept.h" -#include "systrace.h" - -#define X(x) if ((x) == -1) \ - err(1, "%s:%d: intercept failed", __func__, __LINE__) - -void -systrace_initcb(void) -{ - struct systrace_alias *alias; - struct intercept_translate *tl; - - X(intercept_init()); - - X(intercept_register_gencb(gen_cb, NULL)); - X(intercept_register_sccb("native", "open", trans_cb, NULL)); - tl = intercept_register_transfn("native", "open", 0); - intercept_register_translation("native", "open", 1, &ic_oflags); - alias = systrace_new_alias("native", "open", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "sendmsg", trans_cb, NULL)); - intercept_register_translation("native", "sendmsg", 1, - &ic_translate_sendmsg); - X(intercept_register_sccb("native", "connect", trans_cb, NULL)); - intercept_register_translation("native", "connect", 1, - &ic_translate_connect); - X(intercept_register_sccb("native", "sendto", trans_cb, NULL)); - intercept_register_translation("native", "sendto", 4, - &ic_translate_connect); - X(intercept_register_sccb("native", "bind", trans_cb, NULL)); - intercept_register_translation("native", "bind", 1, - &ic_translate_connect); - X(intercept_register_sccb("native", "execve", trans_cb, NULL)); - intercept_register_transfn("native", "execve", 0); - intercept_register_translation("native", "execve", 1, &ic_trargv); - X(intercept_register_sccb("native", "stat", trans_cb, NULL)); - tl = intercept_register_transfn("native", "stat", 0); - alias = systrace_new_alias("native", "stat", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "lstat", trans_cb, NULL)); - tl = intercept_register_translation("native", "lstat", 0, - &ic_translate_unlinkname); - alias = systrace_new_alias("native", "lstat", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "unlink", trans_cb, NULL)); - tl = intercept_register_translation("native", "unlink", 0, - &ic_translate_unlinkname); - alias = systrace_new_alias("native", "unlink", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - X(intercept_register_sccb("native", "truncate", trans_cb, NULL)); - tl = intercept_register_transfn("native", "truncate", 0); - alias = systrace_new_alias("native", "truncate", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "mkfifo", trans_cb, NULL)); - tl = intercept_register_transfn("native", "mkfifo", 0); - intercept_register_translation("native", "mkfifo", 1, &ic_modeflags); - alias = systrace_new_alias("native", "mkfifo", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - X(intercept_register_sccb("native", "mknod", trans_cb, NULL)); - intercept_register_transfn("native", "mknod", 0); - intercept_register_translation("native", "mknod", 1, &ic_modeflags); - - X(intercept_register_sccb("native", "chown", trans_cb, NULL)); - intercept_register_transfn("native", "chown", 0); - intercept_register_translation("native", "chown", 1, &ic_uidt); - intercept_register_translation("native", "chown", 2, &ic_gidt); - X(intercept_register_sccb("native", "fchown", trans_cb, NULL)); - intercept_register_translation("native", "fchown", 0, &ic_fdt); - intercept_register_translation("native", "fchown", 1, &ic_uidt); - intercept_register_translation("native", "fchown", 2, &ic_gidt); - X(intercept_register_sccb("native", "lchown", trans_cb, NULL)); - intercept_register_translation("native", "lchown", 0, - &ic_translate_unlinkname); - intercept_register_translation("native", "lchown", 1, &ic_uidt); - intercept_register_translation("native", "lchown", 2, &ic_gidt); - X(intercept_register_sccb("native", "chmod", trans_cb, NULL)); - intercept_register_transfn("native", "chmod", 0); - intercept_register_translation("native", "chmod", 1, &ic_modeflags); - X(intercept_register_sccb("native", "fchmod", trans_cb, NULL)); - intercept_register_translation("native", "fchmod", 0, &ic_fdt); - intercept_register_translation("native", "fchmod", 1, &ic_modeflags); - X(intercept_register_sccb("native", "chflags", trans_cb, NULL)); - intercept_register_transfn("native", "chflags", 0); - intercept_register_translation("native", "chflags", 1, &ic_fileflags); - X(intercept_register_sccb("native", "readlink", trans_cb, NULL)); - tl = intercept_register_translation("native", "readlink", 0, - &ic_translate_unlinkname); - alias = systrace_new_alias("native", "readlink", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "chdir", trans_cb, NULL)); - intercept_register_transfn("native", "chdir", 0); - X(intercept_register_sccb("native", "chroot", trans_cb, NULL)); - intercept_register_transfn("native", "chroot", 0); - X(intercept_register_sccb("native", "access", trans_cb, NULL)); - tl = intercept_register_transfn("native", "access", 0); - alias = systrace_new_alias("native", "access", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "mkdir", trans_cb, NULL)); - tl = intercept_register_translation("native", "mkdir", 0, - &ic_translate_unlinkname); - alias = systrace_new_alias("native", "mkdir", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - X(intercept_register_sccb("native", "rmdir", trans_cb, NULL)); - tl = intercept_register_transfn("native", "rmdir", 0); - alias = systrace_new_alias("native", "rmdir", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "rename", trans_cb, NULL)); - intercept_register_translation("native", "rename", 0, - &ic_translate_unlinkname); - intercept_register_translation("native", "rename", 1, - &ic_translate_unlinkname); - X(intercept_register_sccb("native", "symlink", trans_cb, NULL)); - intercept_register_transstring("native", "symlink", 0); - intercept_register_translation("native", "symlink", 1, - &ic_translate_unlinkname); - X(intercept_register_sccb("native", "link", trans_cb, NULL)); - intercept_register_transfn("native", "link", 0); - intercept_register_transfn("native", "link", 1); - - X(intercept_register_sccb("native", "setuid", trans_cb, NULL)); - intercept_register_translation("native", "setuid", 0, &ic_uidt); - intercept_register_translation("native", "setuid", 0, &ic_uname); - X(intercept_register_sccb("native", "seteuid", trans_cb, NULL)); - intercept_register_translation("native", "seteuid", 0, &ic_uidt); - intercept_register_translation("native", "seteuid", 0, &ic_uname); - X(intercept_register_sccb("native", "setgid", trans_cb, NULL)); - intercept_register_translation("native", "setgid", 0, &ic_gidt); - X(intercept_register_sccb("native", "setegid", trans_cb, NULL)); - intercept_register_translation("native", "setegid", 0, &ic_gidt); - - X(intercept_register_sccb("native", "socket", trans_cb, NULL)); - intercept_register_translation("native", "socket", 0, &ic_sockdom); - intercept_register_translation("native", "socket", 1, &ic_socktype); - X(intercept_register_sccb("native", "kill", trans_cb, NULL)); - intercept_register_translation("native", "kill", 0, &ic_pidname); - intercept_register_translation("native", "kill", 1, &ic_signame); - X(intercept_register_sccb("native", "fcntl", trans_cb, NULL)); - intercept_register_translation("native", "fcntl", 1, &ic_fcntlcmd); - - X(intercept_register_sccb("native", "mmap", trans_cb, NULL)); - intercept_register_translation("native", "mmap", 2, &ic_memprot); - X(intercept_register_sccb("native", "mprotect", trans_cb, NULL)); - intercept_register_translation("native", "mprotect", 2, &ic_memprot); - - X(intercept_register_sccb("native", "openat", trans_cb, NULL)); - tl = intercept_register_translation("native", "openat", 1, - &ic_translate_filenameat); - intercept_register_translation("native", "openat", 2, &ic_oflags); - alias = systrace_new_alias("native", "openat", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "mkdirat", trans_cb, NULL)); - tl = intercept_register_translation("native", "mkdirat", 1, - &ic_translate_unlinknameat); - alias = systrace_new_alias("native", "mkdirat", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "mkfifoat", trans_cb, NULL)); - tl = intercept_register_translation("native", "mkfifoat", 1, - &ic_translate_unlinknameat); - intercept_register_translation("native", "mkfifoat", 2, &ic_modeflags); - alias = systrace_new_alias("native", "mkfifoat", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "mknodat", trans_cb, NULL)); - intercept_register_translation("native", "mknodat", 1, - &ic_translate_unlinknameat); - intercept_register_translation("native", "mknodat", 2, &ic_modeflags); - - X(intercept_register_sccb("native", "symlinkat", trans_cb, NULL)); - intercept_register_transstring("native", "symlinkat", 0); - intercept_register_translation("native", "symlinkat", 2, - &ic_translate_unlinknameat); - - X(intercept_register_sccb("native", "faccessat", trans_cb, NULL)); - tl = intercept_register_translation("native", "faccessat", 1, - &ic_translate_filenameat); - alias = systrace_new_alias("native", "faccessat", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "unlinkat", trans_cb, NULL)); - tl = intercept_register_translation("native", "unlinkat", 1, - &ic_translate_unlinknameat); - alias = systrace_new_alias("native", "unlinkat", "native", "fswrite"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "readlinkat", trans_cb, NULL)); - tl = intercept_register_translation("native", "readlinkat", 1, - &ic_translate_unlinknameat); - alias = systrace_new_alias("native", "readlinkat", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "renameat", trans_cb, NULL)); - intercept_register_translation("native", "renameat", 1, - &ic_translate_unlinknameat); - intercept_register_translation("native", "renameat", 3, - &ic_translate_unlinknameat); - - X(intercept_register_sccb("native", "fchownat", trans_cb, NULL)); - intercept_register_translation("native", "fchownat", 1, - &ic_translate_filenameatflag); - intercept_register_translation("native", "fchownat", 2, &ic_uidt); - intercept_register_translation("native", "fchownat", 3, &ic_gidt); - X(intercept_register_sccb("native", "fchmodat", trans_cb, NULL)); - intercept_register_translation("native", "fchmodat", 1, - &ic_translate_filenameatflag); - intercept_register_translation("native", "fchmodat", 2, &ic_modeflags); - X(intercept_register_sccb("native", "fstatat", trans_cb, NULL)); - tl = intercept_register_translation("native", "fstatat", 1, - &ic_translate_filenameatflag); - alias = systrace_new_alias("native", "fstatat", "native", "fsread"); - systrace_alias_add_trans(alias, tl); - - X(intercept_register_sccb("native", "chflagsat", trans_cb, NULL)); - intercept_register_translation("native", "chflagsat", 1, - &ic_translate_filenameatflag); - intercept_register_translation("native", "chflagsat", 2, &ic_fileflags); - - X(intercept_register_sccb("native", "linkat", trans_cb, NULL)); - intercept_register_translation("native", "linkat", 1, - &ic_translate_unlinknameatflag); - intercept_register_translation("native", "linkat", 3, - &ic_translate_unlinknameat); - - X(intercept_register_execcb(execres_cb, NULL)); - X(intercept_register_pfreecb(policyfree_cb, NULL)); -} diff --git a/bin/systrace/systrace-errno.h b/bin/systrace/systrace-errno.h deleted file mode 100644 index 49c4af356ed..00000000000 --- a/bin/systrace/systrace-errno.h +++ /dev/null @@ -1,128 +0,0 @@ -/* $OpenBSD: systrace-errno.h,v 1.2 2014/08/10 00:20:55 guenther Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYSTRACE_ERRNO_H_ -#define _SYSTRACE_ERRNO_H_ - -#define SYSTRACE_EPERM 1 -#define SYSTRACE_ENOENT 2 -#define SYSTRACE_ESRCH 3 -#define SYSTRACE_EINTR 4 -#define SYSTRACE_EIO 5 -#define SYSTRACE_ENXIO 6 -#define SYSTRACE_E2BIG 7 -#define SYSTRACE_ENOEXEC 8 -#define SYSTRACE_EBADF 9 -#define SYSTRACE_ECHILD 10 -#define SYSTRACE_EDEADLK 11 -#define SYSTRACE_ENOMEM 12 -#define SYSTRACE_EACCES 13 -#define SYSTRACE_EFAULT 14 -#define SYSTRACE_ENOTBLK 15 -#define SYSTRACE_EBUSY 16 -#define SYSTRACE_EEXIST 17 -#define SYSTRACE_EXDEV 18 -#define SYSTRACE_ENODEV 19 -#define SYSTRACE_ENOTDIR 20 -#define SYSTRACE_EISDIR 21 -#define SYSTRACE_EINVAL 22 -#define SYSTRACE_ENFILE 23 -#define SYSTRACE_EMFILE 24 -#define SYSTRACE_ENOTTY 25 -#define SYSTRACE_ETXTBSY 26 -#define SYSTRACE_EFBIG 27 -#define SYSTRACE_ENOSPC 28 -#define SYSTRACE_ESPIPE 29 -#define SYSTRACE_EROFS 30 -#define SYSTRACE_EMLINK 31 -#define SYSTRACE_EPIPE 32 -#define SYSTRACE_EDOM 33 -#define SYSTRACE_ERANGE 34 -#define SYSTRACE_EAGAIN 35 -#define SYSTRACE_EWOULDBLOCK 35 -#define SYSTRACE_EINPROGRESS 36 -#define SYSTRACE_EALREADY 37 -#define SYSTRACE_ENOTSOCK 38 -#define SYSTRACE_EDESTADDRREQ 39 -#define SYSTRACE_EMSGSIZE 40 -#define SYSTRACE_EPROTOTYPE 41 -#define SYSTRACE_ENOPROTOOPT 42 -#define SYSTRACE_EPROTONOSUPPORT 43 -#define SYSTRACE_ESOCKTNOSUPPORT 44 -#define SYSTRACE_EOPNOTSUPP 45 -#define SYSTRACE_EPFNOSUPPORT 46 -#define SYSTRACE_EAFNOSUPPORT 47 -#define SYSTRACE_EADDRINUSE 48 -#define SYSTRACE_EADDRNOTAVAIL 49 -#define SYSTRACE_ENETDOWN 50 -#define SYSTRACE_ENETUNREACH 51 -#define SYSTRACE_ENETRESET 52 -#define SYSTRACE_ECONNABORTED 53 -#define SYSTRACE_ECONNRESET 54 -#define SYSTRACE_ENOBUFS 55 -#define SYSTRACE_EISCONN 56 -#define SYSTRACE_ENOTCONN 57 -#define SYSTRACE_ESHUTDOWN 58 -#define SYSTRACE_ETOOMANYREFS 59 -#define SYSTRACE_ETIMEDOUT 60 -#define SYSTRACE_ECONNREFUSED 61 -#define SYSTRACE_ELOOP 62 -#define SYSTRACE_ENAMETOOLONG 63 -#define SYSTRACE_EHOSTDOWN 64 -#define SYSTRACE_EHOSTUNREACH 65 -#define SYSTRACE_ENOTEMPTY 66 -#define SYSTRACE_EPROCLIM 67 -#define SYSTRACE_EUSERS 68 -#define SYSTRACE_EDQUOT 69 -#define SYSTRACE_ESTALE 70 -#define SYSTRACE_EREMOTE 71 -#define SYSTRACE_EBADRPC 72 -#define SYSTRACE_ERPCMISMATCH 73 -#define SYSTRACE_EPROGUNAVAIL 74 -#define SYSTRACE_EPROGMISMATCH 75 -#define SYSTRACE_EPROCUNAVAIL 76 -#define SYSTRACE_ENOLCK 77 -#define SYSTRACE_ENOSYS 78 -#define SYSTRACE_EFTYPE 79 -#define SYSTRACE_EAUTH 80 -#define SYSTRACE_ENEEDAUTH 81 -#define SYSTRACE_EIPSEC 82 -#define SYSTRACE_ENOATTR 83 -#define SYSTRACE_EILSEQ 84 -#define SYSTRACE_ENOMEDIUM 85 -#define SYSTRACE_EMEDIUMTYPE 86 -#define SYSTRACE_EOVERFLOW 87 -#define SYSTRACE_ECANCELED 88 -#define SYSTRACE_EIDRM 89 -#define SYSTRACE_ENOMSG 90 -#define SYSTRACE_ENOTSUP 91 - -#endif diff --git a/bin/systrace/systrace-error.c b/bin/systrace/systrace-error.c deleted file mode 100644 index 8992d01b9df..00000000000 --- a/bin/systrace/systrace-error.c +++ /dev/null @@ -1,156 +0,0 @@ -/* $OpenBSD: systrace-error.c,v 1.4 2015/01/16 00:19:12 deraadt Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BU - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TOR - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/tree.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <stdio.h> -#include <string.h> - -#include "intercept.h" -#include "systrace.h" -#include "systrace-errno.h" - -struct systrace_error { - char *name; - int errno; -} systrace_errors[] = { - { "EPERM", SYSTRACE_EPERM }, - { "ENOENT", SYSTRACE_ENOENT }, - { "ESRCH", SYSTRACE_ESRCH }, - { "EINTR", SYSTRACE_EINTR }, - { "EIO", SYSTRACE_EIO }, - { "ENXIO", SYSTRACE_ENXIO }, - { "E2BIG", SYSTRACE_E2BIG }, - { "ENOEXEC", SYSTRACE_ENOEXEC }, - { "EBADF", SYSTRACE_EBADF }, - { "ECHILD", SYSTRACE_ECHILD }, - { "EDEADLK", SYSTRACE_EDEADLK }, - { "ENOMEM", SYSTRACE_ENOMEM }, - { "EACCES", SYSTRACE_EACCES }, - { "EFAULT", SYSTRACE_EFAULT }, - { "ENOTBLK", SYSTRACE_ENOTBLK }, - { "EBUSY", SYSTRACE_EBUSY }, - { "EEXIST", SYSTRACE_EEXIST }, - { "EXDEV", SYSTRACE_EXDEV }, - { "ENODEV", SYSTRACE_ENODEV }, - { "ENOTDIR", SYSTRACE_ENOTDIR }, - { "EISDIR", SYSTRACE_EISDIR }, - { "EINVAL", SYSTRACE_EINVAL }, - { "ENFILE", SYSTRACE_ENFILE }, - { "EMFILE", SYSTRACE_EMFILE }, - { "ENOTTY", SYSTRACE_ENOTTY }, - { "ETXTBSY", SYSTRACE_ETXTBSY }, - { "EFBIG", SYSTRACE_EFBIG }, - { "ENOSPC", SYSTRACE_ENOSPC }, - { "ESPIPE", SYSTRACE_ESPIPE }, - { "EROFS", SYSTRACE_EROFS }, - { "EMLINK", SYSTRACE_EMLINK }, - { "EPIPE", SYSTRACE_EPIPE }, - { "EDOM", SYSTRACE_EDOM }, - { "ERANGE", SYSTRACE_ERANGE }, - { "EAGAIN", SYSTRACE_EAGAIN }, - { "EWOULDBLOCK", SYSTRACE_EWOULDBLOCK }, - { "EINPROGRESS", SYSTRACE_EINPROGRESS }, - { "EALREADY", SYSTRACE_EALREADY }, - { "ENOTSOCK", SYSTRACE_ENOTSOCK }, - { "EDESTADDRREQ", SYSTRACE_EDESTADDRREQ }, - { "EMSGSIZE", SYSTRACE_EMSGSIZE }, - { "EPROTOTYPE", SYSTRACE_EPROTOTYPE }, - { "ENOPROTOOPT", SYSTRACE_ENOPROTOOPT }, - { "EPROTONOSUPPORT", SYSTRACE_EPROTONOSUPPORT }, - { "ESOCKTNOSUPPORT", SYSTRACE_ESOCKTNOSUPPORT }, - { "EOPNOTSUPP", SYSTRACE_EOPNOTSUPP }, - { "EPFNOSUPPORT", SYSTRACE_EPFNOSUPPORT }, - { "EAFNOSUPPORT", SYSTRACE_EAFNOSUPPORT }, - { "EADDRINUSE", SYSTRACE_EADDRINUSE }, - { "EADDRNOTAVAIL", SYSTRACE_EADDRNOTAVAIL }, - { "ENETDOWN", SYSTRACE_ENETDOWN }, - { "ENETUNREACH", SYSTRACE_ENETUNREACH }, - { "ENETRESET", SYSTRACE_ENETRESET }, - { "ECONNABORTED", SYSTRACE_ECONNABORTED }, - { "ECONNRESET", SYSTRACE_ECONNRESET }, - { "ENOBUFS", SYSTRACE_ENOBUFS }, - { "EISCONN", SYSTRACE_EISCONN }, - { "ENOTCONN", SYSTRACE_ENOTCONN }, - { "ESHUTDOWN", SYSTRACE_ESHUTDOWN }, - { "ETOOMANYREFS", SYSTRACE_ETOOMANYREFS }, - { "ETIMEDOUT", SYSTRACE_ETIMEDOUT }, - { "ECONNREFUSED", SYSTRACE_ECONNREFUSED }, - { "ELOOP", SYSTRACE_ELOOP }, - { "ENAMETOOLONG", SYSTRACE_ENAMETOOLONG }, - { "EHOSTDOWN", SYSTRACE_EHOSTDOWN }, - { "EHOSTUNREACH", SYSTRACE_EHOSTUNREACH }, - { "ENOTEMPTY", SYSTRACE_ENOTEMPTY }, - { "EPROCLIM", SYSTRACE_EPROCLIM }, - { "EUSERS", SYSTRACE_EUSERS }, - { "EDQUOT", SYSTRACE_EDQUOT }, - { "ESTALE", SYSTRACE_ESTALE }, - { "EREMOTE", SYSTRACE_EREMOTE }, - { "EBADRPC", SYSTRACE_EBADRPC }, - { "ERPCMISMATCH", SYSTRACE_ERPCMISMATCH }, - { "EPROGUNAVAIL", SYSTRACE_EPROGUNAVAIL }, - { "EPROGMISMATCH", SYSTRACE_EPROGMISMATCH }, - { "EPROCUNAVAIL", SYSTRACE_EPROCUNAVAIL }, - { "ENOLCK", SYSTRACE_ENOLCK }, - { "ENOSYS", SYSTRACE_ENOSYS }, - { "EFTYPE", SYSTRACE_EFTYPE }, - { "EAUTH", SYSTRACE_EAUTH }, - { "ENEEDAUTH", SYSTRACE_ENEEDAUTH }, - { "EIPSEC", SYSTRACE_EIPSEC }, - { "ENOATTR", SYSTRACE_ENOATTR }, - { "EILSEQ", SYSTRACE_EILSEQ }, - { "ENOMEDIUM", SYSTRACE_ENOMEDIUM }, - { "EMEDIUMTYPE", SYSTRACE_EMEDIUMTYPE }, - { "EOVERFLOW", SYSTRACE_EOVERFLOW }, - { "ECANCELED", SYSTRACE_ECANCELED }, - { "EIDRM", SYSTRACE_EIDRM }, - { "ENOMSG", SYSTRACE_ENOMSG }, - { "ENOTSUP", SYSTRACE_ENOTSUP }, - { NULL, 0} -}; - -int -systrace_error_translate(char *name) -{ - struct systrace_error *error = systrace_errors; - - while (error->name != NULL) { - if (!strcasecmp(error->name, name)) - return (error->errno); - error++; - } - - return (-1); -} diff --git a/bin/systrace/systrace-translate.c b/bin/systrace/systrace-translate.c deleted file mode 100644 index 96cc7a16b10..00000000000 --- a/bin/systrace/systrace-translate.c +++ /dev/null @@ -1,606 +0,0 @@ -/* $OpenBSD: systrace-translate.c,v 1.26 2016/03/01 16:26:06 naddy Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/tree.h> -#include <sys/socket.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/signal.h> -#include <stdint.h> -#include <limits.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <fcntl.h> -#include <pwd.h> -#include <err.h> - -#include "intercept.h" -#include "systrace.h" - -#define FL(w,c) do { \ - if (flags & (w) && p < str + sizeof str - 1) \ - *p++ = (c); \ -} while (0) - -static int print_oflags(char *, size_t, struct intercept_translate *); -static int print_modeflags(char *, size_t, struct intercept_translate *); -static int print_number(char *, size_t, struct intercept_translate *); -static int print_uname(char *, size_t, struct intercept_translate *); -static int print_pidname(char *, size_t, struct intercept_translate *); -static int print_signame(char *, size_t, struct intercept_translate *); -static int print_fcntlcmd(char *, size_t, struct intercept_translate *); -static int print_memprot(char *, size_t, struct intercept_translate *); -static int print_fileflags(char *, size_t, struct intercept_translate *); -static int get_argv(struct intercept_translate *, int, pid_t, void *); -static int print_argv(char *, size_t, struct intercept_translate *); - -static int -print_oflags(char *buf, size_t buflen, struct intercept_translate *tl) -{ - char str[32], *p; - int flags = (intptr_t)tl->trans_addr; - int isread = 0; - - p = str; - switch (flags & O_ACCMODE) { - case O_RDONLY: - strlcpy(p, "ro", str + sizeof str - p); - isread = 1; - break; - case O_WRONLY: - strlcpy(p, "wo", str + sizeof str - p); - break; - case O_RDWR: - strlcpy(p, "rw", str + sizeof str - p); - break; - default: - strlcpy(p, "--", str + sizeof str - p); - break; - } - - /* XXX - Open handling of alias */ - if (isread) - systrace_switch_alias("native", "open", "native", "fsread"); - else - systrace_switch_alias("native", "open", "native", "fswrite"); - - p += 2; - - FL(O_NONBLOCK, 'n'); - FL(O_APPEND, 'a'); - FL(O_CREAT, 'c'); - FL(O_TRUNC, 't'); - - *p = '\0'; - - strlcpy(buf, str, buflen); - - return (0); -} - -static int -print_modeflags(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int mode = (intptr_t)tl->trans_addr; - - mode &= 00007777; - snprintf(buf, buflen, "%o", mode); - - return (0); -} - -static int -print_number(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int number = (intptr_t)tl->trans_addr; - - snprintf(buf, buflen, "%d", number); - - return (0); -} - -static int -print_sockdom(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int domain = (intptr_t)tl->trans_addr; - char *what = NULL; - - switch (domain) { - case AF_UNIX: - what = "AF_UNIX"; - break; - case AF_INET: - what = "AF_INET"; - break; - case AF_INET6: - what = "AF_INET6"; - break; - case AF_IMPLINK: - what = "AF_IMPLINK"; - break; - default: - snprintf(buf, buflen, "AF_UNKNOWN(%d)", domain); - break; - } - - if (what != NULL) - strlcpy(buf, what, buflen); - - return (0); -} - -static int -print_socktype(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int type = (intptr_t)tl->trans_addr; - char *what = NULL; - - switch (type) { - case SOCK_STREAM: - what = "SOCK_STREAM"; - break; - case SOCK_DGRAM: - what = "SOCK_DGRAM"; - break; - case SOCK_RAW: - what = "SOCK_RAW"; - break; - case SOCK_SEQPACKET: - what = "SOCK_SEQPACKET"; - break; - case SOCK_RDM: - what = "SOCK_RDM"; - break; - default: - snprintf(buf, buflen, "SOCK_UNKNOWN(%d)", type); - break; - } - - if (what != NULL) - strlcpy(buf, what, buflen); - - return (0); -} - -static int -print_uname(char *buf, size_t buflen, struct intercept_translate *tl) -{ - struct passwd *pw; - uid_t uid = (intptr_t)tl->trans_addr; - - pw = getpwuid(uid); - strlcpy(buf, pw != NULL ? pw->pw_name : "<unknown>", buflen); - - return (0); -} - -static int -print_pidname(char *buf, size_t buflen, struct intercept_translate *tl) -{ - struct intercept_pid *icpid; - pid_t pid = (intptr_t)tl->trans_addr; - - if (pid > 0) { - icpid = intercept_findpid(pid); - strlcpy(buf, icpid != NULL ? icpid->name : "<unknown>", buflen); - } else if (pid == 0) { - strlcpy(buf, "<own process group>", buflen); - } else if (pid == -1) { - strlcpy(buf, "<every process: -1>", buflen); - } else { - /* pid is negative but not -1 - trying to signal pgroup */ - pid = -pid; - icpid = intercept_findpid(pid); - strlcpy(buf, "pg:", buflen); - strlcat(buf, icpid != NULL ? icpid->name : "unknown", buflen); - } - - return (0); -} - -static int -print_signame(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int sig = (intptr_t)tl->trans_addr; - char *name; - - switch (sig) { - case SIGHUP: - name = "SIGHUP"; - break; - case SIGINT: - name = "SIGINT"; - break; - case SIGQUIT: - name = "SIGQUIT"; - break; - case SIGILL: - name = "SIGILL"; - break; - case SIGABRT: - name = "SIGABRT"; - break; - case SIGFPE: - name = "SIGFPE"; - break; - case SIGKILL: - name = "SIGKILL"; - break; - case SIGBUS: - name = "SIGBUS"; - break; - case SIGSEGV: - name = "SIGSEGV"; - break; - case SIGSYS: - name = "SIGSYS"; - break; - case SIGPIPE: - name = "SIGPIPE"; - break; - case SIGALRM: - name = "SIGALRM"; - break; - case SIGTERM: - name = "SIGTERM"; - break; - case SIGURG: - name = "SIGURG"; - break; - case SIGSTOP: - name = "SIGSTOP"; - break; - case SIGTSTP: - name = "SIGTSTP"; - break; - case SIGCONT: - name = "SIGCONT"; - break; - case SIGCHLD: - name = "SIGCHLD"; - break; - case SIGTTIN: - name = "SIGTTIN"; - break; - case SIGTTOU: - name = "SIGTTOU"; - break; - case SIGIO: - name = "SIGIO"; - break; - case SIGPROF: - name = "SIGPROF"; - break; - case SIGWINCH: - name = "SIGWINCH"; - break; - case SIGINFO: - name = "SIGINFO"; - break; - case SIGUSR1: - name = "SIGUSR1"; - break; - case SIGUSR2: - name = "SIGUSR2"; - break; - default: - snprintf(buf, buflen, "<unknown>: %d", sig); - return (0); - } - - strlcpy(buf, name, buflen); - return (0); -} - -static int -print_fcntlcmd(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int cmd = (intptr_t)tl->trans_addr; - char *name; - - switch (cmd) { - case F_DUPFD: - name = "F_DUPFD"; - break; - case F_DUPFD_CLOEXEC: - name = "F_DUPFD_CLOEXEC"; - break; - case F_GETFD: - name = "F_GETFD"; - break; - case F_SETFD: - name = "F_SETFD"; - break; - case F_GETFL: - name = "F_GETFL"; - break; - case F_SETFL: - name = "F_SETFL"; - break; - case F_GETOWN: - name = "F_GETOWN"; - break; - case F_SETOWN: - name = "F_SETOWN"; - break; - case F_GETLK: - name = "F_GETLK"; - break; - case F_SETLK: - name = "F_SETLK"; - break; - case F_SETLKW: - name = "F_SETLKW"; - break; - default: - snprintf(buf, buflen, "<unknown>: %d", cmd); - return (0); - } - - snprintf(buf, buflen, "%s", name); - return (0); -} - -static int -print_memprot(char *buf, size_t buflen, struct intercept_translate *tl) -{ - int prot = (intptr_t)tl->trans_addr; - char lbuf[64]; - - if (prot == PROT_NONE) { - strlcpy(buf, "PROT_NONE", buflen); - return (0); - } else - *buf = '\0'; - - while (prot) { - if (*buf) - strlcat(buf, "|", buflen); - - if (prot & PROT_READ) { - strlcat(buf, "PROT_READ", buflen); - prot &= ~PROT_READ; - continue; - } - - if (prot & PROT_WRITE) { - strlcat(buf, "PROT_WRITE", buflen); - prot &= ~PROT_WRITE; - continue; - } - - if (prot & PROT_EXEC) { - strlcat(buf, "PROT_EXEC", buflen); - prot &= ~PROT_EXEC; - continue; - } - - if (prot) { - snprintf(lbuf, sizeof(lbuf), "<unknown:0x%x>", prot); - strlcat(buf, lbuf, buflen); - prot = 0; - continue; - } - } - - return (0); -} - -static int -print_fileflags(char *buf, size_t buflen, struct intercept_translate *tl) -{ - unsigned int flags = (intptr_t)tl->trans_addr; - char lbuf[64]; - - *buf = '\0'; - - while (flags) { - if (*buf) - strlcat(buf, "|", buflen); - - if (flags & UF_NODUMP) { - strlcat(buf, "UF_NODUMP", buflen); - flags &= ~UF_NODUMP; - continue; - } - - if (flags & UF_IMMUTABLE) { - strlcat(buf, "UF_IMMUTABLE", buflen); - flags &= ~UF_IMMUTABLE; - continue; - } - - if (flags & UF_APPEND) { - strlcat(buf, "UF_APPEND", buflen); - flags &= ~UF_APPEND; - continue; - } - - if (flags & UF_OPAQUE) { - strlcat(buf, "UF_OPAQUE", buflen); - flags &= ~UF_OPAQUE; - continue; - } - - if (flags & SF_ARCHIVED) { - strlcat(buf, "SF_ARCHIVED", buflen); - flags &= ~SF_ARCHIVED; - continue; - } - - if (flags & SF_IMMUTABLE) { - strlcat(buf, "SF_IMMUTABLE", buflen); - flags &= ~SF_IMMUTABLE; - continue; - } - - if (flags & SF_APPEND) { - strlcat(buf, "SF_APPEND", buflen); - flags &= ~SF_APPEND; - continue; - } - - if (flags) { - snprintf(lbuf, sizeof(lbuf), "<unknown:0x%x>", flags); - strlcat(buf, lbuf, buflen); - flags = 0; - continue; - } - } - - return (0); -} - -static int -get_argv(struct intercept_translate *trans, int fd, pid_t pid, void *addr) -{ - char *arg; - char buf[_POSIX2_LINE_MAX], *p; - int i, off = 0; - size_t len; - extern struct intercept_system intercept; - - i = 0; - buf[0] = '\0'; - while (1) { - if (intercept.io(fd, pid, INTERCEPT_READ, (char *)addr + off, - (void *)&arg, sizeof(char *)) == -1) { - warn("%s: ioctl", __func__); - return (-1); - } - if (arg == NULL) - break; - - p = intercept_get_string(fd, pid, arg); - if (p == NULL) - return (-1); - - if (i > 0) - strlcat(buf, " ", sizeof(buf)); - strlcat(buf, p, sizeof(buf)); - - off += sizeof(char *); - i++; - } - - len = strlen(buf) + 1; - trans->trans_data = malloc(len); - if (trans->trans_data == NULL) - return (-1); - - /* XXX - No argument replacement */ - trans->trans_size = 0; - memcpy(trans->trans_data, buf, len); - - return (0); -} - -static int -print_argv(char *buf, size_t buflen, struct intercept_translate *tl) -{ - strlcpy(buf, (char *)tl->trans_data, buflen); - - return (0); -} - -struct intercept_translate ic_trargv = { - "argv", - get_argv, print_argv, -}; - -struct intercept_translate ic_oflags = { - "oflags", - NULL, print_oflags, -}; - -struct intercept_translate ic_modeflags = { - "mode", - NULL, print_modeflags, -}; - -struct intercept_translate ic_uidt = { - "uid", - NULL, print_number, -}; - -struct intercept_translate ic_uname = { - "uname", - NULL, print_uname, -}; - -struct intercept_translate ic_gidt = { - "gid", - NULL, print_number, -}; - -struct intercept_translate ic_fdt = { - "fd", - NULL, print_number, -}; - -struct intercept_translate ic_sockdom = { - "sockdom", - NULL, print_sockdom, -}; - -struct intercept_translate ic_socktype = { - "socktype", - NULL, print_socktype, -}; - -struct intercept_translate ic_pidname = { - "pidname", - NULL, print_pidname, -}; - -struct intercept_translate ic_signame = { - "signame", - NULL, print_signame, -}; - -struct intercept_translate ic_fcntlcmd = { - "cmd", - NULL, print_fcntlcmd, -}; - -struct intercept_translate ic_memprot = { - "prot", - NULL, print_memprot, -}; - -struct intercept_translate ic_fileflags = { - "flags", - NULL, print_fileflags, -}; diff --git a/bin/systrace/systrace.1 b/bin/systrace/systrace.1 deleted file mode 100644 index 7b1b1d2e3fa..00000000000 --- a/bin/systrace/systrace.1 +++ /dev/null @@ -1,358 +0,0 @@ -.\" $OpenBSD: systrace.1,v 1.46 2015/09/12 15:52:37 schwarze Exp $ -.\" -.\" Copyright 2002 Niels Provos <provos@citi.umich.edu> -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by Niels Provos. -.\" 4. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -.\" -.\" Manual page, using -mandoc macros -.\" -.Dd $Mdocdate: September 12 2015 $ -.Dt SYSTRACE 1 -.Os -.Sh NAME -.Nm systrace -.Nd generate and enforce system call policies -.Sh SYNOPSIS -.Nm systrace -.Op Fl AaCeitUuV -.Op Fl c Ar user : Ns Ar group -.Op Fl d Ar policydir -.Op Fl E Ar logfile -.Op Fl f Ar file -.Op Fl g Ar gui -.Op Fl p Ar pid -.Ar command ... -.Sh DESCRIPTION -The -.Nm -utility monitors and controls an application's access to the system by -enforcing access policies for system calls. -The -.Nm -utility might be used to trace an untrusted application's access to -the system. -Alternatively, it might be used to protect the system -from software bugs (such as buffer overflows) by constraining a -daemon's access to the system. -Its privilege elevation feature can be used to obviate the -need to run large, untrusted programs as root when only one or two -system calls require root privilege. -.Pp -The access policy can be generated interactively or obtained from a -policy file. -Interactive policy generation will be performed by the -.Dq notification user agent , -normally -.Xr xsystrace 1 , -unless text mode is specified via -.Fl t . -.Pp -When running in -.Dq automatic enforcement -mode, operations not covered by the policy raise an alarm and -allow a user to refine the currently configured policy. -.Pp -The options are as follows: -.Bl -tag -width Dfxfile -.It Fl A -Automatically generate a policy that allows every operation the -application executes. -The created policy functions as a base that can be refined. -.It Fl a -Enables automatic enforcement of configured policies. -An operation not covered by policy is denied and logged via -.Xr syslog 3 , -or to -.Em stderr -if the -.Fl e -flag is specified. -.It Fl C -Run -.Nm -in cradle mode; -currently, when multiple processes are started with systrace protection, each -.Nm -starts its own UI -.Pq user interface -process. -Cradle mode allows a user to attach all -.Nm -processes to one UI. -This may be useful, for example, in scenarios where -.Nm -is being heavily used. -If a cradle server is not running, one is launched. -.It Fl c Ar user : Ns Ar group -Specifies the -.Ar user -and -.Ar group -that the monitored application should be executed with, -which may be either non-negative integers or names. -This is useful in conjunction with privilege elevation and requires -root privilege. -.It Fl d Ar policydir -Specifies an alternative location for the user's directory from -which policies are loaded and to which changed policies are stored. -.It Fl E Ar logfile -Logs all policy violations or specifically logged system calls to -.Ar logfile . -.It Fl e -Specifies to log to -.Em stderr -instead of -.Xr syslog 3 . -.It Fl f Ar file -The policies specified in -.Ar file -are added to the policies that -.Nm -knows about. -The dirname in the policy may contain an "*" to match any possible pathname. -The wildcard is removed from the policy database the first time that -a filename matches. -.It Fl g Ar gui -Specifies an alternative location for the notification user interface. -.It Fl i -Inherits the policy after a call to -.Xr execve 2 . -If this option is not specified, a new program will get its own policy. -.It Fl p Ar pid -Specifies the pid of a process that -.Nm -should attach to. -The full path name of the corresponding binary has to be specified -as -.Ar command . -.It Fl t -Uses text mode to ask for interactive policy generation. -.It Fl U -Ignore user-configured policies and use only global system policies. -.It Fl u -Do not perform aliasing on system call names. -Aliasing is enabled by default to group similar system calls into a -single compound name. -For example, system calls that read from the file system like -.Fn lstat -and -.Fn access -are translated to -.Fn fsread . -.It Fl V -Prints the version number of -.Nm . -.El -.Ss POLICY -The policy is specified via the following grammar: -.Bd -literal -offset 3n -filter = expression "then" action errorcode logcode -expression = symbol | "not" expression | "(" expression ")" | - expression "and" expression | expression "or" expression -symbol = string typeoff "match" cmdstring | - string typeoff "eq" cmdstring | string typeoff "neq" cmdstring | - string typeoff "sub" cmdstring | string typeoff "nsub" cmdstring | - string typeoff "inpath" cmdstring | string typeoff "re" cmdstring | - "true" -typeoff = /* empty */ | "[" number "]" -action = "permit" | "deny" | "ask" -errorcode = /* empty */ | "[" string "]" -logcode = /* empty */ | "log" -.Ed -.Pp -The -.Va cmdstring -is an arbitrary string enclosed with quotation marks. -The -.Va errorcode -is used to return an -.Xr errno 2 -value to the system call when using a -.Va deny -action. -The values -.Do -inherit -.Dc -and -.Do -detach -.Dc -have special meanings when used with a -.Va permit -rule for the -.Va execve -system call. -When using -.Do -inherit, -.Dc -the current policy is inherited for the new binary. -With -.Do -detach, -.Dc -.Nm -detaches from a process after successfully -completing -the -.Va execve -system call. -.Pp -The -.Va ask -action specifies that the user should be prompted for a decision -every time that the rule matches. -.Pp -The filter operations have the following meaning: -.Bl -hang -width Dinpath -offset AAA -.It match -Evaluates to true if file name globbing according to -.Xr fnmatch 3 -succeeds. -.It eq -Evaluates to true if the system call argument matches -.Va cmdstring -exactly. -.It neq -This is the logical negation of -.Va eq . -.It sub -Performs a substring match on the system call argument. -.It nsub -This is the logical negation of -.Va sub . -.It inpath -Evaluates to true if the system call argument is a subpath of -.Va cmdstring . -.It re -Evaluates to true if the system call arguments matches -the specified regular expression. -.El -.Pp -By appending the -.Va log -statement to a rule, a matching system call and its arguments -are logged. -This is useful, for example, to log all invocations of the -.Va execve -system call. -.Pp -Policy entries may contain an appended predicate. -Predicates have the following format: -.Bd -literal -offset 3n -", if" {"user", "group"} {"=", "!=", "\*[Lt]", "\*[Gt]" } {number, string} -.Ed -.Pp -A rule is added to the configured policy only if its predicate -evaluates to true. -.Pp -The environment variables -.Ev $HOME , -.Ev $USER -and -.Ev $CWD -are substituted in rules. -Comments, begun by an unquoted -.Sq \&# -character and continuing to the end of the line, are ignored. -.Sh PRIVILEGE ELEVATION -With -.Nm -it is possible to remove setuid or setgid binaries, and use the -privilege elevation feature instead. -Single system calls can be executed with higher privileges if -specified by the policy. -For example, -.Bd -literal -offset 3n -native-bind: sockaddr eq "inet-[0.0.0.0]:22" then permit as root -.Ed -.Pp -allows an unprivileged application to bind to a reserved port. -Privilege elevation requires that the -.Nm -process is executed as root. -.Pp -The following statements can be appended after the -.Va permit -in a policy to elevate the privileges for the matching system call: -.Bd -literal -offset 3n -as user -as user:group -as :group -.Ed -.Pp -The effective -.Va uid -and -.Va gid -are elevated only for the duration of the system call, and are restored -to the old values afterwards (except for the -.Va seteuid -or -.Va setegid -system calls). -.Sh FILES -.Bl -tag -width xHOME/xsystrace -compact -.It Pa /dev/systrace -systrace device -.It Pa /etc/systrace -global systrace policies -.It Pa $HOME/.systrace -user specified policies, one per binary, with slashes in the full pathname -replaced by the underscore character. -.El -.Sh EXAMPLES -An excerpt from a sample -.Xr ls 1 -policy might look as follows: -.Bd -literal -offset 2n -Policy: /bin/ls, Emulation: native -[...] - native-fsread: filename eq "$HOME" then permit - native-fchdir: permit -[...] - native-fsread: filename eq "/tmp" then permit - native-stat: permit - native-fsread: filename match "$HOME/*" then permit - native-fsread: filename eq "/etc/pwd.db" then permit -[...] - native-fsread: filename eq "/etc" then deny[eperm], if group != wheel -.Ed -.Sh SEE ALSO -.Xr systrace 4 -.Sh AUTHORS -The -.Nm -utility was developed by -.An Niels Provos . -.Sh BUGS -Applications that use clone()-like system calls to share the complete -address space between processes may be able to replace system call -arguments after they have been evaluated by -.Nm -and escape policy enforcement. diff --git a/bin/systrace/systrace.c b/bin/systrace/systrace.c deleted file mode 100644 index ce3b0ee90e1..00000000000 --- a/bin/systrace/systrace.c +++ /dev/null @@ -1,826 +0,0 @@ -/* $OpenBSD: systrace.c,v 1.63 2015/04/18 18:28:37 deraadt Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#include <sys/wait.h> -#include <sys/tree.h> -#include <sys/socket.h> -#include <sys/stat.h> -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <stdarg.h> -#include <fcntl.h> -#include <signal.h> -#include <syslog.h> -#include <string.h> -#include <err.h> -#include <errno.h> -#include <grp.h> -#include <pwd.h> -#include <event.h> - -#include "intercept.h" -#include "systrace.h" -#include "util.h" - -#define CRADLE_SERVER "cradle_server" -#define CRADLE_UI "cradle_ui" - -#define VERSION "1.6d (OpenBSD)" - -pid_t trpid; -int trfd; -int connected = 0; /* Connected to GUI */ -int inherit = 0; /* Inherit policy to childs */ -int automatic = 0; /* Do not run interactively */ -int allow = 0; /* Allow all and generate */ -int userpolicy = 1; /* Permit user defined policies */ -int noalias = 0; /* Do not do system call aliasing */ -int iamroot = 0; /* Set if we are running as root */ -int cradle = 0; /* Set if we are running in cradle mode */ -int logtofile = 0; /* Log to file instead of syslog */ -FILE *logfile; /* default logfile to send to if enabled */ -char cwd[PATH_MAX]; /* Current working directory */ -char home[PATH_MAX]; /* Home directory of user */ -char username[LOGIN_NAME_MAX]; /* Username: predicate match and expansion */ -char *guipath = _PATH_XSYSTRACE; /* Path to GUI executable */ -char dirpath[PATH_MAX]; - -static struct event ev_read; -static struct event ev_timeout; - -static void child_handler(int); -static void log_msg(int, const char *, ...); -static void systrace_read(int, short, void *); -static void systrace_timeout(int, short, void *); -static void usage(void); - -void -systrace_parameters(void) -{ - struct passwd *pw; - char *normcwd; - uid_t uid = getuid(); - - iamroot = getuid() == 0; - - /* Find out current username. */ - if ((pw = getpwuid(uid)) == NULL) { - snprintf(username, sizeof(username), "uid %u", uid); - } else { - strlcpy(username, pw->pw_name, sizeof(username)); - strlcpy(home, pw->pw_dir, sizeof(home)); - } - - /* Determine current working directory for filtering */ - if (getcwd(cwd, sizeof(cwd)) == NULL) - err(1, "getcwd"); - if ((normcwd = normalize_filename(-1, 0, cwd, ICLINK_ALL)) == NULL) - errx(1, "normalize_filename"); - if (strlcpy(cwd, normcwd, sizeof(cwd)) >= sizeof(cwd)) - errx(1, "cwd too long"); -} - -/* - * Generate human readable output and setup replacements if available. - */ - -void -make_output(char *output, size_t outlen, const char *binname, - pid_t pid, pid_t ppid, - int policynr, const char *policy, int nfilters, const char *emulation, - const char *name, int code, struct intercept_tlq *tls, - struct intercept_replace *repl) -{ - struct intercept_translate *tl; - char *p, *line; - int size; - - snprintf(output, outlen, - "%s, pid: %d(%d)[%d], policy: %s, filters: %d, syscall: %s-%s(%d)", - binname, pid, policynr, ppid, policy, nfilters, - emulation, name, code); - - p = output + strlen(output); - size = outlen - strlen(output); - - if (tls == NULL) - return; - - TAILQ_FOREACH(tl, tls, next) { - if (!tl->trans_valid) - continue; - line = intercept_translate_print(tl); - if (line == NULL) - continue; - - snprintf(p, size, ", %s: %s", tl->name, strescape(line)); - p = output + strlen(output); - size = outlen - strlen(output); - - if (repl != NULL && tl->trans_size) - intercept_replace_add(repl, tl->off, - tl->trans_data, tl->trans_size, - tl->trans_flags); - } -} - -short -trans_cb(int fd, pid_t pid, int policynr, - const char *name, int code, const char *emulation, - void *args, int argsize, - struct intercept_replace *repl, - struct intercept_tlq *tls, void *cbarg) -{ - short action, future; - struct policy *policy; - struct intercept_pid *ipid; - struct intercept_tlq alitls; - struct intercept_translate alitl[SYSTRACE_MAXALIAS]; - struct systrace_alias *alias = NULL; - struct filterq *pflq = NULL; - const char *binname = NULL; - char output[_POSIX2_LINE_MAX]; - pid_t ppid; - int done = 0, dolog = 0; - - action = ICPOLICY_PERMIT; - - if (policynr == -1) - goto out; - - if ((policy = systrace_findpolnr(policynr)) == NULL) - errx(1, "%s:%d: find %d", __func__, __LINE__, - policynr); - - ipid = intercept_getpid(pid); - ipid->uflags = 0; - binname = ipid->name != NULL ? ipid->name : policy->name; - ppid = ipid->ppid; - - /* Required to set up replacements */ - do { - make_output(output, sizeof(output), binname, pid, ppid, - policynr, policy->name, policy->nfilters, - emulation, name, code, tls, repl); - - /* Fast-path checking */ - if ((action = policy->kerneltable[code]) != ICPOLICY_ASK) - goto out; - - pflq = systrace_policyflq(policy, emulation, name); - if (pflq == NULL) - errx(1, "%s:%d: no filter queue", __func__, __LINE__); - - action = filter_evaluate(tls, pflq, ipid); - if (action != ICPOLICY_ASK) - goto done; - - /* Do aliasing here */ - if (!noalias) - alias = systrace_find_alias(emulation, name); - if (alias != NULL) { - int i; - - /* Set up variables for further filter actions */ - tls = &alitls; - emulation = alias->aemul; - name = alias->aname; - - /* Create an aliased list for filter_evaluate */ - TAILQ_INIT(tls); - for (i = 0; i < alias->nargs; i++) { - memcpy(&alitl[i], alias->arguments[i], - sizeof(struct intercept_translate)); - TAILQ_INSERT_TAIL(tls, &alitl[i], next); - } - - if ((pflq = systrace_policyflq(policy, - alias->aemul, alias->aname)) == NULL) - errx(1, "%s:%d: no filter queue", - __func__, __LINE__); - - action = filter_evaluate(tls, pflq, ipid); - if (action != ICPOLICY_ASK) - goto done; - - make_output(output, sizeof(output), binname, pid, ppid, - policynr, policy->name, policy->nfilters, - alias->aemul, alias->aname, code, tls, NULL); - } - - /* - * At this point, we have to ask the user, but we may check - * if the policy has been updated in the meanwhile. - */ - if (systrace_updatepolicy(fd, policy) == -1) - done = 1; - } while (!done); - - if (policy->flags & POLICY_UNSUPERVISED) { - action = ICPOLICY_NEVER; - dolog = 1; - goto out; - } - - action = filter_ask(fd, tls, pflq, policynr, emulation, name, - output, &future, ipid); - if (future != ICPOLICY_ASK) - filter_modifypolicy(fd, policynr, emulation, name, future); - - if (policy->flags & POLICY_DETACHED) { - if (intercept_detach(fd, pid) == -1) - err(1, "intercept_detach"); - return (action); - } else if (action == ICPOLICY_KILL) { - kill(pid, SIGKILL); - return (ICPOLICY_NEVER); - } - done: - if (ipid->uflags & SYSCALL_LOG) - dolog = 1; - - out: - if (dolog) - log_msg(LOG_WARNING, "%s user: %s, prog: %s", - action < ICPOLICY_NEVER ? "permit" : "deny", - ipid->username, output); - - /* Argument replacement in intercept might still fail */ - - return (action); -} - -short -gen_cb(int fd, pid_t pid, int policynr, const char *name, int code, - const char *emulation, void *args, int argsize, void *cbarg) -{ - char output[_POSIX2_LINE_MAX]; - struct policy *policy; - struct intercept_pid *ipid; - struct filterq *pflq = NULL; - short action = ICPOLICY_PERMIT; - short future; - int off, done = 0, dolog = 0; - size_t len; - - if (policynr == -1) - goto out; - - if ((policy = systrace_findpolnr(policynr)) == NULL) - errx(1, "%s:%d: find %d", __func__, __LINE__, - policynr); - - ipid = intercept_getpid(pid); - ipid->uflags = 0; - - make_output(output, sizeof(output), - ipid->name != NULL ? ipid->name : policy->name, - pid, ipid->ppid, policynr, - policy->name, policy->nfilters, emulation, name, code, - NULL, NULL); - - off = strlen(output); - len = sizeof(output) - off; - if (len > 0) - snprintf(output + off, len, ", args: %d", argsize); - - if ((pflq = systrace_policyflq(policy, emulation, name)) == NULL) - errx(1, "%s:%d: no filter queue", __func__, __LINE__); - - do { - /* Fast-path checking */ - if ((action = policy->kerneltable[code]) != ICPOLICY_ASK) - goto out; - - action = filter_evaluate(NULL, pflq, ipid); - - if (action != ICPOLICY_ASK) - goto haveresult; - /* - * At this point, we have to ask the user, but we may check - * if the policy has been updated in the meanwhile. - */ - if (systrace_updatepolicy(fd, policy) == -1) - done = 1; - } while (!done); - - if (policy->flags & POLICY_UNSUPERVISED) { - action = ICPOLICY_NEVER; - dolog = 1; - goto haveresult; - } - - action = filter_ask(fd, NULL, pflq, policynr, emulation, name, - output, &future, ipid); - if (future != ICPOLICY_ASK) - systrace_modifypolicy(fd, policynr, name, future); - - if (policy->flags & POLICY_DETACHED) { - if (intercept_detach(fd, pid) == -1) - err(1, "intercept_detach"); - } else if (action == ICPOLICY_KILL) { - kill(pid, SIGKILL); - return (ICPOLICY_NEVER); - } - - haveresult: - if (ipid->uflags & SYSCALL_LOG) - dolog = 1; - if (dolog) - log_msg(LOG_WARNING, "%s user: %s, prog: %s", - action < ICPOLICY_NEVER ? "permit" : "deny", - ipid->username, output); - out: - return (action); -} - -void -execres_cb(int fd, pid_t pid, int policynr, const char *emulation, - const char *name, void *arg) -{ - struct policy *policy; - - if (policynr != -1) { - struct intercept_pid *ipid; - - ipid = intercept_getpid(pid); - if (ipid->uflags & PROCESS_DETACH) { - if (intercept_detach(fd, pid) == -1) - err(1, "%s: intercept_detach", __func__); - return; - } - if (inherit) - return; - - if (ipid->uflags & PROCESS_INHERIT_POLICY) - return; - } - if ((policy = systrace_newpolicy(emulation, name)) == NULL) - goto error; - - /* See if this policies runs without interactive feedback */ - if (automatic) - policy->flags |= POLICY_UNSUPERVISED; - - policynr = policy->policynr; - - /* Try to find existing policy in file system */ - if (policynr == -1 && TAILQ_FIRST(&policy->prefilters) == NULL) - systrace_addpolicy(name); - - if (policy->flags & POLICY_DETACHED) { - if (intercept_detach(fd, pid) == -1) - err(1, "intercept_detach"); - return; - } - - if (policynr == -1) { - policynr = systrace_newpolicynr(fd, policy); - if (policynr == -1) - goto error; - } - - if (intercept_assignpolicy(fd, pid, policynr) == -1) - goto error; - - if (TAILQ_FIRST(&policy->prefilters) != NULL) - filter_prepolicy(fd, policy); - - return; - - error: - kill(pid, SIGKILL); - 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); -} - -/* ARGSUSED */ -static void -child_handler(int sig) -{ - int s = errno, status; - - if (signal(SIGCHLD, child_handler) == SIG_ERR) { - close(trfd); - } - - while (wait4(-1, &status, WNOHANG, NULL) > 0) - ; - - errno = s; -} - -static void -log_msg(int priority, const char *fmt, ...) -{ - char buf[_POSIX2_LINE_MAX]; - extern char *__progname; - va_list ap; - - va_start(ap, fmt); - - if (logtofile) { - vsnprintf(buf, sizeof(buf), fmt, ap); - fprintf(logfile, "%s: %s\n", __progname, buf); - } else - vsyslog(priority, fmt, ap); - - va_end(ap); -} - -static void -usage(void) -{ - fprintf(stderr, - "Usage: systrace [-AaCeitUuV] [-c user:group] [-d policydir] [-E logfile]\n" - "\t [-f file] [-g gui] [-p pid] command ...\n"); - exit(1); -} - -int -requestor_start(char *path, int docradle) -{ - char *argv[3]; - int pair[2]; - pid_t pid; - - argv[0] = path; - argv[1] = docradle ? "-C" : NULL; - argv[2] = NULL; - - if (!docradle && socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) - err(1, "socketpair"); - - pid = fork(); - if (pid == -1) - err(1, "fork"); - if (pid == 0) { - if (!docradle) { - close(pair[0]); - if (dup2(pair[1], fileno(stdin)) == -1) - err(1, "dup2"); - if (dup2(pair[1], fileno(stdout)) == -1) - err(1, "dup2"); - setvbuf(stdout, NULL, _IOLBF, 0); - - close(pair[1]); - } - - execvp(path, argv); - - err(1, "execvp: %s", path); - - } - - if (!docradle) { - close(pair[1]); - if (dup2(pair[0], fileno(stdin)) == -1) - err(1, "dup2"); - - if (dup2(pair[0], fileno(stdout)) == -1) - err(1, "dup2"); - - close(pair[0]); - - setvbuf(stdout, NULL, _IOLBF, 0); - - connected = 1; - } - - return (0); -} - - -static void -cradle_setup(char *pathtogui) -{ - struct stat sb; - char cradlepath[PATH_MAX], cradleuipath[PATH_MAX]; - - snprintf(dirpath, sizeof(dirpath), "/tmp/systrace-%d", getuid()); - - if (stat(dirpath, &sb) == -1) { - if (errno != ENOENT) - err(1, "stat()"); - if (mkdir(dirpath, S_IRUSR | S_IWUSR | S_IXUSR) == -1) - err(1, "mkdir()"); - } else { - if (sb.st_uid != getuid()) - errx(1, "Wrong owner on directory %s", dirpath); - if (sb.st_mode != (S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR)) - errx(1, "Wrong permissions on directory %s", dirpath); - } - - strlcpy(cradlepath, dirpath, sizeof (cradlepath)); - strlcat(cradlepath, "/" CRADLE_SERVER, sizeof (cradlepath)); - - strlcpy(cradleuipath, dirpath, sizeof (cradleuipath)); - strlcat(cradleuipath, "/" CRADLE_UI, sizeof (cradleuipath)); - - cradle_start(cradlepath, cradleuipath, pathtogui); -} - -static int -get_uid_gid(const char *argument, uid_t *uid, gid_t *gid) -{ - struct group *gp; - struct passwd *pw; - unsigned long ulval; - char uid_gid_str[128]; - char *endp, *g, *u; - - strlcpy(uid_gid_str, argument, sizeof(uid_gid_str)); - g = uid_gid_str; - u = strsep(&g, ":"); - - if ((pw = getpwnam(u)) != NULL) { - explicit_bzero(pw->pw_passwd, strlen(pw->pw_passwd)); - *uid = pw->pw_uid; - *gid = pw->pw_gid; - /* Ok if group not specified. */ - if (g == NULL) - return (0); - } else { - errno = 0; - ulval = strtoul(u, &endp, 10); - if (u[0] == '\0' || *endp != '\0') - errx(1, "no such user '%s'", u); - if (errno == ERANGE && ulval == ULONG_MAX) - errx(1, "invalid uid %s", u); - *uid = (uid_t)ulval; - } - - if (g == NULL) - return (-1); - - if ((gp = getgrnam(g)) != NULL) - *gid = gp->gr_gid; - else { - errno = 0; - ulval = strtoul(g, &endp, 10); - if (g[0] == '\0' || *endp != '\0') - errx(1, "no such group '%s'", g); - if (errno == ERANGE && ulval == ULONG_MAX) - errx(1, "invalid gid %s", g); - *gid = (gid_t)ulval; - } - - return (0); -} - -static void -systrace_timeout(int fd, short what, void *arg) -{ - struct timeval tv; - - /* Reschedule timeout */ - timerclear(&tv); - tv.tv_sec = SYSTRACE_UPDATETIME; - evtimer_add(&ev_timeout, &tv); - - systrace_updatepolicies(trfd); - if (userpolicy) - systrace_dumppolicies(trfd); -} - -/* - * Read from the kernel if something happened. - */ - -static void -systrace_read(int fd, short what, void *arg) -{ - intercept_read(fd); - - if (!intercept_existpids()) { - event_del(&ev_read); - event_del(&ev_timeout); - } -} - -int -main(int argc, char **argv) -{ - int i, c; - char **args; - char *filename = NULL; - char *policypath = NULL; - const char *errstr; - struct timeval tv; - pid_t pidattach = 0; - int usex11 = 1; - int background; - int setcredentials = 0; - uid_t cr_uid; - gid_t cr_gid; - - while ((c = getopt(argc, argv, "Vc:aAeE:ituUCd:g:f:p:")) != -1) { - switch (c) { - case 'V': - fprintf(stderr, "%s V%s\n", argv[0], VERSION); - exit(0); - case 'c': - setcredentials = 1; - if (get_uid_gid(optarg, &cr_uid, &cr_gid) == -1) - usage(); - break; - case 'a': - if (allow) - usage(); - automatic = 1; - break; - case 'd': - policypath = optarg; - break; - case 'e': - logtofile = 1; - logfile = stderr; - break; - case 'E': - logtofile = 1; - logfile = fopen(optarg, "a"); - if (logfile == NULL) - err(1, "Cannot open \"%s\" for writing", - optarg); - break; - case 'A': - if (automatic) - usage(); - allow = 1; - break; - case 'u': - noalias = 1; - break; - case 'i': - inherit = 1; - break; - case 'g': - guipath = optarg; - break; - case 'C': - cradle = 1; - break; - case 'f': - filename = optarg; - break; - case 'p': - if (setcredentials) - usage(); - pidattach = strtonum(optarg, 1, INT_MAX, &errstr); - if (errstr) { - warnx("bad pid: %s", optarg); - usage(); - } - break; - case 't': - usex11 = 0; - break; - case 'U': - userpolicy = 0; - break; - default: - usage(); - break; - } - } - argc -= optind; - argv += optind; - - if (argc == 0 || (pidattach && *argv[0] != '/')) - usage(); - - systrace_parameters(); - - if (setcredentials && !iamroot) { - fprintf(stderr, "Need to be root to change credentials.\n"); - usage(); - } - - /* Initialize libevent but without kqueue because of systrace fd */ - setenv("EVENT_NOKQUEUE", "yes", 0); - event_init(); - - /* Local initialization */ - systrace_initalias(); - systrace_initpolicy(filename, policypath); - systrace_initcb(); - - if ((trfd = intercept_open()) == -1) - exit(1); - - /* See if we can run the systrace process in the background */ - background = usex11 || automatic || allow; - - if (pidattach == 0) { - /* Run a command and attach to it */ - args = reallocarray(NULL, argc + 1, sizeof(char *)); - if (args == NULL) - err(1, "malloc"); - - for (i = 0; i < argc; i++) - args[i] = argv[i]; - args[i] = NULL; - - if (setcredentials) - trpid = intercept_run(background, &trfd, - cr_uid, cr_gid, args[0], args); - else - trpid = intercept_run(background, &trfd, 0, 0, - args[0], args); - if (trpid == -1) - err(1, "fork"); - - if (intercept_attach(trfd, trpid) == -1) - err(1, "attach"); - - if (kill(trpid, SIGUSR1) == -1) - err(1, "kill"); - } else { - /* Attach to a running command */ - if (intercept_attachpid(trfd, pidattach, argv[0]) == -1) - err(1, "attachpid"); - - if (background) { - if (daemon(1, 1) == -1) - err(1, "daemon"); - } - } - - if (signal(SIGCHLD, child_handler) == SIG_ERR) - err(1, "signal"); - - if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) - err(1, "signal"); - - /* Start the policy GUI or cradle if necessary */ - if (usex11 && (!automatic && !allow)) { - if (cradle) - cradle_setup(guipath); - else - requestor_start(guipath, 0); - - } - - /* Register read events */ - event_set(&ev_read, trfd, EV_READ|EV_PERSIST, systrace_read, NULL); - event_add(&ev_read, NULL); - - if (userpolicy || automatic) { - evtimer_set(&ev_timeout, systrace_timeout, &ev_timeout); - timerclear(&tv); - tv.tv_sec = SYSTRACE_UPDATETIME; - evtimer_add(&ev_timeout, &tv); - } - - /* Wait for events */ - event_dispatch(); - - if (userpolicy) - systrace_dumppolicies(trfd); - - close(trfd); - - exit(0); -} diff --git a/bin/systrace/systrace.h b/bin/systrace/systrace.h deleted file mode 100644 index 9ec8952c61e..00000000000 --- a/bin/systrace/systrace.h +++ /dev/null @@ -1,250 +0,0 @@ -/* $OpenBSD: systrace.h,v 1.28 2016/03/01 16:26:06 naddy Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _SYSTRACE_H_ -#define _SYSTRACE_H_ -#include <sys/queue.h> - -#define _PATH_XSYSTRACE "/usr/X11R6/bin/xsystrace" - -enum logicop { LOGIC_AND, LOGIC_OR, LOGIC_NOT, LOGIC_SINGLE }; - -struct logic { - enum logicop op; - struct logic *left; - struct logic *right; - char *type; - int typeoff; - int flags; - void *filterdata; - size_t filterlen; - int (*filter_match)(struct intercept_translate *, struct logic *); - void *filterarg; -}; - -#define LOGIC_NEEDEXPAND 0x01 - -struct filter { - TAILQ_ENTRY(filter) next; - TAILQ_ENTRY(filter) policy_next; - - char *rule; - char name[32]; - char emulation[16]; - struct logic *logicroot; - short match_action; - int match_error; - int match_flags; - int match_count; /* Number of times this filter matched */ - - struct predicate { -#define PREDIC_UID 0x01 -#define PREDIC_GID 0x02 -#define PREDIC_NEGATIVE 0x10 -#define PREDIC_LESSER 0x20 -#define PREDIC_GREATER 0x30 -#define PREDIC_MASK 0x30 - int p_flags; - uid_t p_uid; - gid_t p_gid; - } match_predicate; - - struct elevate elevate; -}; - -TAILQ_HEAD(filterq, filter); - -struct policy_syscall { - SPLAY_ENTRY(policy_syscall) node; - - char name[64]; - char emulation[16]; - - struct filterq flq; -}; - -struct policy { - SPLAY_ENTRY(policy) node; - SPLAY_ENTRY(policy) nrnode; - - const char *name; - char emulation[16]; - - struct timespec ts_last; /* last time we read the file */ - - SPLAY_HEAD(syscalltree, policy_syscall) pflqs; - - int policynr; /* in-kernel policy number */ - short kerneltable[INTERCEPT_MAXSYSCALLNR]; - int flags; - - struct filterq filters; - int nfilters; /* nr of installed policy statements */ - struct filterq prefilters; /* filters we need to install*/ -}; - -struct template { - TAILQ_ENTRY(template) next; - - char *filename; - char *name; - char *description; - - char *emulation; -}; - -TAILQ_HEAD(tmplqueue, template); - -#define POLICY_PATH "/etc/systrace" - -#define POLICY_UNSUPERVISED 0x01 /* Auto-Pilot */ -#define POLICY_DETACHED 0x02 /* Ignore this program */ -#define POLICY_CHANGED 0x04 - -#define PROCESS_INHERIT_POLICY 0x01 /* Process inherits policy */ -#define PROCESS_DETACH 0x02 /* Process gets detached */ -#define SYSCALL_LOG 0x04 /* Log this system call */ -#define PROCESS_PROMPT 0x08 /* Prompt but nothing else */ - -#define SYSTRACE_UPDATETIME 30 /* update policies every 30 seconds */ - -void systrace_parameters(void); -int systrace_initpolicy(char *, char *); -void systrace_setupdir(char *); -struct template *systrace_readtemplate(char *, struct policy *, - struct template *); -void systrace_initcb(void); -struct policy *systrace_newpolicy(const char *, const char *); -void systrace_cleanpolicy(struct policy *); -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 *); -struct policy *systrace_findpolicy_wildcard(const char *); -struct policy *systrace_findpolnr(int); -int systrace_dumppolicies(int); -int systrace_updatepolicies(int); -struct policy *systrace_readpolicy(const char *); -int systrace_addpolicy(const char *); -int systrace_updatepolicy(int fd, struct policy *policy); -struct filterq *systrace_policyflq(struct policy *, const char *, const char *); -char *systrace_getpolicyname(const char *); - -int systrace_error_translate(char *); - -#define SYSTRACE_MAXALIAS 10 - -struct systrace_alias { - SPLAY_ENTRY(systrace_alias) node; - TAILQ_ENTRY(systrace_alias) next; - - char name[64]; - char emulation[16]; - - char aname[64]; - char aemul[16]; - - struct intercept_translate *arguments[SYSTRACE_MAXALIAS]; - int nargs; - - struct systrace_revalias *reverse; -}; - -int systrace_initalias(void); -struct systrace_alias *systrace_new_alias(const char *, const char *, char *, char *); -void systrace_switch_alias(const char *, const char *, char *, char *); -struct systrace_alias *systrace_find_alias(const char *, const char *); -void systrace_alias_add_trans(struct systrace_alias *, - struct intercept_translate *); - -struct systrace_revalias { - SPLAY_ENTRY(systrace_revalias) node; - - char name[64]; - char emulation[16]; - - TAILQ_HEAD(revaliasq, systrace_alias) revl; -}; - -struct systrace_revalias *systrace_reverse(const char *, const char *); -struct systrace_revalias *systrace_find_reverse(const char *, const char *); - -short filter_evaluate(struct intercept_tlq *, struct filterq *, - struct intercept_pid *); -short filter_ask(int, struct intercept_tlq *, struct filterq *, int, - const char *, const char *, char *, short *, struct intercept_pid *); -void filter_free(struct filter *); -void filter_modifypolicy(int, int, const char *, const char *, short); - -int filter_predicate(struct intercept_pid *, struct predicate *); -int filter_parse_simple(char *, short *, short *); -int filter_parse(char *, struct filter **); -int filter_prepolicy(int, struct policy *); -char *filter_expand(char *); -char *filter_dynamicexpand(struct intercept_pid *, char *); -int filter_needexpand(char *); - -void cradle_start(char *, char *, char *); - -int parse_filter(char *, struct filter **); - -char *uid_to_name(uid_t); - -char *strrpl(char *, size_t, char *, char *); - -void make_output(char *, size_t, const char *, pid_t, pid_t, int, - const char *, int, const char *, const char *, int, struct intercept_tlq *, - struct intercept_replace *); -short trans_cb(int, pid_t, int, const char *, int, const char *, void *, - int, struct intercept_replace *, struct intercept_tlq *, 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; -extern struct intercept_translate ic_fdt; -extern struct intercept_translate ic_uidt; -extern struct intercept_translate ic_uname; -extern struct intercept_translate ic_gidt; -extern struct intercept_translate ic_trargv; -extern struct intercept_translate ic_sockdom; -extern struct intercept_translate ic_socktype; -extern struct intercept_translate ic_pidname; -extern struct intercept_translate ic_signame; -extern struct intercept_translate ic_fcntlcmd; -extern struct intercept_translate ic_memprot; -extern struct intercept_translate ic_fileflags; - -int requestor_start(char *, int); - -#endif /* _SYSTRACE_H_ */ diff --git a/bin/systrace/util.c b/bin/systrace/util.c deleted file mode 100644 index 5790c1596a6..00000000000 --- a/bin/systrace/util.c +++ /dev/null @@ -1,213 +0,0 @@ -/* $OpenBSD: util.c,v 1.13 2015/09/29 20:11:36 tedu Exp $ */ -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/types.h> -#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); - /* FALLTHROUGH */ - default: - escape[p++] = a; - } - } - - escape[p] = '\0'; - return (escape); -} - -char * -strrpl(char *str, size_t size, char *match, char *value) -{ - char *p, *e; - int len, rlen; - - p = str; - e = p + strlen(p); - len = strlen(match); - - /* Try to match against the variable */ - while ((p = strchr(p, match[0])) != NULL) { - if (!strncmp(p, match, len) && !isalnum((unsigned char)p[len])) - break; - p += len; - - if (p >= e) - return (NULL); - } - - if (p == NULL) - return (NULL); - - rlen = strlen(value); - - if (strlen(str) - len + rlen > size) - return (NULL); - - memmove(p + rlen, p + len, strlen(p + len) + 1); - memcpy(p, value, rlen); - - return (p); -} - -/* simplify_path is from pdksh and apparently in the public domain */ - -/* ISABSPATH() means path is fully and completely specified, - * ISROOTEDPATH() means a .. as the first component is a no-op, - * ISRELPATH() means $PWD can be tacked on to get an absolute path. - * - * OS Path ISABSPATH ISROOTEDPATH ISRELPATH - * unix /foo yes yes no - * unix foo no no yes - * unix ../foo no no yes - * os2+cyg a:/foo yes yes no - * os2+cyg a:foo no no no - * os2+cyg /foo no yes no - * os2+cyg foo no no yes - * os2+cyg ../foo no no yes - * cyg //foo yes yes no - */ -# define PATHSEP ':' -# define DIRSEP '/' -# define DIRSEPSTR "/" -# define ISDIRSEP(c) ((c) == '/') -# define ISABSPATH(s) ISDIRSEP((s)[0]) -# define ISRELPATH(s) (!ISABSPATH(s)) -# define ISROOTEDPATH(s) ISABSPATH(s) -# define FILECHCONV(c) c -# define FILECMP(s1, s2) strcmp(s1, s2) -# define FILENCMP(s1, s2, n) strncmp(s1, s2, n) -# define ksh_strchr_dirsep(p) strchr(p, DIRSEP) -# define ksh_strrchr_dirsep(p) strrchr(p, DIRSEP) - -/* simplify_path is from pdksh */ - -/* - * Simplify pathnames containing "." and ".." entries. - * ie, simplify_path("/a/b/c/./../d/..") returns "/a/b" - */ -void -simplify_path(path) - char *path; -{ - char *cur; - char *t; - int isrooted; - char *very_start = path; - char *start; - - if (!*path) - return; - - if ((isrooted = ISROOTEDPATH(path))) - very_start++; - - /* Before After - * /foo/ /foo - * /foo/../../bar /bar - * /foo/./blah/.. /foo - * . . - * .. .. - * ./foo foo - * foo/../../../bar ../../bar - * OS2 and CYGWIN: - * a:/foo/../.. a:/ - * a:. a: - * a:.. a:.. - * a:foo/../../blah a:../blah - */ - - - for (cur = t = start = very_start; ; ) { - /* treat multiple '/'s as one '/' */ - while (ISDIRSEP(*t)) - t++; - - if (*t == '\0') { - if (cur == path) - /* convert empty path to dot */ - *cur++ = '.'; - *cur = '\0'; - break; - } - - if (t[0] == '.') { - if (!t[1] || ISDIRSEP(t[1])) { - t += 1; - continue; - } else if (t[1] == '.' && (!t[2] || ISDIRSEP(t[2]))) { - if (!isrooted && cur == start) { - if (cur != very_start) - *cur++ = DIRSEP; - *cur++ = '.'; - *cur++ = '.'; - start = cur; - } else if (cur != start) - while (--cur > start && !ISDIRSEP(*cur)) - ; - t += 2; - continue; - } - } - - if (cur != very_start) - *cur++ = DIRSEP; - - /* find/copy next component of pathname */ - while (*t && !ISDIRSEP(*t)) - *cur++ = *t++; - } -} diff --git a/bin/systrace/util.h b/bin/systrace/util.h deleted file mode 100644 index c37315d1201..00000000000 --- a/bin/systrace/util.h +++ /dev/null @@ -1,40 +0,0 @@ -/* $OpenBSD: util.h,v 1.3 2003/06/16 06:36:40 itojun Exp $ */ - -/* - * Copyright 2002 Niels Provos <provos@citi.umich.edu> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Niels Provos. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _UTIL_H_ -#define _UTIL_H_ - -void simplify_path(char *); -char *strescape(char *); -char *strrpl(char *, size_t, char *, char *); - -#endif /* !_UTIL_H_ */ |