int loadrulefile() { FILE *fp; char line[1024]; char *tmp; int failed = 0; flush_rules(); fp = fopen(DEFAULT_RULESFILE, "r"); if (!fp) { fprintf(stderr,"Rules file not found !\n"); return 0; } if (verbose) printf("Loading filter rules\n"); while (!feof(fp)) { if (!fgets(line, 1023, fp)) break; if ((tmp = strchr(line, '\r')) != NULL) *tmp = '\0'; if ((tmp = strchr(line, '\n')) != NULL) *tmp = '\0'; if (line[0] == '#' || line[0] == '\0') continue; if ((add_rule(line)) == NULL) { fprintf(stderr,"Cannot add rule `%s'\n",line); failed = 1; break; } else { if (vv) printf("%s\n",line); } } fclose(fp); if (failed) { fprintf(stderr, "Rules loading cancelled, flushing\n"); flush_rules(); return 0; } if (verbose) printf("Rules loaded\n"); return 1; }
static secadm_error_t handle_add_rule(struct thread *td, secadm_command_t *cmd, secadm_reply_t *reply) { secadm_rule_t *rule, *next, *tail; struct secadm_prison_entry *entry; size_t maxid=0; secadm_error_t res=secadm_success; int err; entry = get_prison_list_entry(td->td_ucred->cr_prison->pr_name, 1); rule = malloc(sizeof(secadm_rule_t), M_SECADM, M_WAITOK); if ((err = copyin(cmd->sc_metadata, rule, sizeof(secadm_rule_t))) != 0) { free(rule, M_SECADM); reply->sr_code = secadm_fail; reply->sr_errno = err; return (secadm_fail); } if (read_rule_from_userland(td, rule)) { reply->sr_errno = EINVAL; rule->sr_next = NULL; goto error; } rule->sr_id = maxid++; tail = rule; while (tail->sr_next != NULL) { next = malloc(sizeof(secadm_rule_t), M_SECADM, M_WAITOK); if ((err = copyin(tail->sr_next, next, sizeof(secadm_rule_t))) != 0) { reply->sr_errno = err; free(next, M_SECADM); tail->sr_next = NULL; goto error; } if (read_rule_from_userland(td, next)) { res=secadm_fail; reply->sr_errno = EINVAL; free_rule(next, 1); tail->sr_next = NULL; goto error; } next->sr_id = maxid++; tail->sr_next = next; tail = next; } if (validate_ruleset(td, rule)) { res = secadm_fail; reply->sr_errno = EINVAL; goto error; } flush_rules(td); SPL_WLOCK(entry); entry->spl_rules = rule; entry->spl_max_id = maxid; SPL_WUNLOCK(entry); reply->sr_code = secadm_success; reply->sr_errno = 0; return (0); error: while (rule != NULL) { next = rule->sr_next; free_rule(rule, 1); rule = next; } reply->sr_code = secadm_fail; return (res); }
static int sysctl_control(SYSCTL_HANDLER_ARGS) { secadm_command_t cmd; secadm_reply_t reply; int err; if (!(req->newptr) || (req->newlen != sizeof(secadm_command_t))) return (EINVAL); if (!(req->oldptr) || (req->oldlen) != sizeof(secadm_reply_t)) return (EINVAL); err = SYSCTL_IN(req, &cmd, sizeof(secadm_command_t)); if (err) return (err); /* Access control comes first */ switch (cmd.sc_type) { case secadm_flush_rules: case secadm_set_rules: /* XXX Should we cache the ucred for local use in the * sysctl lifecycle? */ // XXXOP LOCKING if (req->td->td_ucred->cr_uid != 0) { printf("[SECADM] Disallowed command: 0x%x by uid: %d\n", cmd.sc_type, req->td->td_ucred->cr_uid); return (EPERM); } // XXXOP LOCKING if (securelevel_gt(req->td->td_ucred, 0)) { printf("[SECADM] Disallowed command: 0x%x by uid: %d\n", cmd.sc_type, req->td->td_ucred->cr_uid); return (EPERM); } break; default: break; } /* XXX We should relax this check once we get stable releases. */ if (cmd.sc_version < SECADM_VERSION) return (EINVAL); memset(&reply, 0x00, sizeof(reply)); if ((err = copyin(req->oldptr, &reply, sizeof(reply)))) return (err); reply.sr_version = SECADM_VERSION; reply.sr_id = cmd.sc_id; switch (cmd.sc_type) { case secadm_get_version: if (cmd.sc_bufsize < sizeof(unsigned long)) return (EINVAL); handle_version_command(&cmd, &reply); break; case secadm_set_rules: if (cmd.sc_size != sizeof(secadm_rule_t)) return (EINVAL); handle_add_rule(req->td, &cmd, &reply); break; case secadm_flush_rules: flush_rules(req->td); break; case secadm_get_rule_size: handle_get_rule_size(req->td, &cmd, &reply); break; case secadm_get_num_rules: get_num_rules(req->td, &cmd, &reply); break; case secadm_get_rule: handle_get_rule(req->td, &cmd, &reply); break; case secadm_get_rules: case secadm_get_admins: case secadm_set_admins: case secadm_get_views: case secadm_set_views: return (ENOTSUP); default: // XXXOP LOCKING printf("[SECADM] Unknown command: 0x%x by uid: %d\n", cmd.sc_type, req->td->td_ucred->cr_uid); return (EINVAL); } err = SYSCTL_OUT(req, &reply, sizeof(secadm_reply_t)); return (err); }