aboutsummaryrefslogtreecommitdiff
path: root/sys/security
diff options
context:
space:
mode:
Diffstat (limited to 'sys/security')
-rw-r--r--sys/security/audit/audit.c2
-rw-r--r--sys/security/audit/audit_bsm_db.c28
-rw-r--r--sys/security/audit/audit_pipe.c1
-rw-r--r--sys/security/audit/audit_syscalls.c47
-rw-r--r--sys/security/mac/mac_framework.c4
-rw-r--r--sys/security/mac_bsdextended/mac_bsdextended.c4
-rw-r--r--sys/security/mac_do/mac_do.c56
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);