diff --git a/.gitignore b/.gitignore index 51678eb..ed25720 100644 --- a/.gitignore +++ b/.gitignore @@ -193,3 +193,4 @@ libselinux-2.0.96.tgz /libselinux-2.1.9.tgz /libselinux-2.1.10.tgz /libselinux-2.1.11.tgz +/libselinux-2.1.12.tgz diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 328904b..a146711 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,63 +1,8 @@ -diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h -index 8263f32..9ef10fc 100644 ---- a/libselinux/include/selinux/label.h -+++ b/libselinux/include/selinux/label.h -@@ -48,8 +48,10 @@ struct selabel_handle; - #define SELABEL_OPT_PATH 3 - /* select a subset of the search space as an optimization (file backend) */ - #define SELABEL_OPT_SUBSET 4 -+/* like subset, but an array of subsets */ -+#define SELABEL_OPT_PREFIXES 5 - /* total number of options */ --#define SELABEL_NOPT 5 -+#define SELABEL_NOPT 6 - - /* - * Label operations diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index 6f483c9..9a5509e 100644 +index 6b9089d..85b0cfc 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h -@@ -139,7 +139,10 @@ struct av_decision { - /* Structure for passing options, used by AVC and label subsystems */ - struct selinux_opt { - int type; -- const char *value; -+ union { -+ const char *value; -+ const char **values; -+ }; - }; - - /* Callback facilities */ -@@ -420,6 +423,11 @@ extern int matchpathcon_init(const char *path); - regexes that have stems that are prefixes of 'prefix'. */ - extern int matchpathcon_init_prefix(const char *path, const char *prefix); - -+/* Same as matchpathcon_init, but only load entries with -+ * regexes that have stems that are prefixes of the 'prefixes' -+ * array of entries. The last entry must be NULL. */ -+extern int matchpathcon_init_prefixes(const char *patch, const char **prefixes); -+ - /* Free the memory allocated by matchpathcon_init. */ - extern void matchpathcon_fini(void); - -@@ -473,6 +481,14 @@ extern int matchmediacon(const char *media, security_context_t * con); - extern int selinux_getenforcemode(int *enforce); - - /* -+ selinux_boolean_sub reads the /etc/selinux/TYPE/booleans.subs_dist file -+ looking for a record with boolean_name. If a record exists selinux_boolean_sub -+ returns the translated name otherwise it returns the original name. -+ The returned value needs to be freed. On failure NULL will be returned. -+ */ -+extern char *selinux_boolean_sub(const char *boolean_name); -+ -+/* - selinux_getpolicytype reads the /etc/selinux/config file and determines - what the default policy for the machine is. Calling application must - free policytype. -@@ -488,7 +504,9 @@ extern const char *selinux_policy_root(void); +@@ -496,7 +496,9 @@ extern const char *selinux_policy_root(void); /* These functions return the paths to specific files under the policy root directory. */ @@ -67,86 +12,6 @@ index 6f483c9..9a5509e 100644 extern const char *selinux_failsafe_context_path(void); extern const char *selinux_removable_context_path(void); extern const char *selinux_default_context_path(void); -@@ -502,10 +520,12 @@ extern const char *selinux_homedir_context_path(void); - extern const char *selinux_media_context_path(void); - extern const char *selinux_virtual_domain_context_path(void); - extern const char *selinux_virtual_image_context_path(void); -+extern const char *selinux_lxc_contexts_path(void); - 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/man/man3/matchpathcon.3 b/libselinux/man/man3/matchpathcon.3 -index cdbb252..b6814ed 100644 ---- a/libselinux/man/man3/matchpathcon.3 -+++ b/libselinux/man/man3/matchpathcon.3 -@@ -8,7 +8,9 @@ matchpathcon, matchpathcon_index \- get the default SELinux security context for - - .BI "int matchpathcon_init(const char *" path ");" - --.BI "int matchpathcon_init_prefix(const char *" path ", const char *" subset ");" -+.BI "int matchpathcon_init_prefix(const char *" path ", const char *" prefix ");" -+ -+.BI "int matchpathcon_init_prefixes(const char *" path ", const char **" prefixes ");" - - .BI "int matchpathcon_fini(void);" - .sp -@@ -50,6 +52,14 @@ by - .I prefix. - - .sp -+.B matchpathcon_init_prefixes -+is the same as -+.B matchpathcon_init_prefix -+but takes an array of -+.I prefixes -+instead of a single prefix. The last entry in the array must be NULL. -+ -+.sp - .B matchpathcon_fini - frees the memory allocated by a prior call to - .B matchpathcon_init. -diff --git a/libselinux/man/man3/selabel_open.3 b/libselinux/man/man3/selabel_open.3 -index 8674e37..fc5b120 100644 ---- a/libselinux/man/man3/selabel_open.3 -+++ b/libselinux/man/man3/selabel_open.3 -@@ -37,8 +37,11 @@ structures of length - .ta 4n 16n 24n - .nf - struct selinux_opt { -- int type; -- const char *value; -+ int type; -+ union { -+ const char *value; -+ const char **values; -+ }; - }; - .fi - .ta -@@ -66,6 +69,13 @@ A non-null value for this option enables context validation. By default, - is used; a custom validation function can be provided via - .BR selinux_set_callback (3). - Note that an invalid context may not be treated as an error unless it is actually encountered during a lookup operation. -+.TP -+.B SELABEL_OPT_SUBSET -+A ":" separates string of path prefixes that tell the system to only loads entries with regular expressions that could match this strings. For example "/dev:/var/run:/tmp". This option can cause the system to use less memory and work faster, but you should only use paths that begin with a prefix. -+.TP -+.B SELABEL_OPT_PATH -+A string representing an alternate path the the regular expressions. -+.sp - - .SH "BACKENDS" - -@@ -99,4 +109,3 @@ Eamon Walsh - .BR selabel_stats (3), - .BR selinux_set_callback (3), - .BR selinux (8) -- diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3 index 8ead1a4..c68ace5 100644 --- a/libselinux/man/man3/selinux_binary_policy_path.3 @@ -171,84 +36,22 @@ index 8ead1a4..c68ace5 100644 .sp selinux_default_type_path - context file mapping roles to default types. .sp -diff --git a/libselinux/man/man3/selinux_boolean_sub.3 b/libselinux/man/man3/selinux_boolean_sub.3 -new file mode 100644 -index 0000000..8d54c88 ---- /dev/null -+++ b/libselinux/man/man3/selinux_boolean_sub.3 -@@ -0,0 +1,25 @@ -+.TH "selinux_boolean_subs" "3" "11 June 2012" "dwalsh@redhat.com" "SELinux API documentation" -+.SH "NAME" -+selinux_boolean_subs -+.SH "SYNOPSIS" -+.B #include -+.sp -+.BI "char *selinux_boolean_subs(const char * " boolean_name, ");" -+.sp -+.SH "DESCRIPTION" -+.B selinux_boolean_sub -+searches the /etc/selinux/POLICYTYPE/booleans.subs_dist file -+for a maching boolean_name record. If the record exists the boolean substitution name is returned. If not -+.B selinux_boolean_sub -+returns the original boolean_name. -+ -+.SH "RETURN VALUE" -+.BR selinux_boolean_subs -+returns the -+.I boolean_name -+or the substituted name on success. The returned value must be freed with -+.BR free "(3)." -+.BR selinux_boolean_subs -+returns NULL on error. -+.SH "SEE ALSO" -+security_get_boolean_names.3 -diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index b333f07..74e53bb 100644 ---- a/libselinux/src/Makefile -+++ b/libselinux/src/Makefile -@@ -13,12 +13,10 @@ SHLIBDIR ?= $(DESTDIR)/lib - INCLUDEDIR ?= $(PREFIX)/include - PYLIBVER ?= $(shell $(PYTHON) -c 'import sys;print("python%d.%d" % sys.version_info[0:2])') - PYINC ?= $(shell pkg-config --cflags $(PYPREFIX)) --PYTHONLIBDIR ?= $(shell pkg-config --libs $(PYPREFIX)) - PYLIBDIR ?= $(LIBDIR)/$(PYLIBVER) - RUBYLIBVER ?= $(shell $(RUBY) -e 'print RUBY_VERSION.split(".")[0..1].join(".")') - RUBYPLATFORM ?= $(shell $(RUBY) -e 'print RUBY_PLATFORM') - RUBYINC ?= $(shell pkg-config --cflags ruby-$(RUBYLIBVER)) --RUBYLIBDIR ?= $(shell pkg-config --libs ruby-$(RUBYLIBVER)) - RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM) - LIBBASE=$(shell basename $(LIBDIR)) - -@@ -106,10 +104,10 @@ $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) - $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< - - $(SWIGSO): $(SWIGLOBJ) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $< -L. -lselinux -L$(LIBDIR) $(PYTHONLIBDIR) -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $< -L. -lselinux -L$(LIBDIR) - - $(SWIGRUBYSO): $(SWIGRUBYLOBJ) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux -L$(LIBDIR) -Wl,-soname,$@ -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux -L$(LIBDIR) - - $(LIBA): $(OBJS) - $(AR) rcs $@ $^ -@@ -129,7 +127,7 @@ $(AUDIT2WHYLOBJ): audit2why.c - $(CC) $(filter-out -Werror, $(CFLAGS)) $(PYINC) -fPIC -DSHARED -c -o $@ $< - - $(AUDIT2WHYSO): $(AUDIT2WHYLOBJ) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR) -Wl,-soname,$@ -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux $(LIBDIR)/libsepol.a -L$(LIBDIR) - - %.o: %.c policy.h - $(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c -index 02483a3..f7750fc 100644 +index 02483a3..89953d7 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c -@@ -214,19 +214,12 @@ static int __policy_init(const char *init_path) - PyErr_SetString( PyExc_ValueError, errormsg); +@@ -206,27 +206,12 @@ static int __policy_init(const char *init_path) return 1; } + } else { +- vers = sepol_policy_kern_vers_max(); +- if (vers < 0) { +- snprintf(errormsg, sizeof(errormsg), +- "Could not get policy version: %s\n", +- strerror(errno)); +- PyErr_SetString( PyExc_ValueError, errormsg); +- return 1; +- } - snprintf(path, PATH_MAX, "%s.%d", - selinux_binary_policy_path(), vers); - fp = fopen(path, "r"); @@ -281,406 +84,296 @@ index 802a07f..6ff83a7 100644 return rc; } -diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c -index a07aa7f..d219331 100644 ---- a/libselinux/src/avc_internal.c -+++ b/libselinux/src/avc_internal.c -@@ -53,7 +53,7 @@ int avc_setenforce = 0; - int avc_netlink_trouble = 0; - - /* netlink socket code */ --static int fd; -+static int fd = -1; - - int avc_netlink_open(int blocking) - { -@@ -69,6 +69,7 @@ int avc_netlink_open(int blocking) - fcntl(fd, F_SETFD, FD_CLOEXEC); - if (!blocking && fcntl(fd, F_SETFL, O_NONBLOCK)) { - close(fd); -+ fd = -1; - rc = -1; - goto out; - } -@@ -81,6 +82,7 @@ int avc_netlink_open(int blocking) - - if (bind(fd, (struct sockaddr *)&addr, len) < 0) { - close(fd); -+ fd = -1; - rc = -1; - goto out; - } -@@ -90,7 +92,9 @@ int avc_netlink_open(int blocking) - - void avc_netlink_close(void) - { -- close(fd); -+ if (fd >= 0) -+ close(fd); -+ fd = -1; - } - - static int avc_netlink_receive(char *buf, unsigned buflen, int blocking) -@@ -269,6 +273,7 @@ void avc_netlink_loop(void) - } - - close(fd); -+ fd = -1; - avc_netlink_trouble = 1; - avc_log(SELINUX_ERROR, - "%s: netlink thread: errors encountered, terminating\n", -diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c -index 1510043..b5e6655 100644 ---- a/libselinux/src/booleans.c -+++ b/libselinux/src/booleans.c -@@ -5,6 +5,7 @@ - * Dan Walsh - Added security_load_booleans(). +diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h +index 825f295..d11c8dc 100644 +--- a/libselinux/src/file_path_suffixes.h ++++ b/libselinux/src/file_path_suffixes.h +@@ -26,4 +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") ++ S_(BOOLEAN_SUBS, "/booleans.subs_dist") +diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c +index 02b3cd2..fad8bbd 100644 +--- a/libselinux/src/label_file.c ++++ b/libselinux/src/label_file.c +@@ -8,6 +8,7 @@ + * developed by Secure Computing Corporation. */ +#include + #include + #include + #include +@@ -16,7 +17,12 @@ + #include + #include + #include ++#include + #include ++ ++#include ++ ++#include #include #include - #include -@@ -86,44 +87,145 @@ int security_get_boolean_names(char ***names, int *len) + #include +@@ -229,6 +235,167 @@ static int process_line(struct selabel_handle *rec, + return 0; } - hidden_def(security_get_boolean_names) -+ -+char *selinux_boolean_sub(const char *name) ++static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *stat) +{ -+ char *sub = NULL; -+ char *line_buf = NULL; -+ size_t line_len; -+ FILE *cfg; ++ struct saved_data *data = (struct saved_data *)rec->data; ++ char mmap_path[PATH_MAX + 1]; ++ int mmapfd; ++ int rc, i; ++ struct stat mmap_stat; ++ char *addr; ++ size_t len; ++ int stem_map_len, *stem_map; ++ ++ uint32_t *magic; ++ uint32_t *section_len; ++ uint32_t *plen; ++ ++ rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path); ++ if (rc >= sizeof(mmap_path)) ++ return -1; + -+ if (!name) -+ return NULL; ++ mmapfd = open(mmap_path, O_RDONLY); ++ if (!mmapfd) ++ return -1; + -+ cfg = fopen(selinux_booleans_subs_path(), "r"); -+ if (!cfg) -+ goto out; ++ rc = fstat(mmapfd, &mmap_stat); ++ if (rc < 0) ++ return -1; + -+ 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; ++ /* if mmap is old, ignore it */ ++ if (mmap_stat.st_mtime < stat->st_mtime) ++ return -1; + -+ dst = ptr; -+ while (*dst && isspace(*dst)) -+ dst++; -+ if (!*dst) -+ continue; -+ ptr=dst; -+ while (*ptr && !isspace(*ptr)) -+ ptr++; -+ *ptr='\0'; ++ if (mmap_stat.st_mtime == stat->st_mtime && ++ mmap_stat.st_mtim.tv_nsec < stat->st_mtim.tv_nsec) ++ return -1; + -+ sub = strdup(dst); ++ /* ok, read it in... */ ++ len = mmap_stat.st_size; ++ len += (sysconf(_SC_PAGE_SIZE) - 1); ++ len &= ~(sysconf(_SC_PAGE_SIZE) - 1); + -+ break; ++ addr = mmap(NULL, len, PROT_READ, MAP_PRIVATE, mmapfd, 0); ++ close(mmapfd); ++ if (addr == MAP_FAILED) { ++ perror("mmap"); ++ return -1; + } -+ free(line_buf); -+ fclose(cfg); -+out: -+ if (!sub) -+ sub = strdup(name); -+ return sub; -+} + -+hidden_def(selinux_boolean_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; ++ /* check if this looks like an fcontext file */ ++ magic = (uint32_t *)addr; ++ if (*magic != SELINUX_MAGIC_COMPILED_FCONTEXT) + return -1; -+ } ++ addr += sizeof(uint32_t); + -+ /* 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) ++ /* check if this version is higher than we understand */ ++ section_len = (uint32_t *)addr; ++ if (*section_len > SELINUX_COMPILED_FCONTEXT_MAX_VERS) ++ return -1; ++ addr += sizeof(uint32_t); ++ ++ /* allocate the stems_data array */ ++ section_len = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ ++ /* ++ * map indexed by the stem # in the mmap file and contains the stem ++ * number in the data stem_arr ++ */ ++ stem_map_len = *section_len; ++ stem_map = calloc(stem_map_len, sizeof(*stem_map)); ++ if (!stem_map) + return -1; + -+ ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); -+ if (ret < 0) -+ goto out; -+ assert(ret < len); ++ for (i = 0; i < *section_len; i++) { ++ char *buf; ++ uint32_t stem_len; ++ int newid; ++ ++ /* the length does not inlude the nul */ ++ plen = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ ++ stem_len = *plen; ++ buf = (char *)addr; ++ addr += (stem_len + 1); // +1 is the nul ++ ++ /* store the mapping between old and new */ ++ newid = find_stem(data, buf, stem_len); ++ if (newid < 0) { ++ newid = store_stem(data, buf, stem_len); ++ if (newid < 0) ++ return newid; ++ data->stem_arr[newid].from_mmap = 1; ++ } ++ stem_map[i] = newid; ++ } + -+ fd = open(fname, flag); -+ if (fd >= 0 || errno != ENOENT) -+ goto out; ++ /* allocate the regex array */ ++ section_len = (uint32_t *)addr; ++ addr += sizeof(*section_len); ++ ++ for (i = 0; i < *section_len; i++) { ++ struct spec *spec; ++ int32_t stem_id; ++ ++ rc = grow_specs(data); ++ if (rc < 0) ++ return rc; ++ ++ spec = &data->spec_arr[data->nspec]; ++ spec->from_mmap = 1; ++ spec->regcomp = 1; ++ ++ plen = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ spec->lr.ctx_raw = strdup((char *)addr); ++ if (!spec->lr.ctx_raw) ++ return -1; ++ addr += *plen; ++ ++ plen = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ spec->regex_str = (char *)addr; ++ addr += *plen; ++ ++ spec->mode = *(mode_t *)addr; ++ addr += sizeof(mode_t); ++ ++ /* map the stem id from the mmap file to the data->stem_arr */ ++ stem_id = *(int32_t *)addr; ++ if (stem_id == -1) { ++ spec->stem_id = -1; ++ } else { ++ assert(stem_id <= stem_map_len); ++ spec->stem_id = stem_map[stem_id]; ++ } ++ addr += sizeof(int32_t); + -+ alt_name = selinux_boolean_sub(name); -+ if (!alt_name) -+ goto out; ++ /* retrieve the hasMetaChars bit */ ++ spec->hasMetaChars = *(uint32_t *)addr; ++ addr += sizeof(uint32_t); + -+ /* 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; ++ plen = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ spec->regex = (pcre *)addr; ++ addr += *plen; + -+ ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); -+ if (ret < 0) -+ goto out; -+ assert(ret < len); ++ plen = (uint32_t *)addr; ++ addr += sizeof(uint32_t); ++ spec->lsd.study_data = (void *)addr; ++ spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA; ++ addr += *plen; + -+ fd = open(fname, flag); -+out: -+ free(fname); -+ free(alt_name); ++ data->nspec++; ++ } + -+ return fd; ++ free(stem_map); ++ ++ /* win */ ++ return 0; +} + - #define STRBUF_SIZE 3 - static int get_bool_value(const char *name, char **buf) + static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char *prefix) { - int fd, len; -- char *fname = NULL; -+ int errno_tmp; - - if (!selinux_mnt) { - errno = ENOENT; + FILE *fp; +@@ -261,6 +428,10 @@ static int process_file(const char *path, const char *suffix, struct selabel_han return -1; } -- *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1)); -+ *buf = malloc(sizeof(char) * (STRBUF_SIZE + 1)); - if (!*buf) -- goto out; -- (*buf)[STRBUF_SIZE] = 0; -+ return -1; - -- 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); -+ (*buf)[STRBUF_SIZE] = 0; - -- 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 +266,8 @@ hidden_def(security_get_boolean_active) ++ rc = load_mmap(rec, path, &sb); ++ if (rc == 0) ++ goto out; ++ + /* + * The do detailed validation of the input and fill the spec array + */ +@@ -270,6 +441,7 @@ static int process_file(const char *path, const char *suffix, struct selabel_han + if (rc) + return rc; + } ++out: + free(line_buf); + fclose(fp); - int security_set_boolean(const char *name, int value) - { -- int fd, ret, len; -- char buf[2], *fname; -+ int fd, ret; -+ char buf[2]; +@@ -357,6 +529,8 @@ static void closef(struct selabel_handle *rec) - if (!selinux_mnt) { - errno = ENOENT; -@@ -176,17 +278,9 @@ int security_set_boolean(const char *name, int value) - return -1; + for (i = 0; i < data->nspec; i++) { + spec = &data->spec_arr[i]; ++ if (spec->from_mmap) ++ continue; + free(spec->regex_str); + free(spec->type_str); + free(spec->lr.ctx_raw); +@@ -369,6 +543,8 @@ static void closef(struct selabel_handle *rec) + + for (i = 0; i < (unsigned int)data->num_stems; i++) { + stem = &data->stem_arr[i]; ++ if (stem->from_mmap) ++ continue; + free(stem->buf); } -- 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 +290,7 @@ int security_set_boolean(const char *name, int value) +diff --git a/libselinux/src/label_file.h b/libselinux/src/label_file.h +index cb5633b..9799bbb 100644 +--- a/libselinux/src/label_file.h ++++ b/libselinux/src/label_file.h +@@ -5,24 +5,32 @@ - ret = write(fd, buf, 2); - close(fd); -- out: -- free(fname); -+ - if (ret > 0) - return 0; - else -@@ -256,7 +349,7 @@ static char *strtrim(char *dest, char *source, int size) - static int process_boolean(char *buffer, char *name, int namesize, int *val) - { - char name1[BUFSIZ]; -- char *ptr; -+ char *ptr = NULL; - char *tok = strtok_r(buffer, "=", &ptr); - if (tok) { - strncpy(name1, tok, BUFSIZ - 1); -diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c -index b245364..7c47222 100644 ---- a/libselinux/src/callbacks.c -+++ b/libselinux/src/callbacks.c -@@ -16,6 +16,7 @@ default_selinux_log(int type __attribute__((unused)), const char *fmt, ...) - { - int rc; - va_list ap; -+ if (is_selinux_enabled() == 0) return 0; - va_start(ap, fmt); - rc = vfprintf(stderr, fmt, ap); - va_end(ap); -diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h -index 0b00156..d11c8dc 100644 ---- a/libselinux/src/file_path_suffixes.h -+++ b/libselinux/src/file_path_suffixes.h -@@ -22,6 +22,8 @@ S_(BINPOLICY, "/policy/policy") - S_(COLORS, "/secolor.conf") - S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context") - S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context") -+ S_(LXC_CONTEXTS, "/contexts/lxc_contexts") - 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_dist") -diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c -index 7bc46cc..82a608c 100644 ---- a/libselinux/src/label_file.c -+++ b/libselinux/src/label_file.c -@@ -27,6 +27,7 @@ - * Internals, mostly moved over from matchpathcon.c - */ + #include "label_internal.h" -+#define MAX_PREFIX 100 ++#define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a ++#define SELINUX_COMPILED_FCONTEXT_MAX_VERS 1 ++ /* A file security context specification. */ - typedef struct spec { + struct spec { struct selabel_lookup_rec lr; /* holds contexts for lookup result */ -@@ -276,7 +277,7 @@ static int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf) - + char *regex_str; /* regular expession string for diagnostics */ + char *type_str; /* type string for diagnostic messages */ + pcre *regex; /* compiled regular expression */ +- pcre_extra *sd; /* extra compiled stuff */ ++ union { ++ pcre_extra *sd; /* pointer to extra compiled stuff */ ++ pcre_extra lsd; /* used to hold the mmap'd version */ ++ }; + mode_t mode; /* mode format value */ + int matches; /* number of matching pathnames */ + int stem_id; /* indicates which stem-compression item */ + char hasMetaChars; /* regular expression has meta-chars */ + char regcomp; /* regex_str has been compiled to regex */ ++ char from_mmap; /* this spec is from an mmap of the data */ + }; - static int process_line(struct selabel_handle *rec, -- const char *path, const char *prefix, -+ const char *path, const char **prefix_array, - char *line_buf, int pass, unsigned lineno) - { - int items, len; -@@ -310,12 +311,24 @@ static int process_line(struct selabel_handle *rec, - } + /* A regular expression stem */ + struct stem { + char *buf; + int len; ++ char from_mmap; + }; - len = get_stem_from_spec(regex); -- if (len && prefix && strncmp(prefix, regex, len)) { -- /* Stem of regex does not match requested prefix, discard. */ -- free(regex); -- free(type); -- free(context); -- return 0; -+ if (len && prefix_array[0]) { -+ int i = 0; -+ int found = 0; -+ while (i < MAX_PREFIX && prefix_array[i]) { -+ if (strncmp(prefix_array[i], regex, len) == 0) { -+ found = 1; -+ break; -+ } -+ i++; -+ } -+ -+ if (! found) { -+ /* Stem of regex does not match requested prefix, discard. */ -+ free(regex); -+ free(type); -+ free(context); -+ return 0; -+ } - } + /* Our stored configuration */ +@@ -45,7 +53,10 @@ struct saved_data { - if (pass == 1) { -@@ -397,7 +410,8 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, + static inline pcre_extra *get_pcre_extra(struct spec *spec) { - struct saved_data *data = (struct saved_data *)rec->data; - const char *path = NULL; -- const char *prefix = NULL; -+ const char *static_prefix_array[2] = {NULL, }; -+ const char **prefix_array = static_prefix_array; - FILE *fp; - FILE *localfp = NULL; - FILE *homedirfp = NULL; -@@ -418,7 +432,10 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, - path = opts[n].value; - break; - case SELABEL_OPT_SUBSET: -- prefix = opts[n].value; -+ static_prefix_array[0] = opts[n].value; -+ break; -+ case SELABEL_OPT_PREFIXES: -+ prefix_array = opts[n].values; - break; - case SELABEL_OPT_BASEONLY: - baseonly = !!opts[n].value; -@@ -481,7 +498,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, - while (getline(&line_buf, &line_len, fp) > 0) { - if (data->nspec >= maxnspec) - break; -- status = process_line(rec, path, prefix, line_buf, pass, ++lineno); -+ status = process_line(rec, path, prefix_array, line_buf, pass, ++lineno); - if (status) - goto finish; - } -@@ -497,7 +514,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, - while (getline(&line_buf, &line_len, homedirfp) > 0) { - if (data->nspec >= maxnspec) - break; -- status = process_line(rec, homedir_path, prefix, line_buf, pass, ++lineno); -+ status = process_line(rec, homedir_path, prefix_array, line_buf, pass, ++lineno); - if (status) - goto finish; - } -@@ -507,7 +524,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, - while (getline(&line_buf, &line_len, localfp) > 0) { - if (data->nspec >= maxnspec) - break; -- status = process_line(rec, local_path, prefix, line_buf, pass, ++lineno); -+ status = process_line(rec, local_path, prefix_array, line_buf, pass, ++lineno); - if (status) - goto finish; - } +- return spec->sd; ++ if (spec->from_mmap) ++ return &spec->lsd; ++ else ++ return spec->sd; + } + + static inline mode_t string_to_mode(char *mode) diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index 10e29b9..888dab5 100644 --- a/libselinux/src/load_policy.c @@ -788,7 +481,7 @@ index 10e29b9..888dab5 100644 } diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c -index 2d7369e..eb292f2 100644 +index 2d7369e..2a00807 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -2,6 +2,7 @@ @@ -808,60 +501,8 @@ index 2d7369e..eb292f2 100644 va_end(ap); } -@@ -306,7 +307,7 @@ static void matchpathcon_init_once(void) - destructor_key_initialized = 1; - } - --int matchpathcon_init_prefix(const char *path, const char *subset) -+int matchpathcon_init_prefixes(const char *path, const char **prefixes) - { - if (!mycanoncon) - mycanoncon = default_canoncon; -@@ -314,15 +315,22 @@ int matchpathcon_init_prefix(const char *path, const char *subset) - __selinux_once(once, matchpathcon_init_once); - __selinux_setspecific(destructor_key, (void *)1); - -- options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET; -- options[SELABEL_OPT_SUBSET].value = subset; -+ options[SELABEL_OPT_PREFIXES].type = SELABEL_OPT_PREFIXES; -+ options[SELABEL_OPT_PREFIXES].values = prefixes; - options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH; - options[SELABEL_OPT_PATH].value = path; - - hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT); - return hnd ? 0 : -1; - } -+hidden_def(matchpathcon_init_prefixes) - -+int matchpathcon_init_prefix(const char *path, const char *prefix) -+{ -+ const char *prefixes[2] = { prefix, NULL }; -+ -+ return matchpathcon_init_prefixes(path, prefixes); -+} - hidden_def(matchpathcon_init_prefix) - - int matchpathcon_init(const char *path) -@@ -397,10 +405,13 @@ int realpath_not_final(const char *name, char *resolved_path) - goto out; - } - -- resolved_path += len; -- strcpy(resolved_path, "/"); -- resolved_path += 1; -- strcpy(resolved_path, last_component); -+ p = resolved_path; -+ p += len; -+ if (strcmp(resolved_path, "/") != 0) { -+ strcpy(p, "/"); -+ p += 1; -+ } -+ strcpy(p, last_component); - out: - free(tmp_path); - return rc; diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index f42cb7c..cb65666 100644 +index 296f357..cb65666 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -9,6 +9,7 @@ @@ -872,18 +513,7 @@ index f42cb7c..cb65666 100644 #include "get_default_type_internal.h" #define SELINUXDIR "/etc/selinux/" -@@ -46,7 +47,9 @@ - #define FILE_CONTEXT_SUBS 23 - #define SEPGSQL_CONTEXTS 24 - #define FILE_CONTEXT_SUBS_DIST 25 --#define NEL 26 -+#define LXC_CONTEXTS 26 -+#define BOOLEAN_SUBS 27 -+#define NEL 28 - - /* Part of one-time lazy init */ - static pthread_once_t once = PTHREAD_ONCE_INIT; -@@ -294,13 +297,57 @@ const char *selinux_removable_context_path(void) +@@ -296,13 +297,57 @@ const char *selinux_removable_context_path(void) hidden_def(selinux_removable_context_path) @@ -942,293 +572,431 @@ index f42cb7c..cb65666 100644 const char *selinux_file_context_path(void) { return get_path(FILE_CONTEXTS); -@@ -418,6 +465,19 @@ const char *selinux_virtual_image_context_path(void) - - hidden_def(selinux_virtual_image_context_path) - -+const char *selinux_lxc_contexts_path(void) -+{ -+ return get_path(LXC_CONTEXTS); -+} -+ -+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 00df405..c47add9 100644 +index 2c7c85c..75ebc88 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h -@@ -59,13 +59,18 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(security_getenforce) - hidden_proto(security_setenforce) +@@ -61,7 +61,9 @@ hidden_proto(selinux_mkload_policy) hidden_proto(security_deny_unknown) -+ hidden_proto(selinux_binary_policy_path_min_max) -+ hidden_proto(selinux_boolean_sub) + hidden_proto(selinux_boolean_sub) hidden_proto(selinux_binary_policy_path) -+ hidden_proto(selinux_booleans_subs_path) ++ hidden_proto(selinux_binary_policy_path_min_max); + hidden_proto(selinux_booleans_subs_path) + hidden_proto(selinux_current_policy_path) hidden_proto(selinux_default_context_path) hidden_proto(selinux_securetty_types_path) hidden_proto(selinux_failsafe_context_path) - hidden_proto(selinux_removable_context_path) - hidden_proto(selinux_virtual_domain_context_path) - hidden_proto(selinux_virtual_image_context_path) -+ hidden_proto(selinux_lxc_contexts_path) - hidden_proto(selinux_file_context_path) - hidden_proto(selinux_file_context_homedir_path) - hidden_proto(selinux_file_context_local_path) -@@ -82,6 +87,7 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(selinux_path) - hidden_proto(selinux_check_passwd_access) - hidden_proto(selinux_check_securetty_context) -+ hidden_proto(matchpathcon_init_prefixes) - hidden_proto(matchpathcon_init_prefix) - hidden_proto(selinux_users_path) - hidden_proto(selinux_usersconf_path); diff --git a/libselinux/src/seusers.c b/libselinux/src/seusers.c -index 73ad42c..569fa43 100644 +index cfea186..8b1eba6 100644 --- a/libselinux/src/seusers.c +++ b/libselinux/src/seusers.c -@@ -276,13 +276,19 @@ int getseuser(const char *username, const char *service, - if (fp == NULL) goto err; - __fsetlocking(fp, FSETLOCKING_BYCALLER); - while (getline(&buffer, &size, fp) > 0) { -- if (strncmp(buffer, "*:", 2) == 0) { -+ -+ if (!service) { -+ rec = strdup(buffer); -+ break; -+ } -+ -+ if (strncmp(buffer, "*:", 2) == 0) -+ { - free(rec); - rec = strdup(buffer); - continue; - } -- if (!service) -- continue; -+ - len = strlen(service); - if ((strncmp(buffer, service, len) == 0) && - (buffer[len] == ':')) { -@@ -298,6 +304,7 @@ int getseuser(const char *username, const char *service, - - seuser++; - level = strchr(seuser, ':'); -+ if (! level) goto err; - *level = 0; - level++; - *r_seuser = strdup(seuser); -diff --git a/libselinux/utils/avcstat.c b/libselinux/utils/avcstat.c -index 7239ef2..73432f2 100644 ---- a/libselinux/utils/avcstat.c -+++ b/libselinux/utils/avcstat.c -@@ -139,6 +139,7 @@ int main(int argc, char **argv) - - sa.sa_handler = sighandler; - sa.sa_flags = SA_RESTART; -+ sigemptyset(&sa.sa_mask); - - i = sigaction(SIGWINCH, &sa, NULL); - if (i < 0) -diff --git a/libselinux/utils/getdefaultcon.c b/libselinux/utils/getdefaultcon.c -index 049e75c..6bafedb 100644 ---- a/libselinux/utils/getdefaultcon.c -+++ b/libselinux/utils/getdefaultcon.c -@@ -21,10 +21,11 @@ int main(int argc, char **argv) - { - security_context_t usercon = NULL, cur_context = NULL; - char *user = NULL, *level = NULL, *role=NULL, *seuser=NULL, *dlevel=NULL; -+ char *service = NULL; - int ret, opt; - int verbose = 0; - -- while ((opt = getopt(argc, argv, "l:r:v")) > 0) { -+ while ((opt = getopt(argc, argv, "l:r:s:v")) > 0) { - switch (opt) { - case 'l': - level = strdup(optarg); -@@ -32,6 +33,9 @@ int main(int argc, char **argv) - case 'r': - role = strdup(optarg); +@@ -125,7 +125,7 @@ static int check_group(const char *group, const char *name, const gid_t gid) { + rbuf = malloc(rbuflen); + if (rbuf == NULL) + return 0; +- int retval = getgrnam_r(group, &gbuf, rbuf, ++ int retval = getgrnam_r(group, &gbuf, rbuf, + rbuflen, &grent); + if ( retval == ERANGE ) + { +@@ -198,13 +198,13 @@ int getseuserbyname(const char *name, char **r_seuser, char **r_level) + if (!strcmp(username, name)) break; -+ case 's': -+ service = strdup(optarg); -+ break; - case 'v': - verbose = 1; - break; -@@ -61,7 +65,7 @@ int main(int argc, char **argv) - } else - cur_context = argv[optind + 1]; -- if ((ret = getseuserbyname(user, &seuser, &dlevel)) == 0) { -+ if ((ret = getseuser(user, service, &seuser, &dlevel)) == 0) { - if (! level) level=dlevel; - if (role != NULL && role[0]) - ret=get_default_context_with_rolelevel(seuser, role, level,cur_context,&usercon); -@@ -74,7 +78,7 @@ int main(int argc, char **argv) - if (verbose) { - printf("%s: %s from %s %s %s %s -> %s\n", argv[0], user, cur_context, seuser, role, level, usercon); +- if (username[0] == '%' && +- !groupseuser && ++ if (username[0] == '%' && ++ !groupseuser && + check_group(&username[1], name, gid)) { + groupseuser = seuser; + grouplevel = level; } else { -- printf("%s", usercon); -+ printf("%s\n", usercon); - } - } +- if (!defaultseuser && ++ if (!defaultseuser && + !strcmp(username, "__default__")) { + defaultseuser = seuser; + defaultlevel = level; +@@ -258,7 +258,7 @@ int getseuserbyname(const char *name, char **r_seuser, char **r_level) + return 0; + } -diff --git a/libselinux/utils/getsebool.c b/libselinux/utils/getsebool.c -index 3a90449..9ae9243 100644 ---- a/libselinux/utils/getsebool.c -+++ b/libselinux/utils/getsebool.c -@@ -87,14 +87,22 @@ int main(int argc, char **argv) - rc = -1; - goto out; - } -+ char *alt_name = selinux_boolean_sub(names[i]); -+ if (! alt_name) { -+ perror("Out of memory\n"); -+ rc = -1; -+ goto out; +-int getseuser(const char *username, const char *service, ++int getseuser(const char *username, const char *service, + char **r_seuser, char **r_level) { + int ret = -1; + int len = 0; +diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore +index 8b9294d..060eaab 100644 +--- a/libselinux/utils/.gitignore ++++ b/libselinux/utils/.gitignore +@@ -13,6 +13,7 @@ getsebool + getseuser + matchpathcon + policyvers ++sefcontext_compile + selinux_check_securetty_context + selinuxenabled + selinuxexeccon +diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile +index 5f3e047..f469924 100644 +--- a/libselinux/utils/Makefile ++++ b/libselinux/utils/Makefile +@@ -28,6 +28,7 @@ LDLIBS += -L../src -lselinux -L$(LIBDIR) + + TARGETS=$(patsubst %.c,%,$(wildcard *.c)) + ++sefcontext_compile: LDLIBS += -lpcre + + ifeq ($(DISABLE_AVC),y) + UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel +diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c +new file mode 100644 +index 0000000..f8a5fea +--- /dev/null ++++ b/libselinux/utils/sefcontext_compile.c +@@ -0,0 +1,345 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "../src/label_file.h" ++ ++static int process_file(struct saved_data *data, const char *filename) ++{ ++ struct spec *spec; ++ unsigned int line_num; ++ char *line_buf = NULL; ++ size_t line_len; ++ ssize_t len; ++ FILE *context_file; ++ ++ context_file = fopen(filename, "r"); ++ if (!context_file) ++ return -1; ++ ++ line_num = 0; ++ while ((len = getline(&line_buf, &line_len, context_file)) != -1) { ++ char *context; ++ char *mode; ++ char *regex; ++ char *cp, *anchored_regex; ++ char *buf_p; ++ pcre *re; ++ pcre_extra *sd; ++ const char *err; ++ int items, erroff, rc; ++ size_t regex_len; ++ int32_t stem_id; ++ ++ len = strlen(line_buf); ++ if (line_buf[len - 1] == '\n') ++ line_buf[len - 1] = 0; ++ buf_p = line_buf; ++ while (isspace(*buf_p)) ++ buf_p++; ++ /* Skip comment lines and empty lines. */ ++ if (*buf_p == '#' || *buf_p == 0) ++ continue; ++ ++ items = sscanf(line_buf, "%ms %ms %ms", ®ex, &mode, &context); ++ if (items < 2 || items > 3) { ++ fprintf(stderr, "invalid entry, skipping:%s", line_buf); ++ continue; + } + - if (pending != active) { -- printf("%s --> %s pending: %s\n", names[i], -+ printf("%s --> %s pending: %s\n", alt_name, - (active ? "on" : "off"), - (pending ? "on" : "off")); - } else { -- printf("%s --> %s\n", names[i], -+ printf("%s --> %s\n", alt_name, - (active ? "on" : "off")); - } -+ free(alt_name); - } - - out: -diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c -index b1adadd..a3a21ca 100644 ---- a/libselinux/utils/matchpathcon.c -+++ b/libselinux/utils/matchpathcon.c -@@ -45,21 +45,27 @@ static int printmatchpathcon(const char *path, int header, int mode) - - int main(int argc, char **argv) - { -- int i, init = 0; -+ int i, force_mode = 0; - int header = 1, opt; - int verify = 0; - int notrans = 0; - int error = 0; - int quiet = 0; -+ const char *prefixes[100]; -+ char *file = NULL; -+ int prefix=0; - - if (argc < 2) - usage(argv[0]); - -- while ((opt = getopt(argc, argv, "Nnf:p:Vq")) > 0) { -+ while ((opt = getopt(argc, argv, "m:Nnf:p:Vq")) > 0) { - switch (opt) { - case 'n': - header = 0; - break; -+ case 'm': -+ force_mode = atoi(optarg); -+ break; - case 'V': - verify = 1; - break; -@@ -68,36 +74,24 @@ int main(int argc, char **argv) - set_matchpathcon_flags(MATCHPATHCON_NOTRANS); - break; - case 'f': -- if (init) { -+ if (prefix) { - fprintf(stderr, - "%s: -f and -p are exclusive\n", - argv[0]); - exit(1); - } -- init = 1; -- if (matchpathcon_init(optarg)) { -- fprintf(stderr, -- "Error while processing %s: %s\n", -- optarg, -- errno ? strerror(errno) : "invalid"); -- exit(1); -- } -+ file = optarg; - break; - case 'p': -- if (init) { -+ if (file) { - fprintf(stderr, - "%s: -f and -p are exclusive\n", - argv[0]); - exit(1); - } -- init = 1; -- if (matchpathcon_init_prefix(NULL, optarg)) { -- fprintf(stderr, -- "Error while processing %s: %s\n", -- optarg, -- errno ? strerror(errno) : "invalid"); -- exit(1); -- } -+ prefixes[prefix]=optarg; -+ prefix++; -+ prefixes[prefix]=NULL; - break; - case 'q': - quiet = 1; -@@ -106,6 +100,26 @@ int main(int argc, char **argv) - usage(argv[0]); - } - } -+ if (prefix > 0) { -+ if (matchpathcon_init_prefixes(file, prefixes)) { -+ fprintf(stderr, -+ "Error while processing %s: %s\n", -+ file, -+ errno ? strerror(errno) : "invalid"); -+ exit(1); ++ if (items == 2) { ++ context = mode; ++ mode = NULL; + } -+ } else { -+ if (file) { -+ if (matchpathcon_init(file)) { -+ fprintf(stderr, -+ "Error inwhile processing %s: %s\n", -+ file, -+ errno ? strerror(errno) : "invalid"); -+ exit(1); -+ } ++ ++ rc = grow_specs(data); ++ if (rc) ++ return rc; ++ ++ spec = &data->spec_arr[data->nspec]; ++ ++ spec->lr.ctx_raw = context; ++ spec->mode = string_to_mode(mode); ++ if (spec->mode == -1) { ++ fprintf(stderr, "%s: line %d has invalid file type %s\n", ++ regex, line_num + 1, mode); ++ spec->mode = 0; + } ++ free(mode); ++ spec->regex_str = regex; ++ ++ stem_id = find_stem_from_spec(data, regex); ++ spec->stem_id = stem_id; ++ /* skip past the fixed stem part */ ++ if (stem_id != -1) ++ regex += data->stem_arr[stem_id].len; ++ ++ regex_len = strlen(regex); ++ cp = anchored_regex = malloc(regex_len + 3); ++ if (!cp) ++ return -1; ++ ++ *cp++ = '^'; ++ memcpy(cp, regex, regex_len); ++ cp += regex_len; ++ *cp++ = '$'; ++ *cp = '\0'; ++ ++ spec_hasMetaChars(spec); ++ ++ re = pcre_compile(anchored_regex, 0, &err, &erroff, NULL); ++ if (!re) { ++ fprintf(stderr, "PCRE compilation failed for %s at offset %d: %s\n", anchored_regex, erroff, err); ++ return -1; ++ } ++ spec->regex = re; ++ ++ sd = pcre_study(re, 0, &err); ++ if (!sd) { ++ fprintf(stderr, "PCRE study failed for %s: %s\n", anchored_regex, err); ++ return -1; ++ } ++ free(anchored_regex); ++ spec->sd = sd; ++ ++ line_num++; ++ data->nspec++; + } + - for (i = optind; i < argc; i++) { - int rc, mode = 0; - struct stat buf; -@@ -114,8 +128,11 @@ int main(int argc, char **argv) - if (len > 1 && path[len - 1 ] == '/') - path[len - 1 ] = '\0'; - -- if (lstat(path, &buf) == 0) -- mode = buf.st_mode; -+ if (! force_mode) { -+ if (lstat(path, &buf) == 0) -+ mode = buf.st_mode; -+ } else -+ mode = force_mode; - - if (verify) { - rc = selinux_file_context_verify(path, mode); ++ free(line_buf); ++ fclose(context_file); ++ ++ return 0; ++} ++ ++/* ++ * File Format ++ * ++ * u32 - magic number ++ * u32 - version ++ * u32 - number of stems ++ * ** Stems ++ * u32 - length of stem EXCLUDING nul ++ * char - stem char array INCLUDING nul ++ * u32 - number of regexs ++ * ** Regexes ++ * u32 - length of upcoming context INCLUDING nul ++ * char - char array of the raw context ++ * u32 - length of the upcoming regex_str ++ * char - char array of the original regex string including the stem. ++ * mode_t - mode bits ++ * s32 - stemid associated with the regex ++ * u32 - spec has meta characters ++ * u32 - data length of the pcre regex ++ * char - a bufer holding the raw pcre regex info ++ * u32 - data length of the pcre regex study daya ++ * char - a buffer holding the raw pcre regex study data ++ */ ++static int write_binary_file(struct saved_data *data, char *filename) ++{ ++ struct spec *specs = data->spec_arr; ++ FILE *bin_file; ++ size_t len; ++ uint32_t magic = SELINUX_MAGIC_COMPILED_FCONTEXT; ++ uint32_t section_len; ++ uint32_t i; ++ ++ bin_file = fopen(filename, "w"); ++ if (!bin_file) { ++ perror("fopen output_file"); ++ exit(EXIT_FAILURE); ++ } ++ ++ /* write some magic number */ ++ len = fwrite(&magic, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* write the version */ ++ section_len = SELINUX_COMPILED_FCONTEXT_MAX_VERS; ++ len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* write the number of stems coming */ ++ section_len = data->num_stems; ++ len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ for (i = 0; i < section_len; i++) { ++ char *stem = data->stem_arr[i].buf; ++ uint32_t stem_len = data->stem_arr[i].len; ++ ++ /* write the strlen (aka no nul) */ ++ len = fwrite(&stem_len, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* include the nul in the file */ ++ stem_len += 1; ++ len = fwrite(stem, sizeof(char), stem_len, bin_file); ++ if (len != stem_len) ++ return -1; ++ } ++ ++ /* write the number of regexes coming */ ++ section_len = data->nspec; ++ len = fwrite(§ion_len, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ for (i = 0; i < section_len; i++) { ++ char *context = specs[i].lr.ctx_raw; ++ char *regex_str = specs[i].regex_str; ++ mode_t mode = specs[i].mode; ++ int32_t stem_id = specs[i].stem_id; ++ pcre *re = specs[i].regex; ++ pcre_extra *sd = get_pcre_extra(&specs[i]); ++ uint32_t to_write; ++ size_t size; ++ int rc; ++ ++ /* length of the context string (including nul) */ ++ to_write = strlen(context) + 1; ++ len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* original context strin (including nul) */ ++ len = fwrite(context, sizeof(char), to_write, bin_file); ++ if (len != to_write) ++ return -1; ++ ++ /* length of the original regex string (including nul) */ ++ to_write = strlen(regex_str) + 1; ++ len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* original regex string */ ++ len = fwrite(regex_str, sizeof(char), to_write, bin_file); ++ if (len != to_write) ++ return -1; ++ ++ /* binary F_MODE bits */ ++ len = fwrite(&mode, sizeof(mode), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* stem for this regex (could be -1) */ ++ len = fwrite(&stem_id, sizeof(stem_id), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* does this spec have a metaChar? */ ++ to_write = specs[i].hasMetaChars; ++ len = fwrite(&to_write, sizeof(to_write), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* determine the size of the pcre data in bytes */ ++ rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size); ++ if (rc < 0) ++ return -1; ++ ++ /* write the number of bytes in the pcre data */ ++ to_write = size; ++ len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* write the actual pcre data as a char array */ ++ len = fwrite(re, 1, to_write, bin_file); ++ if (len != to_write) ++ return -1; ++ ++ /* determine the size of the pcre study info */ ++ rc = pcre_fullinfo(re, sd, PCRE_INFO_STUDYSIZE, &size); ++ if (rc < 0) ++ return -1; ++ ++ /* write the number of bytes in the pcre study data */ ++ to_write = size; ++ len = fwrite(&to_write, sizeof(uint32_t), 1, bin_file); ++ if (len != 1) ++ return -1; ++ ++ /* write the actual pcre study data as a char array */ ++ len = fwrite(sd->study_data, 1, to_write, bin_file); ++ if (len != to_write) ++ return -1; ++ } ++ ++ fclose(bin_file); ++ ++ return 0; ++} ++ ++static int free_specs(struct saved_data *data) ++{ ++ struct spec *specs = data->spec_arr; ++ unsigned int num_entries = data->nspec; ++ unsigned int i; ++ ++ for (i = 0; i < num_entries; i++) { ++ free(specs[i].lr.ctx_raw); ++ free(specs[i].lr.ctx_trans); ++ free(specs[i].regex_str); ++ pcre_free(specs[i].regex); ++ pcre_free_study(specs[i].sd); ++ } ++ free(specs); ++ ++ num_entries = data->num_stems; ++ for (i = 0; i < num_entries; i++) { ++ free(data->stem_arr[i].buf); ++ } ++ free(data->stem_arr); ++ ++ memset(data, 0, sizeof(*data)); ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ struct saved_data data; ++ const char *path; ++ char stack_path[PATH_MAX + 1]; ++ int rc; ++ ++ if (argc != 2) { ++ fprintf(stderr, "usage: %s input_file\n", argv[0]); ++ exit(EXIT_FAILURE); ++ } ++ ++ memset(&data, 0, sizeof(data)); ++ ++ path = argv[1]; ++ ++ rc = process_file(&data, path); ++ if (rc < 0) ++ return rc; ++ ++ rc = sort_specs(&data); ++ if (rc) ++ return rc; ++ ++ rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path); ++ if (rc < 0 || rc >= sizeof(stack_path)) ++ return rc; ++ rc = write_binary_file(&data, stack_path); ++ if (rc < 0) ++ return rc; ++ ++ rc = free_specs(&data); ++ if (rc < 0) ++ return rc; ++ ++ return 0; ++} diff --git a/libselinux-tlssegneg.patch b/libselinux-tlssegneg.patch deleted file mode 100644 index fe254dd..0000000 --- a/libselinux-tlssegneg.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- libselinux-1.30.19/src/Makefile.notls 2006-08-01 14:16:38.000000000 -0400 -+++ libselinux-1.30.19/src/Makefile 2006-08-01 14:37:15.000000000 -0400 -@@ -24,6 +24,11 @@ - override CFLAGS += -I../include -I$(INCLUDEDIR) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 - RANLIB=ranlib - -+ARCH := $(patsubst i%86,i386,$(shell uname -m)) -+ifneq (,$(filter i386,$(ARCH))) -+TLSFLAGS += -mno-tls-direct-seg-refs -+endif -+ - SWIG = swig -Wall -python -o $(SWIGCOUT) -outdir ./ - - all: $(LIBA) $(LIBSO) -@@ -45,7 +50,7 @@ - ln -sf $@ $(TARGET) - - %.o: %.c policy.h -- $(CC) $(CFLAGS) -c -o $@ $< -+ $(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< - - %.lo: %.c policy.h - $(CC) $(CFLAGS) -fpic -DSHARED -c -o $@ $< diff --git a/libselinux-xaccel.patch b/libselinux-xaccel.patch deleted file mode 100644 index f8ba360..0000000 --- a/libselinux-xaccel.patch +++ /dev/null @@ -1,236 +0,0 @@ -diff -up libselinux-2.0.77/include/selinux/avc.h.pre.create.cache libselinux-2.0.77/include/selinux/avc.h ---- libselinux-2.0.77/include/selinux/avc.h.pre.create.cache 2009-01-27 14:47:32.000000000 -0500 -+++ libselinux-2.0.77/include/selinux/avc.h 2009-03-02 14:52:40.859167987 -0500 -@@ -353,6 +353,7 @@ int avc_compute_member(security_id_t ssi - #define AVC_CALLBACK_AUDITALLOW_DISABLE 32 - #define AVC_CALLBACK_AUDITDENY_ENABLE 64 - #define AVC_CALLBACK_AUDITDENY_DISABLE 128 -+#define AVC_CALLBACK_ADD_CREATE 256 - - /** - * avc_add_callback - Register a callback for security events. -diff -up libselinux-2.0.77/src/avc.c.pre.create.cache libselinux-2.0.77/src/avc.c ---- libselinux-2.0.77/src/avc.c.pre.create.cache 2009-01-27 14:47:32.000000000 -0500 -+++ libselinux-2.0.77/src/avc.c 2009-03-02 15:57:54.764288907 -0500 -@@ -20,6 +20,8 @@ struct avc_entry { - security_id_t tsid; - security_class_t tclass; - struct av_decision avd; -+ security_id_t create_sid; -+ unsigned create_decided :1; - int used; /* used recently */ - }; - -@@ -58,6 +60,11 @@ static struct avc_cache_stats cache_stat - static struct avc_callback_node *avc_callbacks = NULL; - static struct sidtab avc_sidtab; - -+/* forward declaration */ -+static int avc_update_cache(uint32_t event, security_id_t ssid, -+ security_id_t tsid, security_class_t tclass, -+ access_vector_t perms, security_id_t create_sid); -+ - static inline int avc_hash(security_id_t ssid, - security_id_t tsid, security_class_t tclass) - { -@@ -340,6 +347,16 @@ static inline struct avc_node *avc_recla - return cur; - } - -+static inline void avc_clear_avc_entry(struct avc_entry *ae) -+{ -+ ae->ssid = ae->tsid = ae->create_sid = NULL; -+ ae->tclass = 0; -+ ae->create_decided = 0; -+ ae->avd.allowed = ae->avd.decided = 0; -+ ae->avd.auditallow = ae->avd.auditdeny = 0; -+ ae->used = 0; -+} -+ - static inline struct avc_node *avc_claim_node(security_id_t ssid, - security_id_t tsid, - security_class_t tclass) -@@ -361,6 +378,7 @@ static inline struct avc_node *avc_claim - } - - hvalue = avc_hash(ssid, tsid, tclass); -+ avc_clear_avc_entry(&new->ae); - new->ae.used = 1; - new->ae.ssid = ssid; - new->ae.tsid = tsid; -@@ -498,8 +516,8 @@ static int avc_insert(security_id_t ssid - * avc_remove - Remove AVC and sidtab entries for SID. - * @sid: security identifier to be removed - * -- * Remove all AVC entries containing @sid as source -- * or target, and remove @sid from the SID table. -+ * Remove all AVC entries containing @sid as source, target, or -+ * create_sid, and remove @sid from the SID table. - * Free the memory allocated for the structure corresponding - * to @sid. After this function has been called, @sid must - * not be used until another call to avc_context_to_sid() has -@@ -514,19 +532,15 @@ static void avc_remove(security_id_t sid - cur = avc_cache.slots[i]; - prev = NULL; - while (cur) { -- if (sid == cur->ae.ssid || sid == cur->ae.tsid) { -+ if (sid == cur->ae.ssid || sid == cur->ae.tsid || -+ (cur->ae.create_decided && sid == cur->ae.create_sid)) { - if (prev) - prev->next = cur->next; - else - avc_cache.slots[i] = cur->next; - tmp = cur; - cur = cur->next; -- tmp->ae.ssid = tmp->ae.tsid = NULL; -- tmp->ae.tclass = 0; -- tmp->ae.avd.allowed = tmp->ae.avd.decided = 0; -- tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = -- 0; -- tmp->ae.used = 0; -+ avc_clear_avc_entry(&tmp->ae); - tmp->next = avc_node_freelist; - avc_node_freelist = tmp; - avc_cache.active_nodes--; -@@ -570,11 +584,7 @@ int avc_reset(void) - while (node) { - tmp = node; - node = node->next; -- tmp->ae.ssid = tmp->ae.tsid = NULL; -- tmp->ae.tclass = 0; -- tmp->ae.avd.allowed = tmp->ae.avd.decided = 0; -- tmp->ae.avd.auditallow = tmp->ae.avd.auditdeny = 0; -- tmp->ae.used = 0; -+ avc_clear_avc_entry(&tmp->ae); - tmp->next = avc_node_freelist; - avc_node_freelist = tmp; - avc_cache.active_nodes--; -@@ -896,24 +906,52 @@ int avc_compute_create(security_id_t ssi - security_class_t tclass, security_id_t *newsid) - { - int rc; -+ struct avc_entry_ref aeref; -+ security_context_t ctx = NULL; -+ - *newsid = NULL; -+ -+ avc_entry_ref_init(&aeref); -+retry: - avc_get_lock(avc_lock); -- if (ssid->refcnt > 0 && tsid->refcnt > 0) { -- security_context_t ctx = NULL; -- rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass, -- &ctx); -- if (rc) -- goto out; -- rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid); -- if (!rc) -- (*newsid)->refcnt++; -- freecon(ctx); -- } else { -+ if (ssid->refcnt <= 0 || tsid->refcnt <= 0) { - errno = EINVAL; /* bad reference count */ - rc = -1; -+ goto out; -+ } -+ -+ rc = avc_lookup(ssid, tsid, tclass, 0, &aeref); -+ if (!rc) { -+ /* we found something in the avc */ -+ if (aeref.ae->create_decided) { -+ *newsid = aeref.ae->create_sid; -+ goto out; -+ } else { -+ goto compute; -+ } - } -+ /* there is nothing in the avd for this tuple, so, lets get something */ -+ avc_release_lock(avc_lock); -+ avc_has_perm_noaudit(ssid, tsid, tclass, 0, &aeref, NULL); -+ goto retry; -+ -+compute: -+ rc = security_compute_create_raw(ssid->ctx, tsid->ctx, tclass, -+ &ctx); -+ if (rc) -+ goto out; -+ rc = sidtab_context_to_sid(&avc_sidtab, ctx, newsid); -+ if (rc) -+ goto out; -+ -+ avc_update_cache(AVC_CALLBACK_ADD_CREATE, ssid, tsid, tclass, 0, -+ *newsid); -+ - out: -+ if (*newsid) -+ (*newsid)->refcnt++; - avc_release_lock(avc_lock); -+ freecon(ctx); - return rc; - } - -@@ -978,7 +1016,8 @@ static inline int avc_sidcmp(security_id - } - - static inline void avc_update_node(uint32_t event, struct avc_node *node, -- access_vector_t perms) -+ access_vector_t perms, -+ security_id_t create_sid) - { - switch (event) { - case AVC_CALLBACK_GRANT: -@@ -1000,12 +1039,16 @@ static inline void avc_update_node(uint3 - case AVC_CALLBACK_AUDITDENY_DISABLE: - node->ae.avd.auditdeny &= ~perms; - break; -+ case AVC_CALLBACK_ADD_CREATE: -+ node->ae.create_sid = create_sid; -+ node->ae.create_decided = 1; -+ break; - } - } - - static int avc_update_cache(uint32_t event, security_id_t ssid, - security_id_t tsid, security_class_t tclass, -- access_vector_t perms) -+ access_vector_t perms, security_id_t create_sid) - { - struct avc_node *node; - int i; -@@ -1019,7 +1062,7 @@ static int avc_update_cache(uint32_t eve - if (avc_sidcmp(ssid, node->ae.ssid) && - avc_sidcmp(tsid, node->ae.tsid) && - tclass == node->ae.tclass) { -- avc_update_node(event, node, perms); -+ avc_update_node(event, node, perms, create_sid); - } - } - } -@@ -1027,7 +1070,7 @@ static int avc_update_cache(uint32_t eve - /* apply to one node */ - node = avc_search_node(ssid, tsid, tclass, 0); - if (node) { -- avc_update_node(event, node, perms); -+ avc_update_node(event, node, perms, create_sid); - } - } - -@@ -1058,7 +1101,7 @@ static int avc_control(uint32_t event, s - * been invoked to update the cache state. - */ - if (event != AVC_CALLBACK_TRY_REVOKE) -- avc_update_cache(event, ssid, tsid, tclass, perms); -+ avc_update_cache(event, ssid, tsid, tclass, perms, NULL); - - for (c = avc_callbacks; c; c = c->next) { - if ((c->events & event) && -@@ -1080,7 +1123,7 @@ static int avc_control(uint32_t event, s - if (event == AVC_CALLBACK_TRY_REVOKE) { - /* revoke any unretained permissions */ - perms &= ~tretained; -- avc_update_cache(event, ssid, tsid, tclass, perms); -+ avc_update_cache(event, ssid, tsid, tclass, perms, NULL); - *out_retained = tretained; - } - - diff --git a/libselinux.spec b/libselinux.spec index 1d2df2a..abeae88 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -2,13 +2,13 @@ %define ruby_inc %(pkg-config --cflags ruby-1.9) %define ruby_sitearch %(ruby -rrbconfig -e "puts RbConfig::CONFIG['vendorarchdir']") -%define libsepolver 2.1.5-1 +%define libsepolver 2.1.8-1 %{!?python_sitearch: %define python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")} Summary: SELinux library and simple utilities Name: libselinux -Version: 2.1.11 -Release: 4%{?dist} +Version: 2.1.12 +Release: 1%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -185,6 +185,7 @@ rm -rf %{buildroot} %{_libdir}/libselinux.so.* /var/run/setrans %{_sbindir}/matchpathcon +%{_sbindir}/sefcontext_compile /usr/lib/tmpfiles.d/libselinux.conf %files utils @@ -233,6 +234,40 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Thu Sep 13 2012 Dan Walsh - 2.1.12-1 +- Update to upstream + * Add support for lxc_contexts_path + * utils: add service to getdefaultcon + * libsemanage: do not set soname needlessly + * libsemanage: remove PYTHONLIBDIR and ruby equivalent + * boolean name equivalency + * getsebool: support boolean name substitution + * Add man page for new selinux_boolean_sub function. + * expose selinux_boolean_sub + * matchpathcon: add -m option to force file type check + * utils: avcstat: clear sa_mask set + * seusers: Check for strchr failure + * booleans: initialize pointer to silence coveriety + * stop messages when SELinux disabled + * label_file: use PCRE instead of glibc regex functions + * label_file: remove all typedefs + * label_file: move definitions to include file + * label_file: do string to mode_t conversion in a helper function + * label_file: move error reporting back into caller + * label_file: move stem/spec handling to header + * label_file: drop useless ncomp field from label_file data + * label_file: move spec_hasMetaChars to header + * label_file: fix potential read past buffer in spec_hasMetaChars + * label_file: move regex sorting to the header + * label_file: add accessors for the pcre extra data + * label_file: only run regex files one time + * label_file: new process_file function + * label_file: break up find_stem_from_spec + * label_file: struct reorg + * label_file: only run array once when sorting + * Ensure that we only close the selinux netlink socket once. + * improve the file_contexts.5 manual page + * Tue Jul 31 2012 Dan Walsh - 2.1.11-4 - Ensure that we only close the selinux netlink socket once. - Taken from our Android libselinux tree. From Stephen Smalley diff --git a/libselinux_swig_with_raw.patch b/libselinux_swig_with_raw.patch deleted file mode 100644 index 2b6a4e8..0000000 --- a/libselinux_swig_with_raw.patch +++ /dev/null @@ -1,343 +0,0 @@ -Index: libselinux/src/selinuxswig.i -=================================================================== ---- libselinux/src/selinuxswig.i (revision 2476) -+++ libselinux/src/selinuxswig.i (working copy) -@@ -1,7 +1,9 @@ --/* Author: Dan Walsh -+/* Authors: Dan Walsh -+ * James Athey - * - * Copyright (C) 2004-2005 Red Hat -- * -+ * Copyright (C) 2007 Tresys Technology, LLC -+ * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either -@@ -17,170 +19,47 @@ - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -- - %module selinux - %{ - #include "selinux/selinux.h" -- #include "selinux/get_context_list.h" - %} --%apply int *OUTPUT { int * }; -+%apply int *OUTPUT { int *enforce }; - %apply int *OUTPUT { size_t * }; - --%typemap(in, numinputs=0) security_context_t *(security_context_t temp=NULL) { -- $1 = &temp; --} --%typemap(argout) security_context_t * (char *temp=NULL) { -- if (*$1) -- temp = *$1; -- else -- temp = ""; -- $result = SWIG_Python_AppendOutput($result, PyString_FromString(temp)); --} -+%typedef unsigned mode_t; - --%typemap(in) security_context_t { -- $1 = (security_context_t)PyString_AsString($input); -+%typemap(in, numinputs=0) (char ***names, int *len) (char **temp1, int temp2) { -+ $1 = &temp1; -+ $2 = &temp2; - } - --%typedef unsigned mode_t; -- --%include "../include/selinux/get_context_list.h" -- --extern int is_selinux_enabled(void); --extern int is_selinux_mls_enabled(void); --extern void freecon(security_context_t con); --extern void freeconary(security_context_t * con); --extern int getcon(security_context_t *con); --extern int setcon(security_context_t con); --extern int getpidcon(int pid, security_context_t *con); --extern int getprevcon(security_context_t *con); --extern int getexeccon(security_context_t *con); --extern int setexeccon(security_context_t con); --extern int getfscreatecon(security_context_t *con); --extern int setfscreatecon(security_context_t context); --extern int getkeycreatecon(security_context_t *con); --extern int setkeycreatecon(security_context_t context); --extern int getsockcreatecon(security_context_t *con); --extern int setsockcreatecon(security_context_t context); --extern int getfilecon(const char *path, security_context_t *con); --extern int lgetfilecon(const char *path, security_context_t *con); --extern int fgetfilecon(int fd, security_context_t *con); --extern int setfilecon(const char *path, security_context_t con); --extern int lsetfilecon(const char *path, security_context_t con); --extern int fsetfilecon(int fd, security_context_t con); --extern int getpeercon(int fd, security_context_t *con); --extern int selinux_mkload_policy(int preservebools); --extern int selinux_init_load_policy(int *enforce); --extern int security_set_boolean_list(size_t boolcnt, -- SELboolean *boollist, -- int permanent); --extern int security_load_booleans(char *path); --extern int security_check_context(security_context_t con); --extern int security_canonicalize_context(security_context_t con, -- security_context_t *canoncon); --extern int security_getenforce(void); --extern int security_setenforce(int value); --extern int security_policyvers(void); --extern int security_get_boolean_names(char ***names, int *len); --extern int security_get_boolean_pending(const char *name); --extern int security_get_boolean_active(const char *name); --extern int security_set_boolean(const char *name, int value); --extern int security_commit_booleans(void); -- --/* Set flags controlling operation of matchpathcon_init or matchpathcon. */ --#define MATCHPATHCON_BASEONLY 1 /* Only process the base file_contexts file. */ --#define MATCHPATHCON_NOTRANS 2 /* Do not perform any context translation. */ --extern void set_matchpathcon_flags(unsigned int flags); --extern int matchpathcon_init(const char *path); --extern int matchpathcon(const char *path, -- mode_t mode, -- security_context_t *con); -- --extern int matchpathcon_init_prefix(const char *path, -- const char *prefix); --extern void matchpathcon_fini(void); -- -- --extern int matchmediacon(const char *media, -- security_context_t *con); -- --extern int selinux_getenforcemode(int *enforce); --extern const char *selinux_policy_root(void); --extern const char *selinux_binary_policy_path(void); --extern const char *selinux_failsafe_context_path(void); --extern const char *selinux_removable_context_path(void); --extern const char *selinux_default_context_path(void); --extern const char *selinux_user_contexts_path(void); --extern const char *selinux_file_context_path(void); --extern const char *selinux_file_context_homedir_path(void); --extern const char *selinux_file_context_local_path(void); --extern const char *selinux_homedir_context_path(void); --extern const char *selinux_media_context_path(void); --extern const char *selinux_contexts_path(void); --extern const char *selinux_securetty_types_path(void); --extern const char *selinux_booleans_path(void); --extern const char *selinux_customizable_types_path(void); --extern const char *selinux_users_path(void); --extern const char *selinux_usersconf_path(void); --extern const char *selinux_translations_path(void); --extern const char *selinux_netfilter_context_path(void); --extern const char *selinux_path(void); --#extern int selinux_check_passwd_access(access_vector_t requested); --#extern int checkPasswdAccess(access_vector_t requested); -- --extern int selinux_check_securetty_context(security_context_t tty_context); --void set_selinuxmnt(char *mnt); -- --#ifdef SWIGpython --// This tells SWIG to treat char ** as a special case --%typemap(in) char ** { -- /* Check if is a list */ -- if (PyList_Check($input)) { -- int size = PyList_Size($input); -- int i = 0; -- $1 = (char **) malloc((size+1)*sizeof(char *)); -- if ($1 == NULL) { -- PyErr_SetString(PyExc_MemoryError,"Out of memory"); -- return NULL; -- } -- for (i = 0; i < size; i++) { -- PyObject *o = PyList_GetItem($input,i); -- if (PyString_Check(o)) -- $1[i] = PyString_AsString(PyList_GetItem($input,i)); -- else { -- PyErr_SetString(PyExc_TypeError,"list must contain strings"); -- free($1); -- return NULL; -- } -- } -- $1[i] = 0; -- } else { -- PyErr_SetString(PyExc_TypeError,"not a list"); -- return NULL; -- } -+%typemap(freearg) (char ***names, int *len) { -+ int i; -+ if (*$1) { -+ for (i = 0; i < *$2; i++) { -+ free((*$1)[i]); -+ } -+ free(*$1); -+ } - } --#endif - --extern int rpm_execcon(unsigned int verified, -- const char *filename, -- char **, char **); -- --extern int is_context_customizable (security_context_t scontext); -- --extern int selinux_trans_to_raw_context(char *trans, -- security_context_t *rawp); --extern int selinux_raw_to_trans_context(char *raw, -- security_context_t *transp); -- --%typemap(in, numinputs=0) char **(char *temp=NULL) { -+%typemap(in, numinputs=0) (security_context_t **) (security_context_t *temp) { - $1 = &temp; - } - --%typemap(argout) char ** { -- $result = SWIG_Python_AppendOutput($result, PyString_FromString(*$1)); -+%typemap(freearg) (security_context_t **) { -+ if (*$1) freeconary(*$1); - } --extern int selinux_getpolicytype(char **enforce); --extern int getseuserbyname(const char *linuxuser, char **seuser, char **level); - --int selinux_file_context_cmp(const security_context_t a, const security_context_t b); --int selinux_file_context_verify(const char *path, mode_t mode); --int selinux_lsetfilecon_default(const char *path); -+/* Ignore functions that don't make sense when wrapped */ -+%ignore freecon; -+%ignore freeconary; -+ -+/* Ignore functions that take a function pointer as an argument */ -+%ignore set_matchpathcon_printf; -+%ignore set_matchpathcon_invalidcon; -+%ignore set_matchpathcon_canoncon; -+ -+%include "../include/selinux/selinux.h" -+%include "../include/selinux/get_default_type.h" -+%include "../include/selinux/get_context_list.h" -Index: libselinux/src/selinuxswig_python.i -=================================================================== ---- libselinux/src/selinuxswig_python.i (revision 0) -+++ libselinux/src/selinuxswig_python.i (revision 0) -@@ -0,0 +1,101 @@ -+/* Author: James Athey -+ * -+ * Copyright (C) 2007 Tresys Technology, LLC -+ * -+ * This library is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU Lesser General Public -+ * License as published by the Free Software Foundation; either -+ * version 2.1 of the License, or (at your option) any later version. -+ * -+ * This library is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ * Lesser General Public License for more details. -+ * -+ * You should have received a copy of the GNU Lesser General Public -+ * License along with this library; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ */ -+ -+%module selinux -+%{ -+ #include "selinux/selinux.h" -+%} -+ -+/* security_get_boolean_names() typemap */ -+%typemap(argout) (char ***names, int *len) { -+ PyObject* list = PyList_New(*$2); -+ int i; -+ for (i = 0; i < *$2; i++) { -+ PyList_SetItem(list, i, PyString_FromString((*$1)[i])); -+ } -+ $result = SWIG_Python_AppendOutput($result, list); -+} -+ -+/* Makes security_compute_user() return a Python list of contexts */ -+%typemap(argout) (security_context_t **con) { -+ PyObject* plist; -+ int i, len = 0; -+ -+ if (*$1) { -+ while((*$1)[len]) -+ len++; -+ plist = PyList_New(len); -+ for (i = 0; i < len; i++) { -+ PyList_SetItem(plist, i, PyString_FromString((*$1)[i])); -+ } -+ } else { -+ plist = PyList_New(0); -+ } -+ -+ $result = SWIG_Python_AppendOutput($result, plist); -+} -+ -+/* Makes functions in get_context_list.h return a Python list of contexts */ -+%typemap(argout) (security_context_t **list) { -+ PyObject* plist; -+ int i; -+ -+ if (*$1) { -+ plist = PyList_New(result); -+ for (i = 0; i < result; i++) { -+ PyList_SetItem(plist, i, PyString_FromString((*$1)[i])); -+ } -+ } else { -+ plist = PyList_New(0); -+ } -+ /* Only return the Python list, don't need to return the length anymore */ -+ $result = plist; -+} -+ -+%typemap(in,noblock=1,numinputs=0) security_context_t * (security_context_t temp = 0) { -+ $1 = &temp; -+} -+%typemap(freearg,match="in") security_context_t * ""; -+%typemap(argout,noblock=1) security_context_t * { -+ if (*$1) { -+ %append_output(SWIG_FromCharPtr(*$1)); -+ freecon(*$1); -+ } -+ else { -+ Py_INCREF(Py_None); -+ %append_output(Py_None); -+ } -+} -+ -+%typemap(in,noblock=1,numinputs=0) char ** (char * temp = 0) { -+ $1 = &temp; -+} -+%typemap(freearg,match="in") char ** ""; -+%typemap(argout,noblock=1) char ** { -+ if (*$1) { -+ %append_output(SWIG_FromCharPtr(*$1)); -+ free(*$1); -+ } -+ else { -+ Py_INCREF(Py_None); -+ %append_output(Py_None); -+ } -+} -+ -+%include "selinuxswig.i" ---- libselinux-2.0.21/src/fsetfilecon.c~ 2007-06-11 14:39:07.000000000 -0400 -+++ libselinux-2.0.21/src/fsetfilecon.c 2007-06-19 14:52:40.000000000 -0400 -@@ -13,7 +13,7 @@ int fsetfilecon_raw(int fd, security_con - 0); - } - --hidden_def(setfilecon_raw) -+hidden_def(fsetfilecon_raw) - - int fsetfilecon(int fd, security_context_t context) - { ---- libselinux-2.0.21/src/Makefile~ 2007-06-11 14:39:07.000000000 -0400 -+++ libselinux-2.0.21/src/Makefile 2007-06-19 15:49:43.000000000 -0400 -@@ -12,7 +12,7 @@ LIBVERSION = 1 - - LIBA=libselinux.a - TARGET=libselinux.so --SWIGIF= selinuxswig.i -+SWIGIF= selinuxswig_python.i - SWIGCOUT= selinuxswig_wrap.c - SWIGLOBJ:= $(patsubst %.c,%.lo,$(SWIGCOUT)) - SWIGSO=_selinux.so diff --git a/sources b/sources index 4e67dff..822ff4e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -34ba81b68ddf832a0a4272fe889050dc libselinux-2.1.11.tgz +71a3a6ade9be8b31567fa9437e00698d libselinux-2.1.12.tgz