diff --git a/sys/security/mac_portacl/mac_portacl.c b/sys/security/mac_portacl/mac_portacl.c index 7524155d48a..c7551bb6a5f 100644 --- a/sys/security/mac_portacl/mac_portacl.c +++ b/sys/security/mac_portacl/mac_portacl.c @@ -61,21 +61,21 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include #include -#include #include #include #include #include -#include #include #include @@ -134,7 +134,7 @@ struct rule { * for the specified binding. */ -static struct sx rule_sx; +static struct mtx rule_mtx; static TAILQ_HEAD(rulehead, rule) rule_head; static char rule_string[MAC_RULE_STRING_LEN]; @@ -157,7 +157,7 @@ static void destroy(struct mac_policy_conf *mpc) { - sx_destroy(&rule_sx); + mtx_destroy(&rule_mtx); toast_rules(&rule_head); } @@ -165,7 +165,7 @@ static void init(struct mac_policy_conf *mpc) { - sx_init(&rule_sx, "rule_sx"); + mtx_init(&rule_mtx, "rule_mtx", NULL, MTX_DEF); TAILQ_INIT(&rule_head); } @@ -260,6 +260,12 @@ out: return (error); } +/* + * rule_printf() and rules_to_string() are unused currently because they rely + * on sbufs with auto-extension, which may sleep while holding a mutex. + * Instead, the non-canonical user-generated rule string is returned to the + * user when the rules are queried, which is faster anyway. + */ #if 0 static void rule_printf(struct sbuf *sb, struct rule *rule) @@ -302,7 +308,7 @@ rules_to_string(void) sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND); needcomma = 0; - sx_slock(&rule_sx); + mtx_lock(&rule_mtx); for (rule = TAILQ_FIRST(&rule_head); rule != NULL; rule = TAILQ_NEXT(rule, r_entries)) { if (!needcomma) @@ -311,7 +317,7 @@ rules_to_string(void) sbuf_printf(sb, ","); rule_printf(sb, rule); } - sx_sunlock(&rule_sx); + mtx_unlock(&rule_mtx); sbuf_finish(sb); temp = strdup(sbuf_data(sb), M_PORTACL); sbuf_delete(sb); @@ -328,7 +334,6 @@ sysctl_rules(SYSCTL_HANDLER_ARGS) { char *string, *copy_string, *new_string; struct rulehead head, save_head; - struct rule *rule; int error; new_string = NULL; @@ -353,23 +358,11 @@ sysctl_rules(SYSCTL_HANDLER_ARGS) goto out; TAILQ_INIT(&save_head); - sx_xlock(&rule_sx); - /* - * XXX: Unfortunately, TAILQ doesn't yet have a supported - * assignment operator to copy one queue to another, due - * to a self-referential pointer in the tailq header. - * For now, do it the old-fashioned way. - */ - while ((rule = TAILQ_FIRST(&rule_head)) != NULL) { - TAILQ_REMOVE(&rule_head, rule, r_entries); - TAILQ_INSERT_HEAD(&save_head, rule, r_entries); - } - while ((rule = TAILQ_FIRST(&head)) != NULL) { - TAILQ_REMOVE(&head, rule, r_entries); - TAILQ_INSERT_HEAD(&rule_head, rule, r_entries); - } + mtx_lock(&rule_mtx); + TAILQ_CONCAT(&save_head, &rule_head, r_entries); + TAILQ_CONCAT(&rule_head, &head, r_entries); strcpy(rule_string, string); - sx_xunlock(&rule_sx); + mtx_unlock(&rule_mtx); toast_rules(&save_head); } out: @@ -396,7 +389,7 @@ rules_check(struct ucred *cred, int family, int type, u_int16_t port) return (0); error = EPERM; - sx_slock(&rule_sx); + mtx_lock(&rule_mtx); for (rule = TAILQ_FIRST(&rule_head); rule != NULL; rule = TAILQ_NEXT(rule, r_entries)) { @@ -423,7 +416,7 @@ rules_check(struct ucred *cred, int family, int type, u_int16_t port) panic("rules_check: unknown rule type %d", rule->r_idtype); } - sx_sunlock(&rule_sx); + mtx_unlock(&rule_mtx); if (error != 0 && mac_portacl_suser_exempt != 0) error = suser_cred(cred, 0);