Page MenuHomeFreeBSD

D47598.diff
No OneTemporary

D47598.diff

diff --git a/sys/security/mac_do/mac_do.c b/sys/security/mac_do/mac_do.c
--- a/sys/security/mac_do/mac_do.c
+++ b/sys/security/mac_do/mac_do.c
@@ -58,18 +58,30 @@
TAILQ_HEAD(rulehead, rule) head;
};
-static struct rules rules0;
+static struct rules *rules0;
static void
-toast_rules(struct rulehead *head)
+toast_rules(struct rules *const rules)
{
- struct rule *r;
+ struct rulehead *const head = &rules->head;
+ struct rule *rule;
- while ((r = TAILQ_FIRST(head)) != NULL) {
- TAILQ_REMOVE(head, r, r_entries);
- free(r, M_DO);
+ while ((rule = TAILQ_FIRST(head)) != NULL) {
+ TAILQ_REMOVE(head, rule, r_entries);
+ free(rule, M_DO);
}
- TAILQ_INIT(head);
+ free(rules, M_DO);
+}
+
+static struct rules *
+alloc_rules(void)
+{
+ struct rules *const rules = malloc(sizeof(*rules), M_DO, M_WAITOK);
+
+ _Static_assert(MAC_RULE_STRING_LEN > 0, "MAC_RULE_STRING_LEN <= 0!");
+ rules->string[0] = 0;
+ TAILQ_INIT(&rules->head);
+ return (rules);
}
static int
@@ -133,30 +145,32 @@
/*
* Parse rules specification and produce rule structures out of it.
*
- * 'head' must be an empty list head. Returns 0 on success, with 'head' filled
- * with structures representing the rules. On error, 'head' is left empty and
- * the returned value is non-zero. If 'string' has length greater or equal to
+ * Returns 0 on success, with '*rulesp' made to point to a 'struct rule'
+ * representing the rules. On error, the returned value is non-zero and
+ * '*rulesp' is unchanged. If 'string' has length greater or equal to
* MAC_RULE_STRING_LEN, ENAMETOOLONG is returned. If it is not in the expected
* format (comma-separated list of clauses of the form "<type>=<val>:<target>",
* where <type> is "uid" or "gid", <val> an UID or GID (depending on <type>) and
* <target> is "*", "any" or some UID), EINVAL is returned.
*/
static int
-parse_rules(const char *const string, struct rulehead *const head)
+parse_rules(const char *const string, struct rules **const rulesp)
{
const size_t len = strlen(string);
char *copy;
char *p;
char *element;
+ struct rules *rules;
struct rule *new;
int error = 0;
- QMD_TAILQ_CHECK_TAIL(head, r_entries);
- MPASS(TAILQ_EMPTY(head));
-
if (len >= MAC_RULE_STRING_LEN)
return (ENAMETOOLONG);
+ rules = alloc_rules();
+ bcopy(string, rules->string, len + 1);
+ MPASS(rules->string[len] == '\0'); /* Catch some races. */
+
copy = malloc(len + 1, M_DO, M_WAITOK);
bcopy(string, copy, len + 1);
MPASS(copy[len] == '\0'); /* Catch some races. */
@@ -167,11 +181,13 @@
continue;
error = parse_rule_element(element, &new);
if (error != 0) {
- toast_rules(head);
+ toast_rules(rules);
goto out;
}
- TAILQ_INSERT_TAIL(head, new, r_entries);
+ TAILQ_INSERT_TAIL(&rules->head, new, r_entries);
}
+
+ *rulesp = rules;
out:
free(copy, M_DO);
return (error);
@@ -194,7 +210,7 @@
for (cpr = pr;; cpr = cpr->pr_parent) {
prison_lock(cpr);
if (cpr == &prison0) {
- rules = &rules0;
+ rules = rules0;
break;
}
rules = osd_jail_get(cpr, mac_do_osd_jail_slot);
@@ -207,53 +223,6 @@
return (rules);
}
-/*
- * Ensure the passed prison has its own 'struct rules'.
- *
- * On entry, the prison must be unlocked, but will be returned locked. Returns
- * the newly allocated and initialized 'struct rules', or the existing one.
- */
-static struct rules *
-ensure_rules(struct prison *const pr)
-{
- struct rules *rules, *new_rules;
- void **rsv;
-
- if (pr == &prison0) {
- prison_lock(pr);
- return (&rules0);
- }
-
- /* Optimistically try to avoid memory allocations. */
-restart:
- prison_lock(pr);
- rules = osd_jail_get(pr, mac_do_osd_jail_slot);
- if (rules != NULL)
- return (rules);
- prison_unlock(pr);
-
- new_rules = malloc(sizeof(*new_rules), M_DO, M_WAITOK|M_ZERO);
- TAILQ_INIT(&new_rules->head);
- rsv = osd_reserve(mac_do_osd_jail_slot);
- prison_lock(pr);
- rules = osd_jail_get(pr, mac_do_osd_jail_slot);
- if (rules != NULL) {
- /*
- * We could cleanup while holding the prison lock (given the
- * current implementation of osd_free_reserved()), but be safe
- * and a good citizen by not keeping it more than strictly
- * necessary. The only consequence is that we have to relookup
- * the rules.
- */
- prison_unlock(pr);
- osd_free_reserved(rsv);
- free(new_rules, M_DO);
- goto restart;
- }
- osd_jail_set_reserved(pr, mac_do_osd_jail_slot, rsv, new_rules);
- return (new_rules);
-}
-
/*
* OSD destructor for slot 'mac_do_osd_jail_slot'.
*
@@ -264,17 +233,19 @@
{
struct rules *const rules = value;
- toast_rules(&rules->head);
- free(rules, M_DO);
+ toast_rules(rules);
}
/*
- * Deallocate the rules associated to a prison.
+ * Remove the rules specifically associated to a prison.
+ *
+ * In practice, this means that the rules become inherited (from the closest
+ * ascendant that has some).
*
* Destroys the 'mac_do_osd_jail_slot' slot of the passed jail.
*/
static void
-dealloc_rules(struct prison *const pr)
+remove_rules(struct prison *const pr)
{
prison_lock(pr);
/* This calls destructor dealloc_osd(). */
@@ -283,25 +254,38 @@
}
/*
- * Assign already parsed rules to a jail.
+ * Assign already built rules to a jail.
*/
static void
-set_rules(struct prison *const pr, const char *const rules_string,
- struct rulehead *const head)
+set_rules(struct prison *const pr, struct rules *const rules)
{
- struct rules *rules;
- struct rulehead old_head;
+ struct rules *old_rules;
+ void **rsv;
- MPASS(rules_string != NULL);
- MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN);
+ rsv = osd_reserve(mac_do_osd_jail_slot);
- TAILQ_INIT(&old_head);
- rules = ensure_rules(pr);
- strlcpy(rules->string, rules_string, MAC_RULE_STRING_LEN);
- TAILQ_CONCAT(&old_head, &rules->head, r_entries);
- TAILQ_CONCAT(&rules->head, head, r_entries);
+ prison_lock(pr);
+ if (pr == &prison0) {
+ old_rules = rules0;
+ rules0 = rules;
+ } else {
+ old_rules = osd_jail_get(pr, mac_do_osd_jail_slot);
+ osd_jail_set_reserved(pr, mac_do_osd_jail_slot, rsv, rules);
+ }
prison_unlock(pr);
- toast_rules(&old_head);
+ if (old_rules != NULL)
+ toast_rules(old_rules);
+}
+
+/*
+ * Assigns empty rules to a jail.
+ */
+static void
+set_empty_rules(struct prison *const pr)
+{
+ struct rules *const rules = alloc_rules();
+
+ set_rules(pr, rules);
}
/*
@@ -312,13 +296,13 @@
static int
parse_and_set_rules(struct prison *const pr, const char *rules_string)
{
- struct rulehead head;
+ struct rules *rules;
int error;
- error = parse_rules(rules_string, &head);
+ error = parse_rules(rules_string, &rules);
if (error != 0)
return (error);
- set_rules(pr, rules_string, &head);
+ set_rules(pr, rules);
return (0);
}
@@ -361,7 +345,7 @@
destroy(struct mac_policy_conf *mpc)
{
osd_jail_deregister(mac_do_osd_jail_slot);
- toast_rules(&rules0.head);
+ toast_rules(rules0);
}
static int
@@ -382,7 +366,7 @@
jsys = JAIL_SYS_NEW;
switch (jsys) {
case JAIL_SYS_INHERIT:
- dealloc_rules(pr);
+ remove_rules(pr);
error = 0;
break;
case JAIL_SYS_NEW:
@@ -422,8 +406,7 @@
{
struct prison *const pr = obj;
- (void)ensure_rules(pr);
- prison_unlock(pr);
+ set_empty_rules(pr);
return (0);
}
@@ -431,12 +414,8 @@
mac_do_prison_remove(void *obj, void *data __unused)
{
struct prison *pr = obj;
- struct rules *r;
- prison_lock(pr);
- r = osd_jail_get(pr, mac_do_osd_jail_slot);
- prison_unlock(pr);
- toast_rules(&r->head);
+ remove_rules(pr);
return (0);
}
@@ -481,12 +460,10 @@
struct prison *pr;
mac_do_osd_jail_slot = osd_jail_register(dealloc_osd, methods);
- TAILQ_INIT(&rules0.head);
+ rules0 = alloc_rules();
sx_slock(&allprison_lock);
- TAILQ_FOREACH(pr, &allprison, pr_list) {
- (void)ensure_rules(pr);
- prison_unlock(pr);
- }
+ TAILQ_FOREACH(pr, &allprison, pr_list)
+ set_empty_rules(pr);
sx_sunlock(&allprison_lock);
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 17, 5:42 AM (22 h, 21 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14661802
Default Alt Text
D47598.diff (7 KB)

Event Timeline