diff --git a/.gitignore b/.gitignore index 0b90366..51678eb 100644 --- a/.gitignore +++ b/.gitignore @@ -192,3 +192,4 @@ libselinux-2.0.96.tgz /libselinux-2.1.8.tgz /libselinux-2.1.9.tgz /libselinux-2.1.10.tgz +/libselinux-2.1.11.tgz diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 3cd53d6..7f5eddb 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,17 +1,8 @@ diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h -index 1a54307..9ef10fc 100644 +index 8263f32..9ef10fc 100644 --- a/libselinux/include/selinux/label.h +++ b/libselinux/include/selinux/label.h -@@ -31,6 +31,8 @@ struct selabel_handle; - #define SELABEL_CTX_X 2 - /* db objects */ - #define SELABEL_CTX_DB 3 -+/* Android property service contexts */ -+#define SELABEL_CTX_ANDROID_PROP 4 - - /* - * Available options -@@ -46,8 +48,10 @@ struct selabel_handle; +@@ -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 @@ -24,7 +15,7 @@ index 1a54307..9ef10fc 100644 /* * Label operations diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index 6f483c9..2316252 100644 +index 6f483c9..84efe28 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -139,7 +139,10 @@ struct av_decision { @@ -55,9 +46,9 @@ index 6f483c9..2316252 100644 extern int selinux_getenforcemode(int *enforce); /* -+ selinux_boolean_sub reads the /etc/selinux/TYPE/booleans.subs_dist file ++ 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. ++ 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); @@ -66,15 +57,18 @@ index 6f483c9..2316252 100644 selinux_getpolicytype reads the /etc/selinux/config file and determines what the default policy for the machine is. Calling application must free policytype. -@@ -488,6 +504,7 @@ extern const char *selinux_policy_root(void); +@@ -488,7 +504,9 @@ extern const char *selinux_policy_root(void); /* These functions return the paths to specific files under the policy root directory. */ +-extern const char *selinux_binary_policy_path(void); +extern const char *selinux_current_policy_path(void); - extern const char *selinux_binary_policy_path(void); ++extern char *selinux_binary_policy_path(void); ++extern char *selinux_binary_policy_path_min_max(int min, int *max); extern const char *selinux_failsafe_context_path(void); extern const char *selinux_removable_context_path(void); -@@ -502,10 +519,12 @@ extern const char *selinux_homedir_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); @@ -180,11 +174,11 @@ index 8ead1a4..c68ace5 100644 .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..02d3ce2 +index 0000000..8d54c88 --- /dev/null +++ b/libselinux/man/man3/selinux_boolean_sub.3 @@ -0,0 +1,25 @@ -+.TH "selinux_boolean_subs" "3" "22 January 2011" "kaigai@ak.jp.nec.com" "SELinux API documentation" ++.TH "selinux_boolean_subs" "3" "11 June 2012" "dwalsh@redhat.com" "SELinux API documentation" +.SH "NAME" +selinux_boolean_subs +.SH "SYNOPSIS" @@ -193,98 +187,41 @@ index 0000000..02d3ce2 +.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 ++.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 ++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. ++.BR free "(3)." ++.BR selinux_boolean_subs ++returns NULL on error. +.SH "SEE ALSO" +security_get_boolean_names.3 -diff --git a/libselinux/src/.gitignore b/libselinux/src/.gitignore -index ff0c7c2..4dcc3b3 100644 ---- a/libselinux/src/.gitignore -+++ b/libselinux/src/.gitignore -@@ -1,3 +1,4 @@ - selinux.py - selinuxswig_wrap.c - selinuxswig_python_exception.i -+selinuxswig_ruby_wrap.c diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index d84033e..74e53bb 100644 +index b333f07..74e53bb 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile -@@ -3,6 +3,8 @@ - # targets with "PYPREFIX": - PYTHON ?= python - PYPREFIX ?= $(notdir $(PYTHON)) -+RUBY ?= ruby -+RUBYPREFIX ?= $(notdir $(RUBY)) - - # Installation directories. - PREFIX ?= $(DESTDIR)/usr -@@ -11,11 +13,10 @@ SHLIBDIR ?= $(DESTDIR)/lib +@@ -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 ?= -I$(LIBDIR)/ruby/$(RUBYLIBVER)/$(RUBYPLATFORM) -+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)) + 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)) -@@ -33,7 +34,7 @@ SWIGLOBJ:= $(patsubst %.c,$(PYPREFIX)%.lo,$(SWIGCOUT)) - SWIGRUBYLOBJ:= $(patsubst %.c,%.lo,$(SWIGRUBYCOUT)) - SWIGSO=$(PYPREFIX)_selinux.so - SWIGFILES=$(SWIGSO) selinux.py --SWIGRUBYSO=_rubyselinux.so -+SWIGRUBYSO=$(RUBYPREFIX)_selinux.so - LIBSO=$(TARGET).$(LIBVERSION) - AUDIT2WHYLOBJ=$(PYPREFIX)audit2why.lo - AUDIT2WHYSO=$(PYPREFIX)audit2why.so -@@ -55,7 +56,7 @@ MAX_STACK_SIZE=32768 - - OBJS= $(patsubst %.c,%.o,$(SRCS)) - LOBJS= $(patsubst %.c,%.lo,$(SRCS)) --CFLAGS ?= -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ -+CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ - -Wunused -Wunknown-pragmas -Wstrict-aliasing -Wshadow -Wpointer-arith \ - -Wbad-function-cast -Wcast-align -Wwrite-strings -Wlogical-op -Waggregate-return \ - -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ -@@ -75,6 +76,10 @@ CFLAGS ?= -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing- - -Werror -Wno-aggregate-return -Wno-redundant-decls - - override CFLAGS += -I../include -I$(INCLUDEDIR) -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 $(EMFLAGS) -+ -+SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ -+ -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations -+ - RANLIB=ranlib - - ARCH := $(patsubst i%86,i386,$(shell uname -m)) -@@ -93,16 +98,16 @@ pywrap: all $(SWIGSO) $(AUDIT2WHYSO) - rubywrap: all $(SWIGRUBYSO) - - $(SWIGLOBJ): $(SWIGCOUT) -- $(CC) $(filter-out -Werror, $(CFLAGS)) $(PYINC) -fPIC -DSHARED -c -o $@ $< -+ $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(PYINC) -fPIC -DSHARED -c -o $@ $< - - $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) -- $(CC) $(filter-out -Werror, $(CFLAGS)) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< -+ $(CC) $(CFLAGS) $(SWIG_CFLAGS) $(RUBYINC) -fPIC -DSHARED -c -o $@ $< +@@ -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) @@ -296,7 +233,7 @@ index d84033e..74e53bb 100644 $(LIBA): $(OBJS) $(AR) rcs $@ $^ -@@ -122,7 +127,7 @@ $(AUDIT2WHYLOBJ): audit2why.c +@@ -129,7 +127,7 @@ $(AUDIT2WHYLOBJ): audit2why.c $(CC) $(filter-out -Werror, $(CFLAGS)) $(PYINC) -fPIC -DSHARED -c -o $@ $< $(AUDIT2WHYSO): $(AUDIT2WHYLOBJ) @@ -305,17 +242,8 @@ index d84033e..74e53bb 100644 %.o: %.c policy.h $(CC) $(CFLAGS) $(TLSFLAGS) -c -o $@ $< -@@ -162,7 +167,7 @@ relabel: - /sbin/restorecon $(SHLIBDIR)/$(LIBSO) - - clean: -- -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(SWIGLOBJ) $(SWIGSO) $(TARGET) $(AUDIT2WHYSO) *.o *.lo *~ -+ -rm -f $(LIBPC) $(OBJS) $(LOBJS) $(LIBA) $(LIBSO) $(SWIGLOBJ) $(SWIGRUBYLOBJ) $(SWIGSO) $(TARGET) $(AUDIT2WHYSO) *.o *.lo *~ - - distclean: clean - rm -f $(GENERATED) $(SWIGFILES) diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c -index 1bf3599..f7750fc 100644 +index 02483a3..f7750fc 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c @@ -214,19 +214,12 @@ static int __policy_init(const char *init_path) @@ -342,22 +270,6 @@ index 1bf3599..f7750fc 100644 PyErr_SetString( PyExc_ValueError, errormsg); return 1; } -@@ -453,11 +446,11 @@ static struct PyModuleDef moduledef = { - NULL - }; - --PyMODINIT_FUNC --PyInit_audit2why(void) -+PyMODINIT_FUNC PyInit_audit2why(void); /* silence -Wmissing-prototypes */ -+PyMODINIT_FUNC PyInit_audit2why(void) - #else --PyMODINIT_FUNC --initaudit2why(void) -+PyMODINIT_FUNC initaudit2why(void); /* silence -Wmissing-prototypes */ -+PyMODINIT_FUNC initaudit2why(void) - #endif - { - PyObject *m; diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c index 802a07f..6ff83a7 100644 --- a/libselinux/src/avc.c @@ -370,23 +282,8 @@ index 802a07f..6ff83a7 100644 return rc; } -diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c -index be4c0a3..a07aa7f 100644 ---- a/libselinux/src/avc_internal.c -+++ b/libselinux/src/avc_internal.c -@@ -101,7 +101,9 @@ static int avc_netlink_receive(char *buf, unsigned buflen, int blocking) - socklen_t nladdrlen = sizeof nladdr; - struct nlmsghdr *nlh = (struct nlmsghdr *)buf; - -- rc = poll(&pfd, 1, (blocking ? -1 : 0)); -+ do { -+ rc = poll(&pfd, 1, (blocking ? -1 : 0)); -+ } while (rc < 0 && errno == EINTR); - - if (rc == 0 && !blocking) { - errno = EWOULDBLOCK; diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c -index 1510043..cbd936f 100644 +index 1510043..b5e6655 100644 --- a/libselinux/src/booleans.c +++ b/libselinux/src/booleans.c @@ -5,6 +5,7 @@ @@ -444,13 +341,13 @@ index 1510043..cbd936f 100644 + *ptr='\0'; + + sub = strdup(dst); -+ ++ + break; + } + free(line_buf); + fclose(cfg); +out: -+ if (!sub) ++ if (!sub) + sub = strdup(name); + return sub; +} @@ -602,6 +499,15 @@ index 1510043..cbd936f 100644 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 @@ -627,327 +533,6 @@ index 0b00156..d11c8dc 100644 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.c b/libselinux/src/label.c -index a9e0853..11f6e96 100644 ---- a/libselinux/src/label.c -+++ b/libselinux/src/label.c -@@ -24,6 +24,7 @@ static selabel_initfunc initfuncs[] = { - &selabel_media_init, - &selabel_x_init, - &selabel_db_init, -+ &selabel_property_init, - }; - - static void selabel_subs_fini(struct selabel_sub *ptr) -@@ -47,7 +48,8 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src) - if (strncmp(src, ptr->src, ptr->slen) == 0 ) { - if (src[ptr->slen] == '/' || - src[ptr->slen] == 0) { -- asprintf(&dst, "%s%s", ptr->dst, &src[ptr->slen]); -+ if (asprintf(&dst, "%s%s", ptr->dst, &src[ptr->slen]) < 0) -+ return NULL; - return dst; - } - } -diff --git a/libselinux/src/label_android_property.c b/libselinux/src/label_android_property.c -new file mode 100644 -index 0000000..79bf923 ---- /dev/null -+++ b/libselinux/src/label_android_property.c -@@ -0,0 +1,293 @@ -+/* -+ * Property Service contexts backend for labeling Android -+ * property keys -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include "callbacks.h" -+#include "label_internal.h" -+ -+/* A property security context specification. */ -+typedef struct spec { -+ struct selabel_lookup_rec lr; /* holds contexts for lookup result */ -+ char *property_key; /* property key string */ -+} spec_t; -+ -+/* Our stored configuration */ -+struct saved_data { -+ /* -+ * The array of specifications is sorted for longest -+ * prefix match -+ */ -+ spec_t *spec_arr; -+ unsigned int nspec; /* total number of specifications */ -+}; -+ -+static int cmp(const void *A, const void *B) -+{ -+ const struct spec *sp1 = A, *sp2 = B; -+ -+ if (strncmp(sp1->property_key, "*", 1) == 0) -+ return 1; -+ if (strncmp(sp2->property_key, "*", 1) == 0) -+ return -1; -+ -+ size_t L1 = strlen(sp1->property_key); -+ size_t L2 = strlen(sp2->property_key); -+ -+ return (L1 < L2) - (L1 > L2); -+} -+ -+/* -+ * Warn about duplicate specifications. -+ */ -+static int nodups_specs(struct saved_data *data, const char *path) -+{ -+ int rc = 0; -+ unsigned int ii, jj; -+ struct spec *curr_spec, *spec_arr = data->spec_arr; -+ -+ for (ii = 0; ii < data->nspec; ii++) { -+ curr_spec = &spec_arr[ii]; -+ for (jj = ii + 1; jj < data->nspec; jj++) { -+ if (!strcmp(spec_arr[jj].property_key, curr_spec->property_key)) { -+ rc = -1; -+ errno = EINVAL; -+ if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) { -+ selinux_log(SELINUX_ERROR, -+ "%s: Multiple different specifications for %s (%s and %s).\n", -+ path, -+ curr_spec->property_key, -+ spec_arr[jj].lr.ctx_raw, -+ curr_spec->lr.ctx_raw); -+ } else { -+ selinux_log(SELINUX_ERROR, -+ "%s: Multiple same specifications for %s.\n", -+ path, -+ curr_spec->property_key); -+ } -+ } -+ } -+ } -+ return rc; -+} -+ -+static int process_line(struct selabel_handle *rec, -+ const char *path, char *line_buf, -+ int pass, unsigned lineno) -+{ -+ int items, len; -+ char buf1[BUFSIZ], buf2[BUFSIZ]; -+ char *buf_p, *prop = buf1, *context = buf2; -+ struct saved_data *data = (struct saved_data *)rec->data; -+ spec_t *spec_arr = data->spec_arr; -+ unsigned int nspec = data->nspec; -+ -+ 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) -+ return 0; -+ items = sscanf(line_buf, "%255s %255s", prop, context); -+ if (items != 2) { -+ selinux_log(SELINUX_WARNING, -+ "%s: line %d is missing fields, skipping\n", path, -+ lineno); -+ return 0; -+ } -+ -+ if (pass == 1) { -+ /* On the second pass, process and store the specification in spec. */ -+ spec_arr[nspec].property_key = strdup(prop); -+ if (!spec_arr[nspec].property_key) { -+ selinux_log(SELINUX_WARNING, -+ "%s: out of memory at line %d on prop %s\n", -+ path, lineno, prop); -+ return -1; -+ -+ } -+ -+ spec_arr[nspec].lr.ctx_raw = strdup(context); -+ if (!spec_arr[nspec].lr.ctx_raw) { -+ selinux_log(SELINUX_WARNING, -+ "%s: out of memory at line %d on context %s\n", -+ path, lineno, context); -+ return -1; -+ } -+ } -+ -+ data->nspec = ++nspec; -+ return 0; -+} -+ -+static int init(struct selabel_handle *rec, struct selinux_opt *opts, -+ unsigned n) -+{ -+ struct saved_data *data = (struct saved_data *)rec->data; -+ const char *path = NULL; -+ FILE *fp; -+ char line_buf[BUFSIZ]; -+ unsigned int lineno = 0, maxnspec, pass; -+ int status = -1; -+ struct stat sb; -+ -+ /* Process arguments */ -+ while (n--) -+ switch (opts[n].type) { -+ case SELABEL_OPT_PATH: -+ path = opts[n].value; -+ break; -+ default: -+ selinux_log(SELINUX_WARNING, -+ "Argument type (%d) not recognized. Skipping\n", opts[n].type); -+ break; -+ } -+ -+ /* Open the specification file. */ -+ if ((fp = fopen(path, "r")) == NULL) -+ return -1; -+ -+ if (fstat(fileno(fp), &sb) < 0) -+ return -1; -+ if (!S_ISREG(sb.st_mode)) { -+ errno = EINVAL; -+ return -1; -+ } -+ -+ /* -+ * Two passes of the specification file. First is to get the size. -+ * After the first pass, the spec array is malloced to the appropriate -+ * size. Second pass is to populate the spec array and check for -+ * dups. -+ */ -+ maxnspec = UINT_MAX / sizeof(spec_t); -+ for (pass = 0; pass < 2; pass++) { -+ data->nspec = 0; -+ -+ while (fgets(line_buf, sizeof line_buf - 1, fp) -+ && data->nspec < maxnspec) { -+ if (process_line(rec, path, line_buf, pass, ++lineno) != 0) -+ goto finish; -+ } -+ -+ if (pass == 1) { -+ status = nodups_specs(data, path); -+ -+ if (status) -+ goto finish; -+ } -+ -+ if (pass == 0) { -+ -+ if (data->nspec == 0) { -+ status = 0; -+ goto finish; -+ } -+ -+ if (NULL == (data->spec_arr = -+ malloc(sizeof(spec_t) * data->nspec))) -+ goto finish; -+ -+ memset(data->spec_arr, 0, sizeof(spec_t) * data->nspec); -+ maxnspec = data->nspec; -+ rewind(fp); -+ } -+ } -+ -+ qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp); -+ -+ status = 0; -+finish: -+ fclose(fp); -+ return status; -+} -+ -+/* -+ * Backend interface routines -+ */ -+static void closef(struct selabel_handle *rec) -+{ -+ struct saved_data *data = (struct saved_data *)rec->data; -+ struct spec *spec; -+ unsigned int i; -+ -+ for (i = 0; i < data->nspec; i++) { -+ spec = &data->spec_arr[i]; -+ free(spec->property_key); -+ free(spec->lr.ctx_raw); -+ free(spec->lr.ctx_trans); -+ } -+ -+ if (data->spec_arr) -+ free(data->spec_arr); -+ -+ free(data); -+} -+ -+static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, -+ const char *key, -+ int __attribute__ ((unused)) type) -+{ -+ struct saved_data *data = (struct saved_data *)rec->data; -+ spec_t *spec_arr = data->spec_arr; -+ unsigned int i; -+ struct selabel_lookup_rec *ret = NULL; -+ -+ if (!data->nspec) { -+ errno = ENOENT; -+ goto finish; -+ } -+ -+ for (i = 0; i < data->nspec; i++) { -+ if (strncmp(spec_arr[i].property_key, key, -+ strlen(spec_arr[i].property_key)) == 0) { -+ break; -+ } -+ if (strncmp(spec_arr[i].property_key, "*", 1) == 0) -+ break; -+ } -+ -+ if (i >= data->nspec) { -+ /* No matching specification. */ -+ errno = ENOENT; -+ goto finish; -+ } -+ -+ ret = &spec_arr[i].lr; -+ -+finish: -+ return ret; -+} -+ -+static void stats(struct selabel_handle __attribute__ ((unused)) * rec) -+{ -+ selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n"); -+} -+ -+int selabel_property_init(struct selabel_handle *rec, struct selinux_opt *opts, -+ unsigned nopts) -+{ -+ struct saved_data *data; -+ -+ data = (struct saved_data *)malloc(sizeof(*data)); -+ if (!data) -+ return -1; -+ memset(data, 0, sizeof(*data)); -+ -+ rec->data = data; -+ rec->func_close = &closef; -+ rec->func_stats = &stats; -+ rec->func_lookup = &lookup; -+ -+ return init(rec, opts, nopts); -+} diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index 7bc46cc..82a608c 100644 --- a/libselinux/src/label_file.c @@ -1049,21 +634,114 @@ index 7bc46cc..82a608c 100644 if (status) goto finish; } -diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h -index 79d5495..435ecf2 100644 ---- a/libselinux/src/label_internal.h -+++ b/libselinux/src/label_internal.h -@@ -25,6 +25,8 @@ int selabel_x_init(struct selabel_handle *rec, struct selinux_opt *opts, - unsigned nopts) hidden; - int selabel_db_init(struct selabel_handle *rec, - struct selinux_opt *opts, unsigned nopts) hidden; -+int selabel_property_init(struct selabel_handle *rec, -+ struct selinux_opt *opts, unsigned nopts) hidden; +diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c +index 10e29b9..888dab5 100644 +--- a/libselinux/src/load_policy.c ++++ b/libselinux/src/load_policy.c +@@ -49,8 +49,9 @@ int load_setlocaldefs hidden = 1; + int selinux_mkload_policy(int preservebools) + { + int kernvers = security_policyvers(); +- int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers; ++ int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION; + int setlocaldefs = load_setlocaldefs; ++ char *pol_path = NULL; + char path[PATH_MAX]; + struct stat sb; + struct utsname uts; +@@ -162,29 +163,24 @@ checkbool: + maxvers = max(kernvers, maxvers); + } + +- vers = maxvers; +- search: +- snprintf(path, sizeof(path), "%s.%d", +- selinux_binary_policy_path(), vers); +- fd = open(path, O_RDONLY); +- while (fd < 0 && errno == ENOENT +- && --vers >= minvers) { +- /* Check prior versions to see if old policy is available */ +- snprintf(path, sizeof(path), "%s.%d", +- selinux_binary_policy_path(), vers); +- fd = open(path, O_RDONLY); ++search: ++ pol_path = selinux_binary_policy_path_min_max(minvers, &maxvers); ++ if (!pol_path) { ++ fprintf(stderr, "SELinux: unable to find usable policy file: %s\n", ++ strerror(errno)); ++ goto dlclose; + } ++ ++ fd = open(pol_path, O_RDONLY); + if (fd < 0) { +- fprintf(stderr, +- "SELinux: Could not open policy file <= %s.%d: %s\n", +- selinux_binary_policy_path(), maxvers, strerror(errno)); ++ fprintf(stderr, "SELinux: Could not open policy file %s: %s\n", ++ pol_path, strerror(errno)); + goto dlclose; + } + + if (fstat(fd, &sb) < 0) { +- fprintf(stderr, +- "SELinux: Could not stat policy file %s: %s\n", +- path, strerror(errno)); ++ fprintf(stderr, "SELinux: Could not stat policy file %s: %s\n", ++ pol_path, strerror(errno)); + goto close; + } + +@@ -195,13 +191,12 @@ checkbool: + size = sb.st_size; + data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); + if (map == MAP_FAILED) { +- fprintf(stderr, +- "SELinux: Could not map policy file %s: %s\n", +- path, strerror(errno)); ++ fprintf(stderr, "SELinux: Could not map policy file %s: %s\n", ++ pol_path, strerror(errno)); + goto close; + } + +- if (vers > kernvers && usesepol) { ++ if (maxvers > kernvers && usesepol) { + /* Need to downgrade to kernel-supported version. */ + if (policy_file_create(&pf)) + goto unmap; +@@ -220,12 +215,12 @@ checkbool: + /* Downgrade failed, keep searching. */ + fprintf(stderr, + "SELinux: Could not downgrade policy file %s, searching for an older version.\n", +- path); ++ pol_path); + policy_file_free(pf); + policydb_free(policydb); + munmap(map, sb.st_size); + close(fd); +- vers--; ++ maxvers--; + goto search; + } + policy_file_free(pf); +@@ -281,7 +276,7 @@ checkbool: + if (rc) + fprintf(stderr, + "SELinux: Could not load policy file %s: %s\n", +- path, strerror(errno)); ++ pol_path, strerror(errno)); + + unmap: + if (data != map) +@@ -296,6 +291,7 @@ checkbool: + if (libsepolh) + dlclose(libsepolh); + #endif ++ free(pol_path); + return rc; + } - /* - * Labeling internal structures diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c -index 8f200d4..6457e4a 100644 +index 2d7369e..eb292f2 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -2,6 +2,7 @@ @@ -1117,7 +795,7 @@ index 8f200d4..6457e4a 100644 hidden_def(matchpathcon_init_prefix) int matchpathcon_init(const char *path) -@@ -391,10 +399,13 @@ int realpath_not_final(const char *name, char *resolved_path) +@@ -397,10 +405,13 @@ int realpath_not_final(const char *name, char *resolved_path) goto out; } @@ -1136,7 +814,7 @@ index 8f200d4..6457e4a 100644 free(tmp_path); return rc; diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index f42cb7c..f544ac2 100644 +index f42cb7c..908fdfc 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -9,6 +9,7 @@ @@ -1152,14 +830,51 @@ index f42cb7c..f544ac2 100644 #define SEPGSQL_CONTEXTS 24 #define FILE_CONTEXT_SUBS_DIST 25 -#define NEL 26 -+#define BOOLEAN_SUBS 26 -+#define LXC_CONTEXTS 27 ++#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; -@@ -301,6 +304,29 @@ const char *selinux_binary_policy_path(void) +@@ -294,13 +297,63 @@ const char *selinux_removable_context_path(void) + hidden_def(selinux_removable_context_path) + +-const char *selinux_binary_policy_path(void) +-{ +- return get_path(BINPOLICY); ++char *selinux_binary_policy_path_min_max(int min, int *max) ++{ ++ int ret; ++ char *path = NULL; ++ ++ while(*max >= min) { ++ ret = asprintf(&path, "%s.%d", get_path(BINPOLICY), *max); ++ if (ret < 0) ++ goto err; ++ ret = access(path, R_OK); ++ if (!ret) ++ return path; ++ free(path); ++ path = NULL; ++ *max = *max - 1; ++ } ++err: ++ free(path); ++ return NULL; + } ++hidden_def(selinux_binary_policy_path_min_max) ++ ++char *selinux_binary_policy_path(void) ++{ ++ int max; ++ ++ max = security_policyvers(); ++ if (max < 0) ++ return NULL; + ++ return selinux_binary_policy_path_min_max(0, &max); ++} hidden_def(selinux_binary_policy_path) +const char *selinux_current_policy_path(void) @@ -1188,7 +903,7 @@ index f42cb7c..f544ac2 100644 const char *selinux_file_context_path(void) { return get_path(FILE_CONTEXTS); -@@ -418,6 +444,19 @@ const char *selinux_virtual_image_context_path(void) +@@ -418,6 +471,19 @@ const char *selinux_virtual_image_context_path(void) hidden_def(selinux_virtual_image_context_path) @@ -1209,13 +924,14 @@ index f42cb7c..f544ac2 100644 return get_path(FILE_CONTEXT_SUBS); } diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h -index 00df405..7c34b00 100644 +index 00df405..c47add9 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h -@@ -59,13 +59,17 @@ hidden_proto(selinux_mkload_policy) +@@ -59,13 +59,18 @@ hidden_proto(selinux_mkload_policy) hidden_proto(security_getenforce) hidden_proto(security_setenforce) hidden_proto(security_deny_unknown) ++ hidden_proto(selinux_binary_policy_path_min_max) + hidden_proto(selinux_boolean_sub) hidden_proto(selinux_binary_policy_path) + hidden_proto(selinux_booleans_subs_path) @@ -1230,7 +946,7 @@ index 00df405..7c34b00 100644 hidden_proto(selinux_file_context_path) hidden_proto(selinux_file_context_homedir_path) hidden_proto(selinux_file_context_local_path) -@@ -82,6 +86,7 @@ hidden_proto(selinux_mkload_policy) +@@ -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) @@ -1239,14 +955,15 @@ index 00df405..7c34b00 100644 hidden_proto(selinux_users_path) hidden_proto(selinux_usersconf_path); diff --git a/libselinux/src/seusers.c b/libselinux/src/seusers.c -index 5cdf6c0..b525fba 100644 +index 73ad42c..569fa43 100644 --- a/libselinux/src/seusers.c +++ b/libselinux/src/seusers.c -@@ -279,11 +279,18 @@ int getseuser(const char *username, const char *service, +@@ -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) { - ++lineno; - - if (strncmp(buffer, "*:", 2) == 0) { ++ + if (!service) { + rec = strdup(buffer); + break; @@ -1258,23 +975,32 @@ index 5cdf6c0..b525fba 100644 rec = strdup(buffer); continue; } +- if (!service) +- continue; + len = strlen(service); if ((strncmp(buffer, service, len) == 0) && (buffer[len] == ':')) { -diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile -index d76ccfa..5f3e047 100644 ---- a/libselinux/utils/Makefile -+++ b/libselinux/utils/Makefile -@@ -5,7 +5,7 @@ USRBINDIR ?= $(PREFIX)/sbin - SBINDIR ?= $(DESTDIR)/sbin +@@ -298,6 +304,7 @@ int getseuser(const char *username, const char *service, - MAX_STACK_SIZE=8192 --CFLAGS ?= -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ -+CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissing-include-dirs \ - -Wunused -Wunknown-pragmas -Wstrict-aliasing -Wshadow -Wpointer-arith \ - -Wbad-function-cast -Wcast-align -Wwrite-strings -Wlogical-op -Waggregate-return \ - -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes \ + 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 @@ -1350,7 +1076,7 @@ index 3a90449..9ae9243 100644 out: diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c -index b1adadd..e8e6ed5 100644 +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) @@ -1364,11 +1090,10 @@ index b1adadd..e8e6ed5 100644 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]); @@ -1463,7 +1188,7 @@ index b1adadd..e8e6ed5 100644 + if (! force_mode) { + if (lstat(path, &buf) == 0) + mode = buf.st_mode; -+ } else ++ } else + mode = force_mode; if (verify) { diff --git a/libselinux.spec b/libselinux.spec index 5e5c9bd..1360d16 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -7,8 +7,8 @@ Summary: SELinux library and simple utilities Name: libselinux -Version: 2.1.10 -Release: 5%{?dist} +Version: 2.1.11 +Release: 1%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -233,6 +233,20 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Wed Jul 4 2012 Dan Walsh - 2.1.11-1 +- Update to upstream + * Fortify source now requires all code to be compiled with -O flag + * asprintf return code must be checked + * avc_netlink_recieve handle EINTR + * audit2why: silence -Wmissing-prototypes warning + * libsemanage: remove build warning when build swig c files + * matchpathcon: bad handling of symlinks in / + * seusers: remove unused lineno + * seusers: getseuser: gracefully handle NULL service + * New Android property labeling backend + * label_android_property whitespace cleanups + * additional makefile support for rubywrap + * Mon Jun 11 2012 Dan Walsh - 2.1.10-5 - Fix booleans.subs name, change function name to selinux_boolean_sub, add man page, minor fixes to the function diff --git a/sources b/sources index b9583e9..4e67dff 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -f3dedbef7c54f19d49c2e7e8bdcaf7ed libselinux-2.1.10.tgz +34ba81b68ddf832a0a4272fe889050dc libselinux-2.1.11.tgz