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); }
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); }
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); }
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); }