From 88c35241535803247bd3044187c6c3b3c7f02c79 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Wed, 18 Apr 2012 11:00:24 -0400 Subject: [PATCH] libselinux: boolean name equivalency Add support for booleans.subs file. Basically this allows us to finally change badly named booleans to some standard name. Signed-off-by: Eric Paris Acked-by: Dan Walsh --- libselinux/include/selinux/selinux.h | 1 + libselinux/src/booleans.c | 158 +++++++++++++++++++++------ libselinux/src/file_path_suffixes.h | 1 + libselinux/src/selinux_config.c | 9 +- libselinux/src/selinux_internal.h | 1 + 5 files changed, 137 insertions(+), 33 deletions(-) diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index 32020399..3487a1cd 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -507,6 +507,7 @@ extern const char *selinux_x_context_path(void); extern const char *selinux_sepgsql_context_path(void); extern const char *selinux_contexts_path(void); extern const char *selinux_securetty_types_path(void); +extern const char *selinux_booleans_subs_path(void); extern const char *selinux_booleans_path(void); extern const char *selinux_customizable_types_path(void); extern const char *selinux_users_path(void); diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c index 15100433..5998552e 100644 --- a/libselinux/src/booleans.c +++ b/libselinux/src/booleans.c @@ -5,6 +5,7 @@ * Dan Walsh - Added security_load_booleans(). */ +#include #include #include #include @@ -86,44 +87,146 @@ int security_get_boolean_names(char ***names, int *len) } hidden_def(security_get_boolean_names) + +static char *bool_sub(const char *name) +{ + char *sub = NULL; + char *line_buf = NULL; + size_t line_len; + FILE *cfg; + + if (!name) + return NULL; + + cfg = fopen(selinux_booleans_subs_path(), "r"); + if (!cfg) + goto out; + + while (getline(&line_buf, &line_len, cfg) != -1) { + char *ptr; + char *src = line_buf; + char *dst; + + while (*src && isspace(*src)) + src++; + if (!*src) + continue; + if (src[0] == '#') + continue; + + ptr = src; + while (*ptr && !isspace(*ptr)) + ptr++; + *ptr++ = '\0'; + if (strcmp(src, name) != 0) + continue; + + dst = ptr; + while (*dst && isspace(*dst)) + dst++; + if (!*dst) + continue; + ptr=dst; + while (*ptr && !isspace(*ptr)) + ptr++; + *ptr='\0'; + + sub = strdup(dst); + + break; + } + + free(line_buf); + fclose(cfg); +out: + if (!sub) + sub = strdup(name); + return sub; +} + +static int bool_open(const char *name, int flag) { + char *fname = NULL; + char *alt_name = NULL; + int len; + int fd = -1; + int ret; + char *ptr; + + if (!name) { + errno = EINVAL; + return -1; + } + + /* note the 'sizeof' gets us enough room for the '\0' */ + len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); + fname = malloc(sizeof(char) * len); + if (!fname) + return -1; + + ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); + if (ret < 0) + goto out; + assert(ret < len); + + fd = open(fname, flag); + if (fd >= 0 || errno != ENOENT) + goto out; + + alt_name = bool_sub(name); + if (!alt_name) + goto out; + + /* note the 'sizeof' gets us enough room for the '\0' */ + len = strlen(alt_name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); + ptr = realloc(fname, len); + if (!ptr) + goto out; + fname = ptr; + + ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); + if (ret < 0) + goto out; + assert(ret < len); + + fd = open(fname, flag); +out: + free(fname); + free(alt_name); + + return fd; +} + #define STRBUF_SIZE 3 static int get_bool_value(const char *name, char **buf) { int fd, len; - char *fname = NULL; + int errno_tmp; if (!selinux_mnt) { errno = ENOENT; return -1; } - *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1)); + *buf = malloc(sizeof(char) * (STRBUF_SIZE + 1)); if (!*buf) - goto out; + return -1; + (*buf)[STRBUF_SIZE] = 0; - len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); - fname = (char *)malloc(sizeof(char) * len); - if (!fname) - goto out; - snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); - - fd = open(fname, O_RDONLY); + fd = bool_open(name, O_RDONLY); if (fd < 0) - goto out; + goto out_err; len = read(fd, *buf, STRBUF_SIZE); + errno_tmp = errno; close(fd); + errno = errno_tmp; if (len != STRBUF_SIZE) - goto out; + goto out_err; - free(fname); return 0; - out: - if (*buf) - free(*buf); - if (fname) - free(fname); +out_err: + free(*buf); return -1; } @@ -164,8 +267,8 @@ hidden_def(security_get_boolean_active) int security_set_boolean(const char *name, int value) { - int fd, ret, len; - char buf[2], *fname; + int fd, ret; + char buf[2]; if (!selinux_mnt) { errno = ENOENT; @@ -176,17 +279,9 @@ int security_set_boolean(const char *name, int value) return -1; } - len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); - fname = (char *)malloc(sizeof(char) * len); - if (!fname) + fd = bool_open(name, O_WRONLY); + if (fd < 0) return -1; - snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); - - fd = open(fname, O_WRONLY); - if (fd < 0) { - ret = -1; - goto out; - } if (value) buf[0] = '1'; @@ -196,8 +291,7 @@ int security_set_boolean(const char *name, int value) ret = write(fd, buf, 2); close(fd); - out: - free(fname); + if (ret > 0) return 0; else diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h index fe9aadac..825f295a 100644 --- a/libselinux/src/file_path_suffixes.h +++ b/libselinux/src/file_path_suffixes.h @@ -26,3 +26,4 @@ S_(BINPOLICY, "/policy/policy") S_(FILE_CONTEXT_SUBS, "/contexts/files/file_contexts.subs") S_(FILE_CONTEXT_SUBS_DIST, "/contexts/files/file_contexts.subs_dist") S_(SEPGSQL_CONTEXTS, "/contexts/sepgsql_contexts") + S_(BOOLEAN_SUBS, "/booleans.subs") diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c index a9d0ce00..296f357b 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -47,7 +47,8 @@ #define SEPGSQL_CONTEXTS 24 #define FILE_CONTEXT_SUBS_DIST 25 #define LXC_CONTEXTS 26 -#define NEL 27 +#define BOOLEAN_SUBS 27 +#define NEL 28 /* Part of one-time lazy init */ static pthread_once_t once = PTHREAD_ONCE_INIT; @@ -426,6 +427,12 @@ const char *selinux_lxc_contexts_path(void) hidden_def(selinux_lxc_contexts_path) +const char * selinux_booleans_subs_path(void) { + return get_path(BOOLEAN_SUBS); +} + +hidden_def(selinux_booleans_subs_path) + const char * selinux_file_context_subs_path(void) { return get_path(FILE_CONTEXT_SUBS); } diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index ab80dba6..c89a1303 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy) hidden_proto(security_setenforce) hidden_proto(security_deny_unknown) hidden_proto(selinux_binary_policy_path) + hidden_proto(selinux_booleans_subs_path) hidden_proto(selinux_default_context_path) hidden_proto(selinux_securetty_types_path) hidden_proto(selinux_failsafe_context_path)