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
This commit is contained in:
parent
83e7e80417
commit
892d4bfa16
@ -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 @@ parse_rules(char *string, struct rulehead *head)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user