diff options
author | rwatson <rwatson@FreeBSD.org> | 2004-12-06 19:43:45 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2004-12-06 19:43:45 +0000 |
commit | 892d4bfa16f4e9d3a0694b822687fe4b7caef873 (patch) | |
tree | 8374e7eb74870c02b47fadcc940d9a26b61d48fb | |
parent | 83e7e80417809f4f9600e08a588bc1de7f5128b2 (diff) | |
download | FreeBSD-src-892d4bfa16f4e9d3a0694b822687fe4b7caef873.zip FreeBSD-src-892d4bfa16f4e9d3a0694b822687fe4b7caef873.tar.gz |
Switch from using an sx lock to a mutex for the mac_portacl rule chain:
the sx lock was used previously because we might sleep allocating
additional memory by using auto-extending sbufs. However, we no longer
do this, instead retaining the user-submitted rule string, so mutexes
can be used instead. Annotate the reason for not using the sbuf-related
rule-to-string code with a comment.
Switch to using TAILQ_CONCAT() instead of manual list copying, as it's
O(1), reducing the rule replacement step under the mutex from O(2N) to
O(2).
Remove now uneeded vnode-related includes.
MFC after: 2 weeks
-rw-r--r-- | sys/security/mac_portacl/mac_portacl.c | 45 |
1 files changed, 19 insertions, 26 deletions
diff --git a/sys/security/mac_portacl/mac_portacl.c b/sys/security/mac_portacl/mac_portacl.c index 7524155..c7551bb 100644 --- a/sys/security/mac_portacl/mac_portacl.c +++ b/sys/security/mac_portacl/mac_portacl.c @@ -61,21 +61,21 @@ #include <sys/domain.h> #include <sys/kernel.h> #include <sys/libkern.h> +#include <sys/lock.h> #include <sys/mac.h> #include <sys/malloc.h> #include <sys/mount.h> +#include <sys/mutex.h> #include <sys/proc.h> #include <sys/protosw.h> #include <sys/queue.h> #include <sys/systm.h> #include <sys/sysproto.h> #include <sys/sysent.h> -#include <sys/vnode.h> #include <sys/file.h> #include <sys/sbuf.h> #include <sys/socket.h> #include <sys/socketvar.h> -#include <sys/sx.h> #include <sys/sysctl.h> #include <netinet/in.h> @@ -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); |