diff options
Diffstat (limited to 'sys/security')
| -rw-r--r-- | sys/security/audit/audit.c | 2 | ||||
| -rw-r--r-- | sys/security/audit/audit_bsm_db.c | 28 | ||||
| -rw-r--r-- | sys/security/audit/audit_pipe.c | 1 | ||||
| -rw-r--r-- | sys/security/audit/audit_syscalls.c | 47 | ||||
| -rw-r--r-- | sys/security/mac/mac_framework.c | 4 | ||||
| -rw-r--r-- | sys/security/mac_bsdextended/mac_bsdextended.c | 4 | ||||
| -rw-r--r-- | sys/security/mac_do/mac_do.c | 56 |
7 files changed, 81 insertions, 61 deletions
diff --git a/sys/security/audit/audit.c b/sys/security/audit/audit.c index 7ec50d990d4e..876776e5f62e 100644 --- a/sys/security/audit/audit.c +++ b/sys/security/audit/audit.c @@ -329,7 +329,7 @@ audit_record_dtor(void *mem, int size, void *arg) * call into the BSM assembly code to initialize it. */ static void -audit_init(void) +audit_init(void *dummy __unused) { audit_trail_enabled = 0; diff --git a/sys/security/audit/audit_bsm_db.c b/sys/security/audit/audit_bsm_db.c index c9f3d5c8a549..358162544287 100644 --- a/sys/security/audit/audit_bsm_db.c +++ b/sys/security/audit/audit_bsm_db.c @@ -56,6 +56,8 @@ #include <security/audit/audit.h> #include <security/audit/audit_private.h> +#include <contrib/ck/include/ck_queue.h> + /* * Hash table functions for the audit event number to event class mask * mapping. @@ -64,21 +66,21 @@ struct evclass_elem { au_event_t event; au_class_t class; - LIST_ENTRY(evclass_elem) entry; + CK_LIST_ENTRY(evclass_elem) entry; }; struct evclass_list { - LIST_HEAD(, evclass_elem) head; + CK_LIST_HEAD(, evclass_elem) head; }; static MALLOC_DEFINE(M_AUDITEVCLASS, "audit_evclass", "Audit event class"); -static struct rwlock evclass_lock; static struct evclass_list evclass_hash[EVCLASSMAP_HASH_TABLE_SIZE]; - -#define EVCLASS_LOCK_INIT() rw_init(&evclass_lock, "evclass_lock") -#define EVCLASS_RLOCK() rw_rlock(&evclass_lock) -#define EVCLASS_RUNLOCK() rw_runlock(&evclass_lock) -#define EVCLASS_WLOCK() rw_wlock(&evclass_lock) -#define EVCLASS_WUNLOCK() rw_wunlock(&evclass_lock) +static struct mtx evclass_mtx; +#define EVCLASS_LOCK_INIT() mtx_init(&evclass_mtx, "evclass_lock", NULL, MTX_DEF) +#define EVCLASS_WLOCK() mtx_lock(&evclass_mtx); +#define EVCLASS_WUNLOCK() mtx_unlock(&evclass_mtx); +/* make these do something if we ever remove entries from the hash */ +#define EVCLASS_RLOCK() {} +#define EVCLASS_RUNLOCK() {} /* * Hash table maintaining a mapping from audit event numbers to audit event @@ -118,7 +120,7 @@ au_event_class(au_event_t event) EVCLASS_RLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; class = 0; - LIST_FOREACH(evc, &evcl->head, entry) { + CK_LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { class = evc->class; goto out; @@ -150,7 +152,7 @@ au_evclassmap_insert(au_event_t event, au_class_t class) EVCLASS_WLOCK(); evcl = &evclass_hash[event % EVCLASSMAP_HASH_TABLE_SIZE]; - LIST_FOREACH(evc, &evcl->head, entry) { + CK_LIST_FOREACH(evc, &evcl->head, entry) { if (evc->event == event) { evc->class = class; EVCLASS_WUNLOCK(); @@ -161,7 +163,7 @@ au_evclassmap_insert(au_event_t event, au_class_t class) evc = evc_new; evc->event = event; evc->class = class; - LIST_INSERT_HEAD(&evcl->head, evc, entry); + CK_LIST_INSERT_HEAD(&evcl->head, evc, entry); EVCLASS_WUNLOCK(); } @@ -172,7 +174,7 @@ au_evclassmap_init(void) EVCLASS_LOCK_INIT(); for (i = 0; i < EVCLASSMAP_HASH_TABLE_SIZE; i++) - LIST_INIT(&evclass_hash[i].head); + CK_LIST_INIT(&evclass_hash[i].head); /* * Set up the initial event to class mapping for system calls. diff --git a/sys/security/audit/audit_pipe.c b/sys/security/audit/audit_pipe.c index fb773fd04297..4d9815467e1a 100644 --- a/sys/security/audit/audit_pipe.c +++ b/sys/security/audit/audit_pipe.c @@ -243,6 +243,7 @@ static const struct filterops audit_pipe_read_filterops = { .f_attach = NULL, .f_detach = audit_pipe_kqdetach, .f_event = audit_pipe_kqread, + .f_copy = knote_triv_copy, }; /* diff --git a/sys/security/audit/audit_syscalls.c b/sys/security/audit/audit_syscalls.c index 40b2fb3d1c9f..f50c627b7515 100644 --- a/sys/security/audit/audit_syscalls.c +++ b/sys/security/audit/audit_syscalls.c @@ -54,6 +54,29 @@ #ifdef AUDIT +static int +audit_priv_check_cred(struct ucred *cred, int priv) +{ + int error; + + error = priv_check_cred(cred, priv); + if (error == EPERM && jailed(cred)) { + /* + * The audit system calls historically returned ENOSYS when + * invoked from within a jail, and some userspace applications + * handle that case specially. Thus, convert the error here. + */ + error = ENOSYS; + } + return (error); +} + +static int +audit_priv_check(struct thread *td, int priv) +{ + return (audit_priv_check_cred(td->td_ucred, priv)); +} + /* * System call to allow a user space application to submit a BSM audit record * to the kernel for inclusion in the audit log. This function does little @@ -592,9 +615,7 @@ sys_getauid(struct thread *td, struct getauid_args *uap) { int error; - if (jailed(td->td_ucred)) - return (ENOSYS); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); return (copyout(&td->td_ucred->cr_audit.ai_auid, uap->auid, @@ -609,8 +630,6 @@ sys_setauid(struct thread *td, struct setauid_args *uap) au_id_t id; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auid, &id, sizeof(id)); if (error) return (error); @@ -624,7 +643,7 @@ sys_setauid(struct thread *td, struct setauid_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; newcred->cr_audit.ai_auid = id; @@ -650,9 +669,7 @@ sys_getaudit(struct thread *td, struct getaudit_args *uap) int error; cred = td->td_ucred; - if (jailed(cred)) - return (ENOSYS); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); if (cred->cr_audit.ai_termid.at_type == AU_IPv6) @@ -674,8 +691,6 @@ sys_setaudit(struct thread *td, struct setaudit_args *uap) struct auditinfo ai; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auditinfo, &ai, sizeof(ai)); if (error) return (error); @@ -689,7 +704,7 @@ sys_setaudit(struct thread *td, struct setaudit_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; bzero(&newcred->cr_audit, sizeof(newcred->cr_audit)); @@ -715,11 +730,9 @@ sys_getaudit_addr(struct thread *td, struct getaudit_addr_args *uap) { int error; - if (jailed(td->td_ucred)) - return (ENOSYS); if (uap->length < sizeof(*uap->auditinfo_addr)) return (EOVERFLOW); - error = priv_check(td, PRIV_AUDIT_GETAUDIT); + error = audit_priv_check(td, PRIV_AUDIT_GETAUDIT); if (error) return (error); return (copyout(&td->td_ucred->cr_audit, uap->auditinfo_addr, @@ -734,8 +747,6 @@ sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) struct auditinfo_addr aia; int error; - if (jailed(td->td_ucred)) - return (ENOSYS); error = copyin(uap->auditinfo_addr, &aia, sizeof(aia)); if (error) return (error); @@ -752,7 +763,7 @@ sys_setaudit_addr(struct thread *td, struct setaudit_addr_args *uap) if (error) goto fail; #endif - error = priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); + error = audit_priv_check_cred(oldcred, PRIV_AUDIT_SETAUDIT); if (error) goto fail; newcred->cr_audit = aia; diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index d742b5dcbc3a..b0776160cc74 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -320,7 +320,7 @@ mac_policy_xlock_assert(void) * Initialize the MAC subsystem, including appropriate SMP locks. */ static void -mac_init(void) +mac_init(void *dummy __unused) { LIST_INIT(&mac_static_policy_list); @@ -340,7 +340,7 @@ mac_init(void) * kernel, or loaded before the kernel startup. */ static void -mac_late_init(void) +mac_late_init(void *dummy __unused) { mac_late = 1; diff --git a/sys/security/mac_bsdextended/mac_bsdextended.c b/sys/security/mac_bsdextended/mac_bsdextended.c index 8a6549214380..bf95c008e2f2 100644 --- a/sys/security/mac_bsdextended/mac_bsdextended.c +++ b/sys/security/mac_bsdextended/mac_bsdextended.c @@ -246,7 +246,9 @@ ugidfw_rulecheck(struct mac_bsdextended_rule *rule, } if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) { - match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && + match = ((cred->cr_gid <= rule->mbr_subject.mbs_gid_max && + cred->cr_gid >= rule->mbr_subject.mbs_gid_min) || + (cred->cr_rgid <= rule->mbr_subject.mbs_gid_max && cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) || (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max && cred->cr_svgid >= rule->mbr_subject.mbs_gid_min)); diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c index 8856be5fa1a3..2bcff7bba973 100644 --- a/sys/security/mac_do/mac_do.c +++ b/sys/security/mac_do/mac_do.c @@ -44,7 +44,7 @@ SYSCTL_INT(_security_mac_do, OID_AUTO, print_parse_error, CTLFLAG_RWTUN, &print_parse_error, 0, "Print parse errors on setting rules " "(via sysctl(8))."); -static MALLOC_DEFINE(M_DO, "do_rule", "Rules for mac_do"); +static MALLOC_DEFINE(M_MAC_DO, "mac_do", "mac_do(4) security module"); #define MAC_RULE_STRING_LEN 1024 @@ -319,17 +319,17 @@ toast_rules(struct rules *const rules) struct rule *rule, *rule_next; STAILQ_FOREACH_SAFE(rule, head, r_entries, rule_next) { - free(rule->uids, M_DO); - free(rule->gids, M_DO); - free(rule, M_DO); + free(rule->uids, M_MAC_DO); + free(rule->gids, M_MAC_DO); + free(rule, M_MAC_DO); } - free(rules, M_DO); + free(rules, M_MAC_DO); } static struct rules * alloc_rules(void) { - struct rules *const rules = malloc(sizeof(*rules), M_DO, M_WAITOK); + struct rules *const rules = malloc(sizeof(*rules), M_MAC_DO, M_WAITOK); _Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!"); rules->string[0] = 0; @@ -433,7 +433,7 @@ static void make_parse_error(struct parse_error **const parse_error, const size_t pos, const char *const fmt, ...) { - struct parse_error *const err = malloc(sizeof(*err), M_DO, M_WAITOK); + struct parse_error *const err = malloc(sizeof(*err), M_MAC_DO, M_WAITOK); va_list ap; err->pos = pos; @@ -448,7 +448,7 @@ make_parse_error(struct parse_error **const parse_error, const size_t pos, static void free_parse_error(struct parse_error *const parse_error) { - free(parse_error, M_DO); + free(parse_error, M_MAC_DO); } static int @@ -733,7 +733,7 @@ parse_target_clause(char *to, struct rule *const rule, "Too many target clauses of type '%s'.", to_type); return (EOVERFLOW); } - ie = malloc(sizeof(*ie), M_DO, M_WAITOK); + ie = malloc(sizeof(*ie), M_MAC_DO, M_WAITOK); ie->spec = is; STAILQ_INSERT_TAIL(list, ie, ie_entries); check_type_and_id_spec(type, &is); @@ -784,7 +784,7 @@ pour_list_into_rule(const id_type_t type, struct id_list *const list, STAILQ_FOREACH_SAFE(ie, list, ie_entries, ie_next) { MPASS(idx < *nb); array[idx] = ie->spec; - free(ie, M_DO); + free(ie, M_MAC_DO); ++idx; } MPASS(idx == *nb); @@ -874,7 +874,7 @@ parse_single_rule(char *rule, struct rules *const rules, STAILQ_INIT(&gid_list); /* Freed when the 'struct rules' container is freed. */ - new = malloc(sizeof(*new), M_DO, M_WAITOK | M_ZERO); + new = malloc(sizeof(*new), M_MAC_DO, M_WAITOK | M_ZERO); from_type = strsep_noblanks(&rule, "="); MPASS(from_type != NULL); /* Because 'rule' was not NULL. */ @@ -933,7 +933,7 @@ parse_single_rule(char *rule, struct rules *const rules, } while (to_list != NULL); if (new->uids_nb != 0) { - new->uids = malloc(sizeof(*new->uids) * new->uids_nb, M_DO, + new->uids = malloc(sizeof(*new->uids) * new->uids_nb, M_MAC_DO, M_WAITOK); error = pour_list_into_rule(IT_UID, &uid_list, new->uids, &new->uids_nb, parse_error); @@ -949,7 +949,7 @@ parse_single_rule(char *rule, struct rules *const rules, } if (new->gids_nb != 0) { - new->gids = malloc(sizeof(*new->gids) * new->gids_nb, M_DO, + new->gids = malloc(sizeof(*new->gids) * new->gids_nb, M_MAC_DO, M_WAITOK); error = pour_list_into_rule(IT_GID, &gid_list, new->gids, &new->gids_nb, parse_error); @@ -969,13 +969,13 @@ parse_single_rule(char *rule, struct rules *const rules, return (0); einval: - free(new->gids, M_DO); - free(new->uids, M_DO); - free(new, M_DO); + free(new->gids, M_MAC_DO); + free(new->uids, M_MAC_DO); + free(new, M_MAC_DO); STAILQ_FOREACH_SAFE(ie, &gid_list, ie_entries, ie_next) - free(ie, M_DO); + free(ie, M_MAC_DO); STAILQ_FOREACH_SAFE(ie, &uid_list, ie_entries, ie_next) - free(ie, M_DO); + free(ie, M_MAC_DO); MPASS(*parse_error != NULL); return (EINVAL); } @@ -1028,7 +1028,7 @@ parse_rules(const char *const string, struct rules **const rulesp, bcopy(string, rules->string, len + 1); MPASS(rules->string[len] == '\0'); /* Catch some races. */ - copy = malloc(len + 1, M_DO, M_WAITOK); + copy = malloc(len + 1, M_MAC_DO, M_WAITOK); bcopy(string, copy, len + 1); MPASS(copy[len] == '\0'); /* Catch some races. */ @@ -1046,7 +1046,7 @@ parse_rules(const char *const string, struct rules **const rulesp, *rulesp = rules; out: - free(copy, M_DO); + free(copy, M_MAC_DO); return (error); } @@ -1226,7 +1226,7 @@ parse_and_set_rules(struct prison *const pr, const char *rules_string, static int mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) { - char *const buf = malloc(MAC_RULE_STRING_LEN, M_DO, M_WAITOK); + char *const buf = malloc(MAC_RULE_STRING_LEN, M_MAC_DO, M_WAITOK); struct prison *const td_pr = req->td->td_ucred->cr_prison; struct prison *pr; struct rules *rules; @@ -1250,7 +1250,7 @@ mac_do_sysctl_rules(SYSCTL_HANDLER_ARGS) free_parse_error(parse_error); } out: - free(buf, M_DO); + free(buf, M_MAC_DO); return (error); } @@ -1573,7 +1573,7 @@ set_data_header(void *const data, const size_t size, const int priv, static void * alloc_data(void *const data, const size_t size) { - struct mac_do_data_header *const hdr = realloc(data, size, M_DO, + struct mac_do_data_header *const hdr = realloc(data, size, M_MAC_DO, M_WAITOK); MPASS(size >= sizeof(struct mac_do_data_header)); @@ -1602,7 +1602,7 @@ alloc_data(void *const data, const size_t size) static void dealloc_thread_osd(void *const value) { - free(value, M_DO); + free(value, M_MAC_DO); } /* @@ -1650,7 +1650,7 @@ rule_grant_supplementary_groups(const struct rule *const rule, const bool current_has_supp = (gid_flags & MDF_CURRENT) != 0 && (gid_flags & MDF_SUPP_MASK) != 0; id_nb_t rule_idx = 0; - int old_idx = 1, new_idx = 1; + int old_idx = 0, new_idx = 0; if ((gid_flags & MDF_ANY_SUPP) != 0 && (gid_flags & MDF_MAY_REJ_SUPP) == 0) @@ -1992,6 +1992,10 @@ check_proc(void) /* * Only grant privileges if requested by the right executable. * + * As MAC/do configuration is per-jail, in order to avoid confused + * deputy situations in chroots (privileged or unprivileged), make sure + * to check the path from the current jail's root. + * * XXXOC: We may want to base this check on a tunable path and/or * a specific MAC label. Going even further, e.g., envisioning to * completely replace the path check with the latter, we would need to @@ -2003,7 +2007,7 @@ check_proc(void) * setting a MAC label per file (perhaps via additions to mtree(1)). So * this probably isn't going to happen overnight, if ever. */ - if (vn_fullpath(curproc->p_textvp, &path, &to_free) != 0) + if (vn_fullpath_jail(curproc->p_textvp, &path, &to_free) != 0) return (EPERM); error = strcmp(path, "/usr/bin/mdo") == 0 ? 0 : EPERM; free(to_free, M_TEMP); |
