From d9f6251b10c5cac5fe02b58cb75b552a1a1566bc Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Jun 11 2012 17:31:23 +0000 Subject: Fix booleans.subs name, change function name to selinux_boolean_sub, add man page, minor fixes to the function --- diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index e25c8f2..3cd53d6 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,8 +1,17 @@ diff --git a/libselinux/include/selinux/label.h b/libselinux/include/selinux/label.h -index 1a54307..f6eeb21 100644 +index 1a54307..9ef10fc 100644 --- a/libselinux/include/selinux/label.h +++ b/libselinux/include/selinux/label.h -@@ -46,8 +46,10 @@ struct selabel_handle; +@@ -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; #define SELABEL_OPT_PATH 3 /* select a subset of the search space as an optimization (file backend) */ #define SELABEL_OPT_SUBSET 4 @@ -15,7 +24,7 @@ index 1a54307..f6eeb21 100644 /* * Label operations diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index 6f483c9..9756ac9 100644 +index 6f483c9..2316252 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -139,7 +139,10 @@ struct av_decision { @@ -42,7 +51,22 @@ index 6f483c9..9756ac9 100644 /* Free the memory allocated by matchpathcon_init. */ extern void matchpathcon_fini(void); -@@ -488,6 +496,7 @@ extern const char *selinux_policy_root(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,6 +504,7 @@ extern const char *selinux_policy_root(void); /* These functions return the paths to specific files under the policy root directory. */ @@ -50,7 +74,7 @@ index 6f483c9..9756ac9 100644 extern const char *selinux_binary_policy_path(void); extern const char *selinux_failsafe_context_path(void); extern const char *selinux_removable_context_path(void); -@@ -502,10 +511,12 @@ extern const char *selinux_homedir_context_path(void); +@@ -502,10 +519,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); @@ -154,11 +178,84 @@ 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..02d3ce2 +--- /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" ++.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/.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..1c2270c 100644 +index d84033e..74e53bb 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile -@@ -55,7 +55,7 @@ MAX_STACK_SIZE=32768 +@@ -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 + 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)) + 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)) @@ -167,8 +264,58 @@ index d84033e..1c2270c 100644 -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 $@ $< + + $(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 $@ $^ +@@ -122,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 $@ $< +@@ -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..f621de7 100644 +index 1bf3599..f7750fc 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c @@ -214,19 +214,12 @@ static int __policy_init(const char *init_path) @@ -195,6 +342,22 @@ index 1bf3599..f621de7 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 @@ -223,165 +386,182 @@ index be4c0a3..a07aa7f 100644 if (rc == 0 && !blocking) { errno = EWOULDBLOCK; diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c -index 1510043..bf526c0 100644 +index 1510043..cbd936f 100644 --- a/libselinux/src/booleans.c +++ b/libselinux/src/booleans.c -@@ -86,45 +86,131 @@ int security_get_boolean_names(char ***names, int *len) +@@ -5,6 +5,7 @@ + * Dan Walsh - Added security_load_booleans(). + */ + ++#include + #include + #include + #include +@@ -86,44 +87,145 @@ int security_get_boolean_names(char ***names, int *len) } hidden_def(security_get_boolean_names) --#define STRBUF_SIZE 3 --static int get_bool_value(const char *name, char **buf) + -+static char * bool_sub(const char *name) - { -- int fd, len; ++char *selinux_boolean_sub(const char *name) ++{ + char *sub = NULL; + char *line_buf = NULL; -+ size_t line_len = 0; ++ size_t line_len; + FILE *cfg; + -+ if (!name) ++ if (!name) + return NULL; + + cfg = fopen(selinux_booleans_subs_path(), "r"); -+ + if (!cfg) -+ return NULL; ++ goto out; + -+ while (getline(&line_buf, &line_len, cfg)) { -+ char *ptr = NULL; ++ while (getline(&line_buf, &line_len, cfg) > -1) { ++ char *ptr; + char *src = line_buf; -+ char *dst = NULL; -+ ++ char *dst; + while (*src && isspace(*src)) + src++; -+ if (src[0] == '#') continue; ++ if (!*src) ++ continue; ++ if (src[0] == '#') ++ continue; + ptr = src; -+ while (*ptr && ! isspace(*ptr)) ++ while (*ptr && !isspace(*ptr)) + ptr++; + *ptr++ = '\0'; -+ if (! *src || (strcmp(src, name) != 0)) ++ if (strcmp(src, name) != 0) + continue; + + dst = ptr; + while (*dst && isspace(*dst)) + dst++; ++ if (!*dst) ++ continue; + ptr=dst; -+ while (*ptr && ! isspace(*ptr)) ++ while (*ptr && !isspace(*ptr)) + ptr++; + *ptr='\0'; -+ if (! *dst) -+ continue; + + sub = strdup(dst); ++ + break; + } -+ + 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 *fname = NULL; + char *alt_name = NULL; + int len; + int fd = -1; ++ int ret; + char *ptr; - -- if (!selinux_mnt) { -- errno = ENOENT; -- return -1; ++ + if (!name) { + errno = EINVAL; -+ return fd; - } - -- *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1)); -- if (!*buf) -- goto out; -- (*buf)[STRBUF_SIZE] = 0; -- - len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); - fname = (char *)malloc(sizeof(char) * len); - if (!fname) -- goto out; -+ return fd; ++ return -1; ++ } ++ ++ /* note the 'sizeof' gets us enough room for the '\0' */ ++ len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); ++ fname = malloc(sizeof(char) * len); ++ if (!fname) ++ return -1; ++ ++ ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); ++ if (ret < 0) ++ goto out; ++ assert(ret < len); + - snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); - -- fd = open(fname, O_RDONLY); -- if (fd < 0) + fd = open(fname, flag); -+ if (fd >= 0 || errno != ENOENT) - goto out; - -- len = read(fd, *buf, STRBUF_SIZE); -- close(fd); -- if (len != STRBUF_SIZE) -+ alt_name = bool_sub(name); -+ if (! alt_name) - goto out; - ++ if (fd >= 0 || errno != ENOENT) ++ goto out; ++ ++ alt_name = selinux_boolean_sub(name); ++ if (!alt_name) ++ goto out; ++ ++ /* note the 'sizeof' gets us enough room for the '\0' */ + len = strlen(alt_name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); + ptr = realloc(fname, len); -+ if (!ptr) ++ if (!ptr) + goto out; -+ + fname = ptr; -+ snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); -+ fd = open(fname, flag); + ++ ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); ++ if (ret < 0) ++ goto out; ++ assert(ret < len); ++ ++ fd = open(fname, flag); +out: - free(fname); -- return 0; ++ free(fname); + free(alt_name); + + return fd; +} + -+#define STRBUF_SIZE 3 -+static int get_bool_value(const char *name, char **buf) -+{ -+ int fd, len; -+ int rc = -1; -+ char *bool_buf = NULL; -+ if (!selinux_mnt) { -+ errno = ENOENT; + #define STRBUF_SIZE 3 + static int get_bool_value(const char *name, char **buf) + { + int fd, len; +- char *fname = NULL; ++ int errno_tmp; + + if (!selinux_mnt) { + errno = ENOENT; + return -1; + } + +- *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1)); ++ *buf = malloc(sizeof(char) * (STRBUF_SIZE + 1)); + if (!*buf) +- goto out; +- (*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) -+ return -1; -+ -+ bool_buf = malloc(sizeof(char) * (STRBUF_SIZE + 1)); -+ if (!bool_buf) -+ goto out; -+ bool_buf[STRBUF_SIZE] = 0; -+ -+ len = read(fd, bool_buf, STRBUF_SIZE); -+ if (len != STRBUF_SIZE) -+ goto out; -+ rc = 0; - out: + 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); -- return -1; -+ close(fd); -+ if (!rc) { -+ *buf = bool_buf; -+ } else { -+ free(bool_buf); -+ } -+ return rc; ++out_err: ++ free(*buf); + return -1; } - int security_get_boolean_pending(const char *name) -@@ -164,8 +250,8 @@ hidden_def(security_get_boolean_active) +@@ -164,8 +266,8 @@ hidden_def(security_get_boolean_active) int security_set_boolean(const char *name, int value) { @@ -392,7 +572,7 @@ index 1510043..bf526c0 100644 if (!selinux_mnt) { errno = ENOENT; -@@ -176,17 +262,9 @@ int security_set_boolean(const char *name, int value) +@@ -176,17 +278,9 @@ int security_set_boolean(const char *name, int value) return -1; } @@ -400,7 +580,7 @@ index 1510043..bf526c0 100644 - fname = (char *)malloc(sizeof(char) * len); - if (!fname) + fd = bool_open(name, O_WRONLY); -+ if (fd < 0) ++ if (fd < 0) return -1; - snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); - @@ -412,7 +592,7 @@ index 1510043..bf526c0 100644 if (value) buf[0] = '1'; -@@ -196,8 +274,7 @@ int security_set_boolean(const char *name, int value) +@@ -196,8 +290,7 @@ int security_set_boolean(const char *name, int value) ret = write(fd, buf, 2); close(fd); @@ -435,7 +615,7 @@ index b245364..7c47222 100644 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..825f295 100644 +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") @@ -446,12 +626,20 @@ index 0b00156..825f295 100644 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.c b/libselinux/src/label.c -index a9e0853..89e28f1 100644 +index a9e0853..11f6e96 100644 --- a/libselinux/src/label.c +++ b/libselinux/src/label.c -@@ -47,7 +47,8 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src) +@@ -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) { @@ -461,6 +649,305 @@ index a9e0853..89e28f1 100644 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 @@ -562,6 +1049,19 @@ 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; + + /* + * Labeling internal structures diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 8f200d4..6457e4a 100644 --- a/libselinux/src/matchpathcon.c @@ -709,12 +1209,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..8a935d0 100644 +index 00df405..7c34b00 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h -@@ -60,12 +60,15 @@ hidden_proto(selinux_mkload_policy) +@@ -59,13 +59,17 @@ hidden_proto(selinux_mkload_policy) + hidden_proto(security_getenforce) hidden_proto(security_setenforce) hidden_proto(security_deny_unknown) ++ hidden_proto(selinux_boolean_sub) hidden_proto(selinux_binary_policy_path) + hidden_proto(selinux_booleans_subs_path) + hidden_proto(selinux_current_policy_path) @@ -728,7 +1230,7 @@ index 00df405..8a935d0 100644 hidden_proto(selinux_file_context_path) hidden_proto(selinux_file_context_homedir_path) hidden_proto(selinux_file_context_local_path) -@@ -82,6 +85,7 @@ hidden_proto(selinux_mkload_policy) +@@ -82,6 +86,7 @@ hidden_proto(selinux_mkload_policy) hidden_proto(selinux_path) hidden_proto(selinux_check_passwd_access) hidden_proto(selinux_check_securetty_context) @@ -736,6 +1238,30 @@ index 00df405..8a935d0 100644 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 5cdf6c0..b525fba 100644 +--- a/libselinux/src/seusers.c ++++ b/libselinux/src/seusers.c +@@ -279,11 +279,18 @@ int getseuser(const char *username, const char *service, + while (getline(&buffer, &size, fp) > 0) { + ++lineno; + +- if (strncmp(buffer, "*:", 2) == 0) { ++ if (!service) { ++ rec = strdup(buffer); ++ break; ++ } ++ ++ if (strncmp(buffer, "*:", 2) == 0) ++ { + free(rec); + rec = strdup(buffer); + 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 @@ -749,3 +1275,196 @@ index d76ccfa..5f3e047 100644 -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 \ +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); + 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); + } else { +- printf("%s", usercon); ++ printf("%s\n", usercon); + } + } + +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; ++ } ++ + 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..e8e6ed5 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); ++ } ++ } else { ++ if (file) { ++ if (matchpathcon_init(file)) { ++ fprintf(stderr, ++ "Error inwhile processing %s: %s\n", ++ file, ++ errno ? strerror(errno) : "invalid"); ++ exit(1); ++ } ++ } ++ } ++ + 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); diff --git a/libselinux.spec b/libselinux.spec index f4eff71..5e5c9bd 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -8,7 +8,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.1.10 -Release: 4%{?dist} +Release: 5%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -233,6 +233,10 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* 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 + * Fri May 25 2012 Dan Walsh - 2.1.10-4 - Fix to compile with Fortify source * Add -O compiler flag