Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144510084
D47597.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D47597.diff
View Options
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
@@ -69,6 +69,7 @@
TAILQ_REMOVE(head, r, r_entries);
free(r, M_DO);
}
+ TAILQ_INIT(head);
}
static int
@@ -129,15 +130,38 @@
return (error);
}
+/*
+ * 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
+ * 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)
{
- struct rule *new;
- char *const copy = strdup(string, M_DO);
- char *p = copy;
+ const size_t len = strlen(string);
+ char *copy;
+ char *p;
char *element;
+ 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);
+
+ copy = malloc(len + 1, M_DO, M_WAITOK);
+ bcopy(string, copy, len + 1);
+ MPASS(copy[len] == '\0'); /* Catch some races. */
+
+ p = copy;
while ((element = strsep(&p, ",")) != NULL) {
if (element[0] == '\0')
continue;
@@ -183,11 +207,125 @@
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'.
+ *
+ * Called with 'value' not NULL.
+ */
+static void
+dealloc_osd(void *const value)
+{
+ struct rules *const rules = value;
+
+ toast_rules(&rules->head);
+ free(rules, M_DO);
+}
+
+/*
+ * Deallocate the rules associated to a prison.
+ *
+ * Destroys the 'mac_do_osd_jail_slot' slot of the passed jail.
+ */
+static void
+dealloc_rules(struct prison *const pr)
+{
+ prison_lock(pr);
+ /* This calls destructor dealloc_osd(). */
+ osd_jail_del(pr, mac_do_osd_jail_slot);
+ prison_unlock(pr);
+}
+
+/*
+ * Assign already parsed rules to a jail.
+ */
+static void
+set_rules(struct prison *const pr, const char *const rules_string,
+ struct rulehead *const head)
+{
+ struct rules *rules;
+ struct rulehead old_head;
+
+ MPASS(rules_string != NULL);
+ MPASS(strlen(rules_string) < MAC_RULE_STRING_LEN);
+
+ 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_unlock(pr);
+ toast_rules(&old_head);
+}
+
+/*
+ * Parse a rules specification and assign them to a jail.
+ *
+ * Returns the same error code as parse_rules() (which see).
+ */
+static int
+parse_and_set_rules(struct prison *const pr, const char *rules_string)
+{
+ struct rulehead head;
+ int error;
+
+ error = parse_rules(rules_string, &head);
+ if (error != 0)
+ return (error);
+ set_rules(pr, rules_string, &head);
+ return (0);
+}
+
static int
sysctl_rules(SYSCTL_HANDLER_ARGS)
{
char *new_string;
- struct rulehead head, saved_head;
struct prison *pr;
struct rules *rules;
int error;
@@ -207,17 +345,7 @@
if (error)
goto out;
- TAILQ_INIT(&head);
- error = parse_rules(new_string, &head);
- if (error)
- goto out;
- TAILQ_INIT(&saved_head);
- prison_lock(pr);
- TAILQ_CONCAT(&saved_head, &rules->head, r_entries);
- TAILQ_CONCAT(&rules->head, &head, r_entries);
- strlcpy(rules->string, new_string, MAC_RULE_STRING_LEN);
- prison_unlock(pr);
- toast_rules(&saved_head);
+ error = parse_and_set_rules(pr, new_string);
out:
free(new_string, M_DO);
@@ -236,51 +364,11 @@
toast_rules(&rules0.head);
}
-static void
-mac_do_alloc_prison(struct prison *pr, struct rules **lrp)
-{
- struct prison *ppr;
- struct rules *rules, *new_rules;
- void **rsv;
-
- rules = find_rules(pr, &ppr);
- if (ppr == pr)
- goto done;
-
- prison_unlock(ppr);
- new_rules = malloc(sizeof(*new_rules), M_PRISON, M_WAITOK|M_ZERO);
- rsv = osd_reserve(mac_do_osd_jail_slot);
- rules = find_rules(pr, &ppr);
- if (ppr == pr) {
- free(new_rules, M_PRISON);
- osd_free_reserved(rsv);
- goto done;
- }
- prison_lock(pr);
- osd_jail_set_reserved(pr, mac_do_osd_jail_slot, rsv, new_rules);
- TAILQ_INIT(&new_rules->head);
-done:
- if (lrp != NULL)
- *lrp = rules;
- prison_unlock(pr);
- prison_unlock(ppr);
-}
-
-static void
-mac_do_dealloc_prison(void *data)
-{
- struct rules *r = data;
-
- toast_rules(&r->head);
-}
-
static int
mac_do_prison_set(void *obj, void *data)
{
struct prison *pr = obj;
struct vfsoptlist *opts = data;
- struct rulehead head, saved_head;
- struct rules *rules;
char *rules_string;
int error, jsys, len;
@@ -289,33 +377,19 @@
jsys = -1;
error = vfs_getopt(opts, "mdo.rules", (void **)&rules_string, &len);
if (error == ENOENT)
- rules = NULL;
+ rules_string = "";
else
jsys = JAIL_SYS_NEW;
switch (jsys) {
case JAIL_SYS_INHERIT:
- prison_lock(pr);
- osd_jail_del(pr, mac_do_osd_jail_slot);
- prison_unlock(pr);
+ dealloc_rules(pr);
+ error = 0;
break;
case JAIL_SYS_NEW:
- mac_do_alloc_prison(pr, &rules);
- if (rules_string == NULL)
- break;
- TAILQ_INIT(&head);
- error = parse_rules(rules_string, &head);
- if (error)
- return (1);
- TAILQ_INIT(&saved_head);
- prison_lock(pr);
- TAILQ_CONCAT(&saved_head, &rules->head, r_entries);
- TAILQ_CONCAT(&rules->head, &head, r_entries);
- strlcpy(rules->string, rules_string, MAC_RULE_STRING_LEN);
- prison_unlock(pr);
- toast_rules(&saved_head);
+ error = parse_and_set_rules(pr, rules_string);
break;
}
- return (0);
+ return (error);
}
SYSCTL_JAIL_PARAM_SYS_NODE(mdo, CTLFLAG_RW, "Jail MAC/do parameters");
@@ -346,9 +420,10 @@
static int
mac_do_prison_create(void *obj, void *data __unused)
{
- struct prison *pr = obj;
+ struct prison *const pr = obj;
- mac_do_alloc_prison(pr, NULL);
+ (void)ensure_rules(pr);
+ prison_unlock(pr);
return (0);
}
@@ -405,11 +480,13 @@
};
struct prison *pr;
- mac_do_osd_jail_slot = osd_jail_register(mac_do_dealloc_prison, methods);
+ mac_do_osd_jail_slot = osd_jail_register(dealloc_osd, methods);
TAILQ_INIT(&rules0.head);
sx_slock(&allprison_lock);
- TAILQ_FOREACH(pr, &allprison, pr_list)
- mac_do_alloc_prison(pr, NULL);
+ TAILQ_FOREACH(pr, &allprison, pr_list) {
+ (void)ensure_rules(pr);
+ prison_unlock(pr);
+ }
sx_sunlock(&allprison_lock);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Feb 10, 12:26 AM (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28531971
Default Alt Text
D47597.diff (7 KB)
Attached To
Mode
D47597: MAC/do: Factor out setting/destroying rule structures
Attached
Detach File
Event Timeline
Log In to Comment