From 7a524ea43e38d73c6b071601071d12beb19f0522 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Fri, 4 Oct 2013 10:18:18 -0400 Subject: [PATCH] Add systemd_contexts support - Do substitutions on a local sub followed by a dist sub --- libselinux-rhat.patch | 289 +++++++++++++++++++++++++++++++++++++++--- libselinux.spec | 10 +- 2 files changed, 281 insertions(+), 18 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 56fbf36..8ca2b1c 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,5 +1,5 @@ diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index a4079aa..0b122af 100644 +index a4079aa..52d6700 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -177,6 +177,7 @@ extern void selinux_set_callback(int type, union selinux_callback cb); @@ -26,6 +26,14 @@ index a4079aa..0b122af 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); +@@ -515,6 +523,7 @@ 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_systemd_contexts_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); diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3 index c6837fc..de62d26 100644 --- a/libselinux/man/man3/security_compute_av.3 @@ -508,7 +516,7 @@ index 948aff1..598dc94 100644 togglesebool \- flip the current value of a SELinux boolean . diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index c4f5d4c..8f557a1 100644 +index c4f5d4c..310177b 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile @@ -18,9 +18,7 @@ RUBYLIBVER ?= $(shell $(RUBY) -e 'print RUBY_VERSION.split(".")[0..1].join(".")' @@ -527,7 +535,7 @@ index c4f5d4c..8f557a1 100644 $(LIBSO): $(LOBJS) - $(CC) $(CFLAGS) -shared -o $@ $^ -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro -+ $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -lpthread -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro ++ $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro ln -sf $@ $(TARGET) $(LIBPC): $(LIBPC).in ../VERSION @@ -705,6 +713,44 @@ index 802a07f..6ff83a7 100644 return rc; } +diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h +index d11c8dc..3c92424 100644 +--- a/libselinux/src/file_path_suffixes.h ++++ b/libselinux/src/file_path_suffixes.h +@@ -23,6 +23,7 @@ S_(BINPOLICY, "/policy/policy") + S_(VIRTUAL_DOMAIN, "/contexts/virtual_domain_context") + S_(VIRTUAL_IMAGE, "/contexts/virtual_image_context") + S_(LXC_CONTEXTS, "/contexts/lxc_contexts") ++ S_(SYSTEMD_CONTEXTS, "/contexts/systemd_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") +diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c +index 309105c..0e9278e 100644 +--- a/libselinux/src/fsetfilecon.c ++++ b/libselinux/src/fsetfilecon.c +@@ -9,8 +9,20 @@ + + int fsetfilecon_raw(int fd, const security_context_t context) + { +- return fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, ++ int rc = fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, + 0); ++ if (rc < 0 && errno == ENOTSUP) { ++ security_context_t ccontext = NULL; ++ int err = errno; ++ if ((fgetfilecon_raw(fd, &ccontext) >= 0) && ++ (strcmp(context,ccontext) == 0)) { ++ rc = 0; ++ } else { ++ errno = err; ++ } ++ freecon(ccontext); ++ } ++ return rc; + } + + hidden_def(fsetfilecon_raw) diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c index b9e8002..1d91123 100644 --- a/libselinux/src/get_context_list.c @@ -793,7 +839,7 @@ index b9e8002..1d91123 100644 hidden_def(get_ordered_context_list) diff --git a/libselinux/src/label.c b/libselinux/src/label.c -index 11f6e96..f5cb52a 100644 +index 11f6e96..b6b3639 100644 --- a/libselinux/src/label.c +++ b/libselinux/src/label.c @@ -43,12 +43,18 @@ static void selabel_subs_fini(struct selabel_sub *ptr) @@ -816,10 +862,68 @@ index 11f6e96..f5cb52a 100644 return NULL; return dst; } +@@ -58,7 +64,7 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src) + return NULL; + } + +-struct selabel_sub *selabel_subs_init(const char *path,struct selabel_sub *list) ++struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list) + { + char buf[1024]; + FILE *cfg = fopen(path, "r"); +@@ -171,6 +177,7 @@ struct selabel_handle *selabel_open(unsigned int backend, + rec->validating = selabel_is_validate_set(opts, nopts); + + rec->subs = NULL; ++ rec->dist_subs = NULL; + + if ((*initfuncs[backend])(rec, opts, nopts)) { + free(rec); +@@ -186,13 +193,24 @@ selabel_lookup_common(struct selabel_handle *rec, int translating, + const char *key, int type) + { + struct selabel_lookup_rec *lr; ++ char *ptr = NULL; ++ char *dptr = NULL; + + if (key == NULL) { + errno = EINVAL; + return NULL; + } + +- char *ptr = selabel_sub(rec->subs, key); ++ ptr = selabel_sub(rec->subs, key); ++ if (ptr) { ++ dptr = selabel_sub(rec->dist_subs, ptr); ++ if (dptr) { ++ free(ptr); ++ ptr = dptr; ++ } ++ } else { ++ ptr = selabel_sub(rec->dist_subs, key); ++ } + if (ptr) { + lr = rec->func_lookup(rec, ptr, type); + free(ptr); diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c -index 5f697f3..9b0d6b0 100644 +index 5f697f3..c424a21 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c +@@ -496,12 +496,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts, + + /* Process local and distribution substitution files */ + if (!path) { +- rec->subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->subs); ++ rec->dist_subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->dist_subs); + rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs); + path = selinux_file_context_path(); + } else { + snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path); +- rec->subs = selabel_subs_init(subs_file, rec->subs); ++ rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs); + snprintf(subs_file, sizeof(subs_file), "%s.subs", path); + rec->subs = selabel_subs_init(subs_file, rec->subs); + } @@ -649,6 +649,8 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, break; } else if (rc == PCRE_ERROR_NOMATCH) @@ -837,6 +941,44 @@ index 5f697f3..9b0d6b0 100644 ret = &spec_arr[i].lr; finish: +diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h +index 435ecf2..b6ae140 100644 +--- a/libselinux/src/label_internal.h ++++ b/libselinux/src/label_internal.h +@@ -68,6 +68,7 @@ struct selabel_handle { + char *spec_file; + + /* substitution support */ ++ struct selabel_sub *dist_subs; + struct selabel_sub *subs; + }; + +diff --git a/libselinux/src/lsetfilecon.c b/libselinux/src/lsetfilecon.c +index 461e3f7..ab85155 100644 +--- a/libselinux/src/lsetfilecon.c ++++ b/libselinux/src/lsetfilecon.c +@@ -9,8 +9,20 @@ + + int lsetfilecon_raw(const char *path, const security_context_t context) + { +- return lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, ++ int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, + 0); ++ if (rc < 0 && errno == ENOTSUP) { ++ security_context_t ccontext = NULL; ++ int err = errno; ++ if ((lgetfilecon_raw(path, &ccontext) >= 0) && ++ (strcmp(context,ccontext) == 0)) { ++ rc = 0; ++ } else { ++ errno = err; ++ } ++ freecon(ccontext); ++ } ++ return rc; + } + + hidden_def(lsetfilecon_raw) diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 2d7369e..2a00807 100644 --- a/libselinux/src/matchpathcon.c @@ -859,10 +1001,10 @@ index 2d7369e..2a00807 100644 } diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c -index 6c5b45a..f6b896e 100644 +index 6c5b45a..ecaccc6 100644 --- a/libselinux/src/procattr.c +++ b/libselinux/src/procattr.c -@@ -9,13 +9,15 @@ +@@ -9,19 +9,30 @@ #include "selinux_internal.h" #include "policy.h" @@ -883,7 +1025,22 @@ index 6c5b45a..f6b896e 100644 static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; -@@ -29,11 +31,16 @@ static pid_t gettid(void) + static int destructor_key_initialized = 0; + static __thread char destructor_initialized; + ++extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden"))); ++extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *); ++ ++static int __selinux_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)) ++{ ++ return __register_atfork (prepare, parent, child, ++ &__dso_handle == NULL ? NULL : __dso_handle); ++} ++ + static pid_t gettid(void) + { + return syscall(__NR_gettid); +@@ -29,11 +40,16 @@ static pid_t gettid(void) static void procattr_thread_destructor(void __attribute__((unused)) *unused) { @@ -905,7 +1062,7 @@ index 6c5b45a..f6b896e 100644 } static void free_procattr(void) -@@ -41,7 +48,7 @@ static void free_procattr(void) +@@ -41,7 +57,7 @@ static void free_procattr(void) procattr_thread_destructor(NULL); tid = 0; cpid = getpid(); @@ -914,7 +1071,16 @@ index 6c5b45a..f6b896e 100644 } void __attribute__((destructor)) procattr_destructor(void); -@@ -131,7 +138,7 @@ static int getprocattrcon_raw(security_context_t * context, +@@ -63,7 +79,7 @@ static inline void init_thread_destructor(void) + static void init_procattr(void) + { + if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) { +- pthread_atfork(NULL, NULL, free_procattr); ++ __selinux_atfork(NULL, NULL, free_procattr); + destructor_key_initialized = 1; + } + } +@@ -131,7 +147,7 @@ static int getprocattrcon_raw(security_context_t * context, return -1; }; @@ -923,7 +1089,7 @@ index 6c5b45a..f6b896e 100644 *context = strdup(prev_context); if (!(*context)) { return -1; -@@ -230,7 +237,8 @@ static int setprocattrcon_raw(security_context_t context, +@@ -230,7 +246,8 @@ static int setprocattrcon_raw(security_context_t context, if (!context && !*prev_context) return 0; @@ -933,7 +1099,7 @@ index 6c5b45a..f6b896e 100644 return 0; fd = openattr(pid, attr, O_RDWR); -@@ -257,6 +265,8 @@ out: +@@ -257,6 +274,8 @@ out: free(context); return -1; } else { @@ -943,7 +1109,7 @@ index 6c5b45a..f6b896e 100644 return 0; } diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index 296f357..9aee32f 100644 +index 296f357..2cd6d54 100644 --- a/libselinux/src/selinux_config.c +++ b/libselinux/src/selinux_config.c @@ -8,6 +8,8 @@ @@ -955,7 +1121,17 @@ index 296f357..9aee32f 100644 #include "selinux_internal.h" #include "get_default_type_internal.h" -@@ -138,6 +140,13 @@ int selinux_getpolicytype(char **type) +@@ -48,7 +50,8 @@ + #define FILE_CONTEXT_SUBS_DIST 25 + #define LXC_CONTEXTS 26 + #define BOOLEAN_SUBS 27 +-#define NEL 28 ++#define SYSTEMD_CONTEXTS 28 ++#define NEL 29 + + /* Part of one-time lazy init */ + static pthread_once_t once = PTHREAD_ONCE_INIT; +@@ -138,6 +141,13 @@ int selinux_getpolicytype(char **type) hidden_def(selinux_getpolicytype) @@ -969,7 +1145,7 @@ index 296f357..9aee32f 100644 static char *selinux_policyroot = NULL; static const char *selinux_rootpath = SELINUXDIR; -@@ -261,6 +270,37 @@ const char *selinux_policy_root(void) +@@ -261,6 +271,37 @@ const char *selinux_policy_root(void) return selinux_policyroot; } @@ -1007,7 +1183,7 @@ index 296f357..9aee32f 100644 const char *selinux_path(void) { return selinux_rootpath; -@@ -303,6 +343,31 @@ const char *selinux_binary_policy_path(void) +@@ -303,6 +344,31 @@ const char *selinux_binary_policy_path(void) hidden_def(selinux_binary_policy_path) @@ -1039,8 +1215,22 @@ index 296f357..9aee32f 100644 const char *selinux_file_context_path(void) { return get_path(FILE_CONTEXTS); +@@ -427,6 +493,13 @@ const char *selinux_lxc_contexts_path(void) + + hidden_def(selinux_lxc_contexts_path) + ++const char *selinux_systemd_contexts_path(void) ++{ ++ return get_path(SYSTEMD_CONTEXTS); ++} ++ ++hidden_def(selinux_systemd_contexts_path) ++ + const char * selinux_booleans_subs_path(void) { + return get_path(BOOLEAN_SUBS); + } diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h -index 2c7c85c..4a4aebc 100644 +index 2c7c85c..afb2170 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy) @@ -1051,6 +1241,14 @@ index 2c7c85c..4a4aebc 100644 hidden_proto(selinux_binary_policy_path) hidden_proto(selinux_booleans_subs_path) hidden_proto(selinux_default_context_path) +@@ -82,6 +83,7 @@ hidden_proto(selinux_mkload_policy) + hidden_proto(selinux_media_context_path) + hidden_proto(selinux_x_context_path) + hidden_proto(selinux_sepgsql_context_path) ++ hidden_proto(selinux_systemd_contexts_path) + hidden_proto(selinux_path) + hidden_proto(selinux_check_passwd_access) + hidden_proto(selinux_check_securetty_context) diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i index 359bd02..9884454 100644 --- a/libselinux/src/selinuxswig_python.i @@ -1077,6 +1275,63 @@ index 359bd02..9884454 100644 /* Makes security_compute_user() return a Python list of contexts */ %typemap(argout) (security_context_t **con) { PyObject* plist; +diff --git a/libselinux/src/setfilecon.c b/libselinux/src/setfilecon.c +index 7465c6a..9aaaa4b 100644 +--- a/libselinux/src/setfilecon.c ++++ b/libselinux/src/setfilecon.c +@@ -9,8 +9,20 @@ + + int setfilecon_raw(const char *path, const security_context_t context) + { +- return setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, ++ int rc = setxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, + 0); ++ if (rc < 0 && errno == ENOTSUP) { ++ security_context_t ccontext = NULL; ++ int err = errno; ++ if ((getfilecon_raw(path, &ccontext) >= 0) && ++ (strcmp(context,ccontext) == 0)) { ++ rc = 0; ++ } else { ++ errno = err; ++ } ++ freecon(ccontext); ++ } ++ return rc; + } + + hidden_def(setfilecon_raw) +diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c +index f9065bd..4ab7c2a 100644 +--- a/libselinux/src/setrans_client.c ++++ b/libselinux/src/setrans_client.c +@@ -249,12 +249,12 @@ out: + + static void setrans_thread_destructor(void __attribute__((unused)) *unused) + { +- free(prev_t2r_trans); +- free(prev_t2r_raw); +- free(prev_r2t_trans); +- free(prev_r2t_raw); +- free(prev_r2c_trans); +- free(prev_r2c_raw); ++ free(prev_t2r_trans); prev_t2r_trans = NULL; ++ free(prev_t2r_raw); prev_t2r_raw = NULL; ++ free(prev_r2t_trans); prev_r2t_trans = NULL; ++ free(prev_r2t_raw); prev_r2t_raw = NULL; ++ free(prev_r2c_trans); prev_r2c_trans = NULL; ++ free(prev_r2c_raw); prev_r2c_raw = NULL; + } + + void __attribute__((destructor)) setrans_lib_destructor(void); +@@ -267,6 +267,7 @@ void hidden __attribute__((destructor)) setrans_lib_destructor(void) + + static inline void init_thread_destructor(void) + { ++ setrans_thread_destructor(NULL); + if (destructor_initialized == 0) { + __selinux_setspecific(destructor_key, (void *)1); + destructor_initialized = 1; diff --git a/libselinux/src/setrans_internal.h b/libselinux/src/setrans_internal.h index a801ee8..b3bdca2 100644 --- a/libselinux/src/setrans_internal.h diff --git a/libselinux.spec b/libselinux.spec index 0699ca3..ec2a2d9 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.1.13 -Release: 19%{?dist} +Release: 21%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -240,6 +240,14 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Fri Oct 4 2013 Dan Walsh - 2.1.13-21 +- Add systemd_contexts support +- Do substitutions on a local sub followed by a dist sub + +* Thu Oct 3 2013 Dan Walsh - 2.1.13-20 +- Eliminate requirement on pthread library, by applying patch for Jakub Jelinek +Resolves #1013801 + * Mon Sep 16 2013 Dan Walsh - 2.1.13-19 - Fix handling of libselinux getconlist with only one entry