aboutsummaryrefslogtreecommitdiff
path: root/sys/security
diff options
context:
space:
mode:
Diffstat (limited to 'sys/security')
-rw-r--r--sys/security/audit/audit_syscalls.c47
-rw-r--r--sys/security/mac_bsdextended/mac_bsdextended.c4
-rw-r--r--sys/security/mac_do/mac_do.c56
3 files changed, 62 insertions, 45 deletions
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_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);