summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/libc/posix1e/mac.c278
1 files changed, 192 insertions, 86 deletions
diff --git a/lib/libc/posix1e/mac.c b/lib/libc/posix1e/mac.c
index 3c08e47..3426ac3 100644
--- a/lib/libc/posix1e/mac.c
+++ b/lib/libc/posix1e/mac.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
- * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
* All rights reserved.
*
* This software was developed by Robert Watson for the TrustedBSD Project.
@@ -49,28 +49,29 @@
static int internal_initialized;
-/* Default sets of labels for various query operations. */
-static char *default_file_labels;
-static char *default_ifnet_labels;
-static char *default_process_labels;
+/*
+ * Maintain a list of default label preparations for various object
+ * types. Each name will appear only once in the list.
+ *
+ * XXXMAC: Not thread-safe.
+ */
+LIST_HEAD(, label_default) label_default_head;
+struct label_default {
+ char *ld_name;
+ char *ld_labels;
+ LIST_ENTRY(label_default) ld_entries;
+};
static void
mac_destroy_labels(void)
{
+ struct label_default *ld;
- if (default_file_labels != NULL) {
- free(default_file_labels);
- default_file_labels = NULL;
- }
-
- if (default_ifnet_labels != NULL) {
- free(default_ifnet_labels);
- default_ifnet_labels = NULL;
- }
-
- if (default_process_labels != NULL) {
- free(default_process_labels);
- default_process_labels = NULL;
+ while ((ld = LIST_FIRST(&label_default_head))) {
+ free(ld->ld_name);
+ free(ld->ld_labels);
+ LIST_REMOVE(ld, ld_entries);
+ free(ld);
}
}
@@ -84,88 +85,175 @@ mac_destroy_internal(void)
}
static int
-mac_init_internal(void)
+mac_add_type(const char *name, const char *labels)
{
- FILE *file;
+ struct label_default *ld, *ld_new;
+ char *name_dup, *labels_dup;
+
+ /*
+ * Speculatively allocate all the memory now to avoid allocating
+ * later when we will someday hold a mutex.
+ */
+ name_dup = strdup(name);
+ if (name_dup == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ labels_dup = strdup(labels);
+ if (labels_dup == NULL) {
+ free(name_dup);
+ errno = ENOMEM;
+ return (-1);
+ }
+ ld_new = malloc(sizeof(*ld));
+ if (ld_new == NULL) {
+ free(name_dup);
+ free(labels_dup);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /*
+ * If the type is already present, replace the current entry
+ * rather than add a new instance.
+ */
+ for (ld = LIST_FIRST(&label_default_head); ld != NULL;
+ ld = LIST_NEXT(ld, ld_entries)) {
+ if (strcmp(name, ld->ld_name) == 0)
+ break;
+ }
+
+ if (ld != NULL) {
+ free(ld->ld_labels);
+ ld->ld_labels = labels_dup;
+ labels_dup = NULL;
+ } else {
+ ld = ld_new;
+ ld->ld_name = name_dup;
+ ld->ld_labels = labels_dup;
+
+ ld_new = NULL;
+ name_dup = NULL;
+ labels_dup = NULL;
+
+ LIST_INSERT_HEAD(&label_default_head, ld, ld_entries);
+ }
+
+ if (name_dup != NULL)
+ free(name_dup);
+ if (labels_dup != NULL)
+ free(labels_dup);
+ if (ld_new != NULL)
+ free(ld_new);
+
+ return (0);
+}
+
+static char *
+next_token(char **string)
+{
+ char *token;
+
+ token = strsep(string, " \t");
+ while (token != NULL && *token == '\0')
+ token = strsep(string, " \t");
+
+ return (token);
+}
+
+static int
+mac_init_internal(int ignore_errors)
+{
+ const char *filename;
char line[LINE_MAX];
+ FILE *file;
int error;
error = 0;
- file = fopen(MAC_CONFFILE, "r");
+ LIST_INIT(&label_default_head);
+
+ if (!issetugid() && getenv("MAC_CONFFILE") != NULL)
+ filename = getenv("MAC_CONFFILE");
+ else
+ filename = MAC_CONFFILE;
+ file = fopen(filename, "r");
if (file == NULL)
return (0);
while (fgets(line, LINE_MAX, file)) {
- char *arg, *parse, *statement;
+ char *arg, *comment, *parse, *statement;
if (line[strlen(line)-1] == '\n')
line[strlen(line)-1] = '\0';
else {
+ if (ignore_errors)
+ continue;
fclose(file);
error = EINVAL;
goto just_return;
}
- parse = line;
- statement = "";
- while (parse && statement[0] == '\0')
- statement = strsep(&parse, " \t");
-
- /* Blank lines ok. */
- if (strlen(statement) == 0)
- continue;
+ /* Remove any comment. */
+ comment = line;
+ parse = strsep(&comment, "#");
- /* Lines that consist only of comments ok. */
- if (statement[0] == '#')
+ /* Blank lines OK. */
+ statement = next_token(&parse);
+ if (statement == NULL)
continue;
- if (strcmp(statement, "default_file_labels") == 0) {
- if (default_file_labels != NULL) {
- free(default_file_labels);
- default_file_labels = NULL;
+ if (strcmp(statement, "default_labels") == 0) {
+ char *name, *labels;
+
+ name = next_token(&parse);
+ labels = next_token(&parse);
+ if (name == NULL || labels == NULL ||
+ next_token(&parse) != NULL) {
+ if (ignore_errors)
+ continue;
+ error = EINVAL;
+ fclose(file);
+ goto just_return;
}
- arg = strsep(&parse, "# \t");
- if (arg != NULL && arg[0] != '\0') {
- default_file_labels = strdup(arg);
- if (default_file_labels == NULL) {
- error = ENOMEM;
- fclose(file);
- goto just_return;
- }
+ if (mac_add_type(name, labels) == -1) {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ goto just_return;
}
- } else if (strcmp(statement, "default_ifnet_labels") == 0) {
- if (default_ifnet_labels != NULL) {
- free(default_ifnet_labels);
- default_ifnet_labels = NULL;
+ } else if (strcmp(statement, "default_ifnet_labels") == 0 ||
+ strcmp(statement, "default_file_labels") == 0 ||
+ strcmp(statement, "default_process_labels") == 0) {
+ char *labels, *type;
+
+ if (strcmp(statement, "default_ifnet_labels") == 0)
+ type = "ifnet";
+ else if (strcmp(statement, "default_file_labels") == 0)
+ type = "file";
+ else if (strcmp(statement, "default_process_labels") ==
+ 0)
+ type = "process";
+
+ labels = next_token(&parse);
+ if (labels == NULL || next_token(&parse) != NULL) {
+ if (ignore_errors)
+ continue;
+ error = EINVAL;
+ fclose(file);
+ goto just_return;
}
- arg = strsep(&parse, "# \t");
- if (arg != NULL && arg[0] != '\0') {
- default_ifnet_labels = strdup(arg);
- if (default_ifnet_labels == NULL) {
- error = ENOMEM;
- fclose(file);
- goto just_return;
- }
- }
- } else if (strcmp(statement, "default_process_labels") == 0) {
- if (default_process_labels != NULL) {
- free(default_process_labels);
- default_process_labels = NULL;
- }
-
- arg = strsep(&parse, "# \t");
- if (arg != NULL && arg[0] != '\0') {
- default_process_labels = strdup(arg);
- if (default_process_labels == NULL) {
- error = ENOMEM;
- fclose(file);
- goto just_return;
- }
+ if (mac_add_type(type, labels) == -1) {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ goto just_return;
}
} else {
+ if (ignore_errors)
+ continue;
fclose(file);
error = EINVAL;
goto just_return;
@@ -187,7 +275,7 @@ mac_maybe_init_internal(void)
{
if (!internal_initialized)
- return (mac_init_internal());
+ return (mac_init_internal(1));
else
return (0);
}
@@ -198,7 +286,7 @@ mac_reload(void)
if (internal_initialized)
mac_destroy_internal();
- return (mac_init_internal());
+ return (mac_init_internal(0));
}
int
@@ -267,7 +355,21 @@ mac_prepare(struct mac **mac, char *elements)
}
int
-mac_prepare_file_label(struct mac **mac)
+mac_prepare_type(struct mac **mac, const char *name)
+{
+ struct label_default *ld;
+
+ for (ld = LIST_FIRST(&label_default_head); ld != NULL;
+ ld = LIST_NEXT(ld, ld_entries)) {
+ if (strcmp(name, ld->ld_name) == 0)
+ return (mac_prepare(mac, ld->ld_labels));
+ }
+
+ return (ENOENT); /* XXXMAC: ENOLABEL */
+}
+
+int
+mac_prepare_ifnet_label(struct mac **mac)
{
int error;
@@ -275,14 +377,11 @@ mac_prepare_file_label(struct mac **mac)
if (error != 0)
return (error);
- if (default_file_labels == NULL)
- return (mac_prepare(mac, ""));
-
- return (mac_prepare(mac, default_file_labels));
+ return (mac_prepare_type(mac, "ifnet"));
}
int
-mac_prepare_ifnet_label(struct mac **mac)
+mac_prepare_file_label(struct mac **mac)
{
int error;
@@ -290,11 +389,21 @@ mac_prepare_ifnet_label(struct mac **mac)
if (error != 0)
return (error);
- if (default_ifnet_labels == NULL)
- return (mac_prepare(mac, ""));
+ return (mac_prepare_type(mac, "file"));
+}
- return (mac_prepare(mac, default_ifnet_labels));
+int
+mac_prepare_packet_label(struct mac **mac)
+{
+ int error;
+
+ error = mac_maybe_init_internal();
+ if (error != 0)
+ return (error);
+
+ return (mac_prepare_type(mac, "packet"));
}
+
int
mac_prepare_process_label(struct mac **mac)
{
@@ -304,10 +413,7 @@ mac_prepare_process_label(struct mac **mac)
if (error != 0)
return (error);
- if (default_process_labels == NULL)
- return (mac_prepare(mac, ""));
-
- return (mac_prepare(mac, default_process_labels));
+ return (mac_prepare_type(mac, "process"));
}
/*
OpenPOWER on IntegriCloud