int secfw_write(struct cdev *dev, struct uio *uio, int ioflag) { secfw_rule_t *rule; secfw_command_t cmd; int error = 0; if (uio->uio_iov->iov_len != sizeof(secfw_command_t)) return (EINVAL); error = copyin(uio->uio_iov->iov_base, &cmd, uio->uio_iov->iov_len); if (error != 0) return (error); switch (cmd.sc_type) { case secfw_insert_rule: rule = read_rule_from_userland(curthread, cmd.sc_metadata, cmd.sc_size); if (rule == NULL) return (EINVAL); break; default: return (EINVAL); } return (0); }
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); }