From 763f66c192dabb96039b4674beacfd36d3fb7316 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 23 Sep 2013 09:58:31 -0400 Subject: [PATCH 01/12] Fix handling of libselinux getconlist with only one entry --- libselinux-rhat.patch | 26 ++++++++++++++++++++------ libselinux.spec | 8 +++++++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 98da2bc..56fbf36 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -706,7 +706,7 @@ index 802a07f..6ff83a7 100644 } diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c -index b9e8002..355730a 100644 +index b9e8002..1d91123 100644 --- a/libselinux/src/get_context_list.c +++ b/libselinux/src/get_context_list.c @@ -426,7 +426,7 @@ int get_ordered_context_list(const char *user, @@ -727,8 +727,11 @@ index b9e8002..355730a 100644 snprintf(fname, fname_len, "%s%s", user_contexts_path, user); fp = fopen(fname, "r"); if (fp) { -@@ -465,31 +465,28 @@ int get_ordered_context_list(const char *user, +@@ -463,33 +463,31 @@ int get_ordered_context_list(const char *user, + __FUNCTION__, selinux_default_context_path()); + /* Fall through */ } ++ rc = 0; } + if (!nordered) @@ -764,7 +767,7 @@ index b9e8002..355730a 100644 - to the caller. Otherwise, fall back to the entire reachable list. */ - if (nordered && nordered < nreach) { + /* Only report the ordered entries to the caller. */ -+ if (nordered < nreach) { ++ if (nordered <= nreach) { for (i = nordered; i < nreach; i++) free(reachable[i]); reachable[nordered] = NULL; @@ -774,7 +777,7 @@ index b9e8002..355730a 100644 } out: -@@ -523,14 +520,6 @@ int get_ordered_context_list(const char *user, +@@ -523,14 +521,6 @@ int get_ordered_context_list(const char *user, } rc = 1; /* one context in the list */ goto out; @@ -1049,10 +1052,21 @@ index 2c7c85c..4a4aebc 100644 hidden_proto(selinux_booleans_subs_path) hidden_proto(selinux_default_context_path) diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i -index 359bd02..0ab0bae 100644 +index 359bd02..9884454 100644 --- a/libselinux/src/selinuxswig_python.i +++ b/libselinux/src/selinuxswig_python.i -@@ -74,6 +74,10 @@ def install(src, dest): +@@ -10,6 +10,10 @@ + + import shutil, os, stat + ++DISABLED = -1 ++PERMISSIVE = 0 ++ENFORCING = 1 ++ + def restorecon(path, recursive=False): + """ Restore SELinux context on a given path """ + +@@ -74,6 +78,10 @@ def install(src, dest): $1 = &temp; } diff --git a/libselinux.spec b/libselinux.spec index 9bd25f9..0699ca3 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.1.13 -Release: 17%{?dist} +Release: 19%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -240,6 +240,12 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Mon Sep 16 2013 Dan Walsh - 2.1.13-19 +- Fix handling of libselinux getconlist with only one entry + +* Tue Sep 3 2013 Dan Walsh - 2.1.13-17 +- Add Python constants for SELinux enforcing modes + * Sat Aug 03 2013 Fedora Release Engineering - 2.1.13-17 - Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild From 0695b75fac098c317dde0f339bf40c13c2130f88 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Thu, 3 Oct 2013 12:36:44 -0400 Subject: [PATCH 02/12] Eliminate requirement on pthread library, by applying patch for Jakub Jelinek Resolves #1013801 --- libselinux-rhat.patch | 151 +++++++++++++++++++++++++++++++++++++++--- libselinux.spec | 6 +- 2 files changed, 147 insertions(+), 10 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 56fbf36..ae14385 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -508,7 +508,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 +527,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 +705,32 @@ index 802a07f..6ff83a7 100644 return rc; } +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 @@ -837,6 +863,32 @@ index 5f697f3..9b0d6b0 100644 ret = &spec_arr[i].lr; finish: +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 +911,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 +935,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 +972,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 +981,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 +999,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 +1009,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 { @@ -1077,6 +1153,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..6592c70 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: 20%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -240,6 +240,10 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* 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 From 82deec5e5becbe8631000caf90525303ea4d3828 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Fri, 4 Oct 2013 10:16:56 -0400 Subject: [PATCH 03/12] Add systemd_contexts support - Do substitutions on a local sub followed by a dist sub --- libselinux-rhat.patch | 138 +++++++++++++++++++++++++++++++++++++++--- libselinux.spec | 6 +- 2 files changed, 135 insertions(+), 9 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index ae14385..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 @@ -705,6 +713,18 @@ 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 @@ -819,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) @@ -842,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) @@ -863,6 +941,18 @@ 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 @@ -1019,7 +1109,7 @@ index 6c5b45a..ecaccc6 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 @@ @@ -1031,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) @@ -1045,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; } @@ -1083,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) @@ -1115,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) @@ -1127,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 diff --git a/libselinux.spec b/libselinux.spec index 6592c70..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: 20%{?dist} +Release: 21%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -240,6 +240,10 @@ 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 From bb6f29def08984d2a003df341c2965fdaffe0a98 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Thu, 31 Oct 2013 09:29:10 -0400 Subject: [PATCH 04/12] Update to upstream * Fix avc_has_perm() returns -1 even when SELinux is in permissive mode. * Support overriding Makefile RANLIB from Sven Vermeulen. * Update pkgconfig definition from Sven Vermeulen. * Mount sysfs before trying to mount selinuxfs from Sven Vermeulen. * Fix man pages from Laurent Bigonville. * Support overriding PATH and LIBBASE in Makefiles from Laurent Bigonville. * Fix LDFLAGS usage from Laurent Bigonville * Avoid shadowing stat in load_mmap from Joe MacDonald. * Support building on older PCRE libraries from Joe MacDonald. * Fix handling of temporary file in sefcontext_compile from Dan Walsh. * Fix procattr cache from Dan Walsh. * Define python constants for getenforce result from Dan Walsh. * Fix label substitution handling of / from Dan Walsh. * Add selinux_current_policy_path from Dan Walsh. * Change get_context_list to only return good matches from Dan Walsh. * Support udev-197 and higher from Sven Vermeulen and Dan Walsh. * Add support for local substitutions from Dan Walsh. * Change setfilecon to not return ENOSUP if context is already correct from Dan Walsh. * Python wrapper leak fixes from Dan Walsh. * Export SELINUX_TRANS_DIR definition in selinux.h from Dan Walsh. * Add selinux_systemd_contexts_path from Dan Walsh. * Add selinux_set_policy_root from Dan Walsh. * Add man page for sefcontext_compile from Dan Walsh. --- .gitignore | 1 + libselinux-rhat.patch | 1435 ----------------------------------------- libselinux.spec | 30 +- sources | 2 +- 4 files changed, 30 insertions(+), 1438 deletions(-) diff --git a/.gitignore b/.gitignore index 76558d8..c3bf9bd 100644 --- a/.gitignore +++ b/.gitignore @@ -195,3 +195,4 @@ libselinux-2.0.96.tgz /libselinux-2.1.11.tgz /libselinux-2.1.12.tgz /libselinux-2.1.13.tgz +/libselinux-2.2.tgz diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 8ca2b1c..1789ec0 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,984 +1,3 @@ -diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -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); - #define SELINUX_WARNING 1 - #define SELINUX_INFO 2 - #define SELINUX_AVC 3 -+#define SELINUX_TRANS_DIR "/var/run/setrans" - - /* Compute an access decision. */ - extern int security_compute_av(const security_context_t scon, -@@ -496,8 +497,15 @@ extern int selinux_getpolicytype(char **policytype); - */ - extern const char *selinux_policy_root(void); - -+/* -+ selinux_set_policy_root sets an alternate policy root directory path under -+ which the compiled policy file and context configuration files exist. -+ */ -+extern int selinux_set_policy_root(const char *rootpath); -+ - /* These functions return the paths to specific files under the - policy root directory. */ -+extern const char *selinux_current_policy_path(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); -@@ -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 -+++ b/libselinux/man/man3/security_compute_av.3 -@@ -37,9 +37,9 @@ the SELinux policy database in the kernel - .sp - .BI "int security_compute_user_raw(security_context_t "scon ", const char *" username ", security_context_t **" con ); - .sp --.BI "int security_get_initial_context(const char *" name ", security_context_t " con ); -+.BI "int security_get_initial_context(const char *" name ", security_context_t *" con ); - .sp --.BI "int security_get_initial_context_raw(const char *" name ", security_context_t " con ); -+.BI "int security_get_initial_context_raw(const char *" name ", security_context_t *" con ); - .sp - .BI "int selinux_check_access(const security_context_t " scon ", const security_context_t " tcon ", const char *" class ", const char *" perm ", void *" auditdata); - .sp -diff --git a/libselinux/man/man3/security_disable.3 b/libselinux/man/man3/security_disable.3 -index aeb78da..c75ce0d 100644 ---- a/libselinux/man/man3/security_disable.3 -+++ b/libselinux/man/man3/security_disable.3 -@@ -17,7 +17,7 @@ and then unmounts - This function can only be called at runtime and prior to the initial policy - load. After the initial policy load, the SELinux kernel code cannot be disabled, - but only placed in "permissive" mode by using --.BR setenforce (1). -+.BR security_setenforce(3). - . - .SH "RETURN VALUE" - .BR security_disable () -@@ -27,4 +27,4 @@ returns zero on success or \-1 on error. - This manual page has been written by Guido Trentalancia - . - .SH "SEE ALSO" --.BR selinux (8), " setenforce "(3) -+.BR selinux (8), " setenforce "(8) -diff --git a/libselinux/man/man3/security_load_policy.3 b/libselinux/man/man3/security_load_policy.3 -index c4439bf..af56163 100644 ---- a/libselinux/man/man3/security_load_policy.3 -+++ b/libselinux/man/man3/security_load_policy.3 -@@ -43,7 +43,7 @@ unmounted using a call to - .BR security_disable (3). - Therefore, after the initial policy load, the only operational changes - are those permitted by --.BR setenforce (3) -+.BR security_setenforce (3) - (i.e. eventually setting the framework in permissive mode rather than - in enforcing one). - . -@@ -54,4 +54,4 @@ Returns zero on success or \-1 on error. - This manual page has been written by Guido Trentalancia - . - .SH "SEE ALSO" --.BR selinux "(8), " security_disable "(3), " setenforce "(1) -+.BR selinux "(8), " security_disable "(3), " setenforce "(8) -diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3 -index ec97dcf..503c52c 100644 ---- a/libselinux/man/man3/selinux_binary_policy_path.3 -+++ b/libselinux/man/man3/selinux_binary_policy_path.3 -@@ -1,6 +1,6 @@ - .TH "selinux_binary_policy_path" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation" - .SH "NAME" --selinux_path, selinux_policy_root, selinux_binary_policy_path, -+selinux_path, selinux_policy_root, selinux_binary_policy_path, selinux_current_policy_path, - selinux_failsafe_context_path, selinux_removable_context_path, - selinux_default_context_path, selinux_user_contexts_path, - selinux_file_context_path, selinux_media_context_path, -@@ -17,6 +17,8 @@ directories and files - .sp - .B const char *selinux_binary_policy_path(void); - .sp -+.B const char *selinux_current_policy_path(void); -+.sp - .B const char *selinux_failsafe_context_path(void); - .sp - .B const char *selinux_removable_context_path(void); -@@ -55,6 +57,9 @@ returns the top-level policy directory. - .BR selinux_binary_policy_path () - returns the binary policy file loaded into kernel. - .sp -+.BR selinux_current_policy_path () -+returns the currently loaded policy file from the kernel. -+.sp - .BR selinux_default_type_path () - returns the context file mapping roles to default types. - .sp -diff --git a/libselinux/man/man3/selinux_current_policy_path.3 b/libselinux/man/man3/selinux_current_policy_path.3 -new file mode 100644 -index 0000000..175a611 ---- /dev/null -+++ b/libselinux/man/man3/selinux_current_policy_path.3 -@@ -0,0 +1 @@ -+.so man3/selinux_binary_policy_path.3 -diff --git a/libselinux/man/man3/selinux_policy_root.3 b/libselinux/man/man3/selinux_policy_root.3 -index a6ccf86..63dc901 100644 ---- a/libselinux/man/man3/selinux_policy_root.3 -+++ b/libselinux/man/man3/selinux_policy_root.3 -@@ -1,21 +1,34 @@ - .TH "selinux_policy_root" "3" "25 May 2004" "dwalsh@redhat.com" "SELinux API documentation" - .SH "NAME" - selinux_policy_root \- return the path of the SELinux policy files for this machine -+selinux_set_policy_root \- Set an alternate SELinux root path for the SELinux policy files for this machine. - . - .SH "SYNOPSIS" - .B #include - .sp - .B const char *selinux_policy_root(void); - . -+.sp -+.B int selinux_set_policy_root(const char *policypath); -+. - .SH "DESCRIPTION" - .BR selinux_policy_root () - reads the contents of the - .I /etc/selinux/config - file to determine which policy files should be used for this machine. - . -+.BR selinux_set_policy_root () -+sets up all all policy paths based on the alternate root -+ -+.I /etc/selinux/config -+file to determine which policy files should be used for this machine. -+. - .SH "RETURN VALUE" --On success, returns a directory path containing the SELinux policy files. --On failure, NULL is returned. -+On success, selinux_policy_root returns a directory path containing the SELinux policy files. -+On failure, selinux_policy_root returns NULL. -+ -+On success, selinux_set_policy_root returns 0 on success -1 on failure. -+ - . - .SH "SEE ALSO" - .BR selinux "(8)" -diff --git a/libselinux/man/man3/selinux_set_policy_root.3 b/libselinux/man/man3/selinux_set_policy_root.3 -new file mode 100644 -index 0000000..8077658 ---- /dev/null -+++ b/libselinux/man/man3/selinux_set_policy_root.3 -@@ -0,0 +1 @@ -+.so man3/selinux_policy_root.3 -diff --git a/libselinux/man/man5/secolor.conf.5 b/libselinux/man/man5/secolor.conf.5 -deleted file mode 100644 -index b834577..0000000 ---- a/libselinux/man/man5/secolor.conf.5 -+++ /dev/null -@@ -1,178 +0,0 @@ --.TH "secolor.conf" "5" "08 April 2011" "SELinux API documentation" --.SH "NAME" --secolor.conf \- The SELinux color configuration file --. --.SH "DESCRIPTION" --This optional file controls the color to be associated to the context components associated to the --.I raw --context passed by --.BR selinux_raw_context_to_color "(3)," --when context related information is to be displayed in color by an SELinux-aware application. --.sp --.BR selinux_raw_context_to_color "(3)" --obtains this color information from the active policy --.B secolor.conf --file as returned by --.BR selinux_colors_path "(3)." --. --.SH "FILE FORMAT" --The file format is as follows: --.RS --.B color --.I color_name --.BI "= #"color_mask --.br --[...] --.sp --.I context_component string --.B = --.I fg_color_name bg_color_name --.br --[...] --.sp --.RE -- --Where: --.br --.B color --.RS --The color keyword. Each color entry is on a new line. --.RE --.I color_name --.RS --A single word name for the color (e.g. red). --.RE --.I color_mask --.RS --A color mask starting with a hash (#) that describes the hexadecimal RGB colors with black being #000000 and white being #ffffff. --.RE --.I context_component --.RS --The context component name that must be one of the following: --.br --.RS --user, role, type or range --.RE --Each --.IR context_component " " string " ..." --entry is on a new line. --.RE --.I string --.RS --This is the --.I context_component --string that will be matched with the --.I raw --context component passed by --.BR selinux_raw_context_to_color "(3)." --.br --A wildcard '*' may be used to match any undefined string for the user, role and type --.I context_component --entries only. --.RE -- --.I fg_color_name --.RS --The color_name string that will be used as the foreground color. --A --.I color_mask --may also be used. --.RE --.I bg_color_name --.RS --The color_name string that will be used as the background color. --A --.I color_mask --may also be used. --.RE --. --.SH "EXAMPLES" --Example 1 entries are: --.RS --color black = #000000 --.br --color green = #008000 --.br --color yellow = #ffff00 --.br --color blue = #0000ff --.br --color white = #ffffff --.br --color red = #ff0000 --.br --color orange = #ffa500 --.br --color tan = #D2B48C --.sp --user * = black white --.br --role * = white black --.br --type * = tan orange --.br --range s0\-s0:c0.c1023 = black green --.br --range s1\-s1:c0.c1023 = white green --.br --range s3\-s3:c0.c1023 = black tan --.br --range s5\-s5:c0.c1023 = white blue --.br --range s7\-s7:c0.c1023 = black red --.br --range s9\-s9:c0.c1023 = black orange --.br --range s15:c0.c1023 = black yellow --.RE -- --.sp --Example 2 entries are: --.RS --color black = #000000 --.br --color green = #008000 --.br --color yellow = #ffff00 --.br --color blue = #0000ff --.br --color white = #ffffff --.br --color red = #ff0000 --.br --color orange = #ffa500 --.br --color tan = #d2b48c --.sp --user unconfined_u = #ff0000 green --.br --role unconfined_r = red #ffffff --.br --type unconfined_t = red orange --.br --user user_u = black green --.br --role user_r = white black --.br --type user_t = tan red --.br --user xguest_u = black yellow --.br --role xguest_r = black red --.br --type xguest_t = black green --.br --user sysadm_u = white black --.br --range s0:c0.c1023 = black white --.br --user * = black white --.br --role * = black white --.br --type * = black white --.RE --. --.SH "SEE ALSO" --.BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" -diff --git a/libselinux/man/man8/getenforce.8 b/libselinux/man/man8/getenforce.8 -index 906279f..e0924d8 100644 ---- a/libselinux/man/man8/getenforce.8 -+++ b/libselinux/man/man8/getenforce.8 -@@ -1,4 +1,4 @@ --.TH "getenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "getenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - getenforce \- get the current mode of SELinux - . -diff --git a/libselinux/man/man8/matchpathcon.8 b/libselinux/man/man8/matchpathcon.8 -index 368991f..5d60789 100644 ---- a/libselinux/man/man8/matchpathcon.8 -+++ b/libselinux/man/man8/matchpathcon.8 -@@ -13,6 +13,8 @@ matchpathcon \- get the default SELinux security context for the specified path - .IR file_contexts_file ] - .RB [ \-p - .IR prefix ] -+.RB [ \-P -+.IR policy_root_path ] - .I filepath... - . - .SH "DESCRIPTION" -@@ -46,6 +48,9 @@ Use alternate file_context file - .BI \-p " prefix" - Use prefix to speed translations - .TP -+.BI \-P " policy_root_path" -+Use alternate policy root path -+.TP - .B \-V - Verify file context on disk matches defaults - . -diff --git a/libselinux/man/man8/sefcontext_compile.8 b/libselinux/man/man8/sefcontext_compile.8 -new file mode 100644 -index 0000000..c37ed4a ---- /dev/null -+++ b/libselinux/man/man8/sefcontext_compile.8 -@@ -0,0 +1,19 @@ -+.TH "sefcontext_compile" "8" "27 Jun 2013" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.SH "NAME" -+sefcontext_compile \- compile file context regular expression files -+. -+.SH "SYNOPSIS" -+.B sefcontext_compile inputfile -+. -+.SH "DESCRIPTION" -+sefcontext_compile is used libsemanage to compile file context regular expressions into prce format. sefcontext_compile writes the compiled prce file with the .bin suffix appended "inputfile".bin. This compiled file is used by libselinux file labeling functions. -+ -+.SH "EXAMPLE" -+sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts -+. -+.SH AUTHOR -+Dan Walsh, -+. -+.SH "SEE ALSO" -+.BR selinux (8), -+.BR semanage (8), -diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8 -index a328866..50868e4 100644 ---- a/libselinux/man/man8/selinux.8 -+++ b/libselinux/man/man8/selinux.8 -@@ -37,20 +37,22 @@ The - configuration file also controls what policy - is active on the system. SELinux allows for multiple policies to be - installed on the system, but only one policy may be active at any --given time. At present, two kinds of SELinux policy exist: targeted --and strict. The targeted policy is designed as a policy where most --processes operate without restrictions, and only specific services are -+given time. At present, multiple kinds of SELinux policy exist: targeted, -+mls for example. The targeted policy is designed as a policy where most -+user processes operate without restrictions, and only specific services are - placed into distinct security domains that are confined by the policy. - For example, the user would run in a completely unconfined domain - while the named daemon or apache daemon would run in a specific domain --tailored to its operation. The strict policy is designed as a policy --where all processes are partitioned into fine-grained security domains --and confined by policy. It is anticipated in the future that other --policies will be created (Multi-Level Security for example). You can -+tailored to its operation. The MLS (Multi-Level Security) policy is designed -+as a policy where all processes are partitioned into fine-grained security -+domains and confined by policy. MLS also supports the Bell And LaPadula model, where processes are not only confined by the type but also the level of the data. -+ -+You can - define which policy you will run by setting the - .B SELINUXTYPE - environment variable within - .IR /etc/selinux/config . -+You must reboot and possibly relabel if you change the policy type to have it take effect on the system. - The corresponding - policy configuration for each such policy must be installed in the - .I /etc/selinux/{SELINUXTYPE}/ -@@ -58,7 +60,7 @@ directories. - - A given SELinux policy can be customized further based on a set of - compile-time tunable options and a set of runtime policy booleans. --.B \%system\-config\-securitylevel -+.B \%system\-config\-selinux - allows customization of these booleans and tunables. - - Many domains that are protected by SELinux also include SELinux man pages explaining how to customize their policy. -@@ -86,11 +88,13 @@ This manual page was written by Dan Walsh . - .nh - .BR booleans (8), - .BR setsebool (8), --.BR selinuxenabled (8), -+.BR sepolicy (8), -+.BR system-config-selinux (8), - .BR togglesebool (8), - .BR restorecon (8), -+.BR fixfiles (8), - .BR setfiles (8), --.BR semange (8), -+.BR semanage (8), - .BR sepolicy(8) - - Every confined service on the system has a man page in the following format: -diff --git a/libselinux/man/man8/selinuxenabled.8 b/libselinux/man/man8/selinuxenabled.8 -index e0b5201..ac20587 100644 ---- a/libselinux/man/man8/selinuxenabled.8 -+++ b/libselinux/man/man8/selinuxenabled.8 -@@ -1,4 +1,4 @@ --.TH "selinuxenabled" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "selinuxenabled" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - selinuxenabled \- tool to be used within shell scripts to determine if selinux is enabled - . -diff --git a/libselinux/man/man8/selinuxexeccon.8 b/libselinux/man/man8/selinuxexeccon.8 -index 765cf8c..30c20ed 100644 ---- a/libselinux/man/man8/selinuxexeccon.8 -+++ b/libselinux/man/man8/selinuxexeccon.8 -@@ -1,4 +1,4 @@ --.TH "selinuxexeccon" "1" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "selinuxexeccon" "8" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - selinuxexeccon \- report SELinux context used for this executable - . -diff --git a/libselinux/man/man8/setenforce.8 b/libselinux/man/man8/setenforce.8 -index b038da0..8a24f1c 100644 ---- a/libselinux/man/man8/setenforce.8 -+++ b/libselinux/man/man8/setenforce.8 -@@ -1,4 +1,4 @@ --.TH "setenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "setenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - setenforce \- modify the mode SELinux is running in - . -diff --git a/libselinux/man/man8/togglesebool.8 b/libselinux/man/man8/togglesebool.8 -index 948aff1..598dc94 100644 ---- a/libselinux/man/man8/togglesebool.8 -+++ b/libselinux/man/man8/togglesebool.8 -@@ -1,4 +1,4 @@ --.TH "togglesebool" "1" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation" -+.TH "togglesebool" "8" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - togglesebool \- flip the current value of a SELinux boolean - . -diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -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(".")' - RUBYPLATFORM ?= $(shell $(RUBY) -e 'print RUBY_PLATFORM') - RUBYINC ?= $(shell pkg-config --cflags ruby) - RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM) --LIBBASE=$(shell basename $(LIBDIR)) -- --LDFLAGS ?= -lpcre -lpthread -+LIBBASE ?= $(shell basename $(LIBDIR)) - - VERSION = $(shell cat ../VERSION) - LIBVERSION = 1 -@@ -116,7 +114,7 @@ $(LIBA): $(OBJS) - $(RANLIB) $@ - - $(LIBSO): $(LOBJS) -- $(CC) $(CFLAGS) -shared -o $@ $^ -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 -diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c -index ffe381b..560bc25 100644 ---- a/libselinux/src/audit2why.c -+++ b/libselinux/src/audit2why.c -@@ -210,27 +210,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"); -- while (!fp && errno == ENOENT && --vers) { -- snprintf(path, PATH_MAX, "%s.%d", -- selinux_binary_policy_path(), vers); -- fp = fopen(path, "r"); -- } -+ fp = fopen(selinux_current_policy_path(), "r"); - if (!fp) { - snprintf(errormsg, sizeof(errormsg), -- "unable to open %s.%d: %s\n", -- selinux_binary_policy_path(), -- security_policyvers(), strerror(errno)); -+ "unable to open %s: %s\n", -+ selinux_current_policy_path(), -+ strerror(errno)); - PyErr_SetString( PyExc_ValueError, errormsg); - return 1; - } -@@ -310,10 +295,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { - } - - #define RETURN(X) \ -- PyTuple_SetItem(result, 0, Py_BuildValue("i", X)); \ -- return result; -+ { \ -+ return Py_BuildValue("iO", (X), Py_None); \ -+ } - - static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) { -+ char *reason_buf = NULL; - security_context_t scon; - security_context_t tcon; - char *tclassstr; -@@ -328,10 +315,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - struct sepol_av_decision avd; - int rc; - int i=0; -- PyObject *result = PyTuple_New(2); -- if (!result) return NULL; -- Py_INCREF(Py_None); -- PyTuple_SetItem(result, 1, Py_None); - - if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj)) - return NULL; -@@ -342,22 +325,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - /* should raise an error here. */ - if (numlines < 0) return NULL; /* Not a list */ - -- if (!avc) { -+ if (!avc) - RETURN(NOPOLICY) -- } - - rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid); -- if (rc < 0) { -+ if (rc < 0) - RETURN(BADSCON) -- } -+ - rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid); -- if (rc < 0) { -+ if (rc < 0) - RETURN(BADTCON) -- } -+ - tclass = string_to_security_class(tclassstr); -- if (!tclass) { -+ if (!tclass) - RETURN(BADTCLASS) -- } -+ - /* Convert the permission list to an AV. */ - av = 0; - -@@ -377,21 +359,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - #endif - - perm = string_to_av_perm(tclass, permstr); -- if (!perm) { -+ if (!perm) - RETURN(BADPERM) -- } -+ - av |= perm; - } - - /* Reproduce the computation. */ -- rc = sepol_compute_av_reason(ssid, tsid, tclass, av, &avd, &reason); -- if (rc < 0) { -+ rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0); -+ if (rc < 0) - RETURN(BADCOMPUTE) -- } - -- if (!reason) { -+ if (!reason) - RETURN(ALLOW) -- } -+ - if (reason & SEPOL_COMPUTEAV_TE) { - avc->ssid = ssid; - avc->tsid = tsid; -@@ -404,28 +385,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - RETURN(TERULE) - } - } else { -- PyTuple_SetItem(result, 0, Py_BuildValue("i", BOOLEAN)); -+ PyObject *outboollist; - struct boolean_t *b = bools; - int len=0; - while (b->name) { - len++; b++; - } - b = bools; -- PyObject *outboollist = PyTuple_New(len); -+ outboollist = PyList_New(len); - len=0; - while(b->name) { -- PyObject *bool = Py_BuildValue("(si)", b->name, b->active); -- PyTuple_SetItem(outboollist, len++, bool); -+ PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active); -+ PyList_SetItem(outboollist, len++, bool_); - b++; - } - free(bools); -- PyTuple_SetItem(result, 1, outboollist); -- return result; -+ /* 'N' steals the reference to outboollist */ -+ return Py_BuildValue("iN", BOOLEAN, outboollist); - } - } - - if (reason & SEPOL_COMPUTEAV_CONS) { -- RETURN(CONSTRAINT); -+ if (reason_buf) { -+ PyObject *result = NULL; -+ result = Py_BuildValue("is", CONSTRAINT, reason_buf); -+ free(reason_buf); -+ return result; -+ } -+ RETURN(CONSTRAINT) - } - - if (reason & SEPOL_COMPUTEAV_RBAC) -diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c -index 802a07f..6ff83a7 100644 ---- a/libselinux/src/avc.c -+++ b/libselinux/src/avc.c -@@ -827,6 +827,7 @@ int avc_has_perm(security_id_t ssid, security_id_t tsid, - errsave = errno; - avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); - errno = errsave; -+ if (!avc_enforcing) return 0; - 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 -+++ b/libselinux/src/get_context_list.c -@@ -426,7 +426,7 @@ int get_ordered_context_list(const char *user, - /* Initialize ordering array. */ - ordering = malloc(nreach * sizeof(unsigned int)); - if (!ordering) -- goto oom_order; -+ goto failsafe; - for (i = 0; i < nreach; i++) - ordering[i] = nreach; - -@@ -435,7 +435,7 @@ int get_ordered_context_list(const char *user, - fname_len = strlen(user_contexts_path) + strlen(user) + 2; - fname = malloc(fname_len); - if (!fname) -- goto oom_order; -+ goto failsafe; - snprintf(fname, fname_len, "%s%s", user_contexts_path, user); - fp = fopen(fname, "r"); - if (fp) { -@@ -463,33 +463,31 @@ int get_ordered_context_list(const char *user, - __FUNCTION__, selinux_default_context_path()); - /* Fall through */ - } -+ rc = 0; - } - -+ if (!nordered) -+ goto failsafe; -+ - /* Apply the ordering. */ -- if (nordered) { -- co = malloc(nreach * sizeof(struct context_order)); -- if (!co) -- goto oom_order; -- for (i = 0; i < nreach; i++) { -- co[i].con = reachable[i]; -- co[i].order = ordering[i]; -- } -- qsort(co, nreach, sizeof(struct context_order), order_compare); -- for (i = 0; i < nreach; i++) -- reachable[i] = co[i].con; -- free(co); -+ co = malloc(nreach * sizeof(struct context_order)); -+ if (!co) -+ goto failsafe; -+ for (i = 0; i < nreach; i++) { -+ co[i].con = reachable[i]; -+ co[i].order = ordering[i]; - } -+ qsort(co, nreach, sizeof(struct context_order), order_compare); -+ for (i = 0; i < nreach; i++) -+ reachable[i] = co[i].con; -+ free(co); - -- /* Return the ordered list. -- If we successfully ordered it, then only report the ordered entries -- to the caller. Otherwise, fall back to the entire reachable list. */ -- if (nordered && nordered < nreach) { -+ /* Only report the ordered entries to the caller. */ -+ if (nordered <= nreach) { - for (i = nordered; i < nreach; i++) - free(reachable[i]); - reachable[nordered] = NULL; - rc = nordered; -- } else { -- rc = nreach; - } - - out: -@@ -523,14 +521,6 @@ int get_ordered_context_list(const char *user, - } - rc = 1; /* one context in the list */ - goto out; -- -- oom_order: -- /* Unable to order context list due to OOM condition. -- Fall back to unordered reachable context list. */ -- fprintf(stderr, "%s: out of memory, unable to order list\n", -- __FUNCTION__); -- rc = nreach; -- goto out; - } - - hidden_def(get_ordered_context_list) -diff --git a/libselinux/src/label.c b/libselinux/src/label.c -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) - static char *selabel_sub(struct selabel_sub *ptr, const char *src) - { - char *dst = NULL; -+ int len; - - while (ptr) { - if (strncmp(src, ptr->src, ptr->slen) == 0 ) { - if (src[ptr->slen] == '/' || - src[ptr->slen] == 0) { -- if (asprintf(&dst, "%s%s", ptr->dst, &src[ptr->slen]) < 0) -+ if ((src[ptr->slen] == '/') && -+ (strcmp(ptr->dst, "/") == 0)) -+ len = ptr->slen + 1; -+ else -+ len = ptr->slen; -+ if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0) - 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..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) - continue; -+ -+ errno = ENOENT; - /* else it's an error */ - goto finish; - } -@@ -660,6 +662,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, - goto finish; - } - -+ errno = 0; - 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 @@ -1000,457 +19,3 @@ index 2d7369e..2a00807 100644 va_end(ap); } -diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c -index 6c5b45a..ecaccc6 100644 ---- a/libselinux/src/procattr.c -+++ b/libselinux/src/procattr.c -@@ -9,19 +9,30 @@ - #include "selinux_internal.h" - #include "policy.h" - -+#define UNSET (const security_context_t) -1 -+ - static __thread pid_t cpid; - static __thread pid_t tid; --static __thread security_context_t prev_current; --static __thread security_context_t prev_exec; --static __thread security_context_t prev_fscreate; --static __thread security_context_t prev_keycreate; --static __thread security_context_t prev_sockcreate; -+static __thread security_context_t prev_current = UNSET; -+static __thread security_context_t prev_exec = UNSET; -+static __thread security_context_t prev_fscreate = UNSET; -+static __thread security_context_t prev_keycreate = UNSET; -+static __thread security_context_t prev_sockcreate = UNSET; - - static pthread_once_t once = PTHREAD_ONCE_INIT; - static pthread_key_t destructor_key; - 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) - { -- free(prev_current); -- free(prev_exec); -- free(prev_fscreate); -- free(prev_keycreate); -- free(prev_sockcreate); -+ if (prev_current != UNSET) -+ free(prev_current); -+ if (prev_exec != UNSET) -+ free(prev_exec); -+ if (prev_fscreate != UNSET) -+ free(prev_fscreate); -+ if (prev_keycreate != UNSET) -+ free(prev_keycreate); -+ if (prev_sockcreate != UNSET) -+ free(prev_sockcreate); - } - - static void free_procattr(void) -@@ -41,7 +57,7 @@ static void free_procattr(void) - procattr_thread_destructor(NULL); - tid = 0; - cpid = getpid(); -- prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = NULL; -+ prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = UNSET; - } - - void __attribute__((destructor)) procattr_destructor(void); -@@ -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; - }; - -- if (prev_context) { -+ if (prev_context && prev_context != UNSET) { - *context = strdup(prev_context); - if (!(*context)) { - return -1; -@@ -230,7 +246,8 @@ static int setprocattrcon_raw(security_context_t context, - - if (!context && !*prev_context) - return 0; -- if (context && *prev_context && !strcmp(context, *prev_context)) -+ if (context && *prev_context && *prev_context != UNSET -+ && !strcmp(context, *prev_context)) - return 0; - - fd = openattr(pid, attr, O_RDWR); -@@ -257,6 +274,8 @@ out: - free(context); - return -1; - } else { -+ if (*prev_context != UNSET) -+ free(*prev_context); - *prev_context = context; - return 0; - } -diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index 296f357..2cd6d54 100644 ---- a/libselinux/src/selinux_config.c -+++ b/libselinux/src/selinux_config.c -@@ -8,6 +8,8 @@ - #include - #include - #include -+#include -+#include "policy.h" - #include "selinux_internal.h" - #include "get_default_type_internal.h" - -@@ -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) - -+static int setpolicytype(const char *type) -+{ -+ free(selinux_policytype); -+ selinux_policytype = strdup(type); -+ return selinux_policytype ? 0 : -1; -+} -+ - static char *selinux_policyroot = NULL; - static const char *selinux_rootpath = SELINUXDIR; - -@@ -261,6 +271,37 @@ const char *selinux_policy_root(void) - return selinux_policyroot; - } - -+int selinux_set_policy_root(const char *path) -+{ -+ int i; -+ char *policy_type = strrchr(path, '/'); -+ if (!policy_type) { -+ errno = EINVAL; -+ return -1; -+ } -+ policy_type++; -+ -+ fini_selinuxmnt(); -+ fini_selinux_policyroot(); -+ -+ selinux_policyroot = strdup(path); -+ if (! selinux_policyroot) -+ return -1; -+ -+ if (setpolicytype(policy_type) != 0) -+ return -1; -+ -+ for (i = 0; i < NEL; i++) -+ if (asprintf(&file_paths[i], "%s%s", -+ selinux_policyroot, -+ file_path_suffixes_data.str + -+ file_path_suffixes_idx[i]) -+ == -1) -+ return -1; -+ -+ return 0; -+} -+ - const char *selinux_path(void) - { - return selinux_rootpath; -@@ -303,6 +344,31 @@ const char *selinux_binary_policy_path(void) - - hidden_def(selinux_binary_policy_path) - -+const char *selinux_current_policy_path(void) -+{ -+ int rc = 0; -+ int vers = 0; -+ static char policy_path[PATH_MAX]; -+ -+ if (selinux_mnt) { -+ snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt); -+ if (access(policy_path, F_OK) == 0 ) { -+ return policy_path; -+ } -+ } -+ vers = security_policyvers(); -+ do { -+ /* Check prior versions to see if old policy is available */ -+ snprintf(policy_path, sizeof(policy_path), "%s.%d", -+ selinux_binary_policy_path(), vers); -+ } while ((rc = access(policy_path, F_OK)) && --vers > 0); -+ -+ if (rc) return NULL; -+ return policy_path; -+} -+ -+hidden_def(selinux_current_policy_path) -+ - 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..afb2170 100644 ---- a/libselinux/src/selinux_internal.h -+++ b/libselinux/src/selinux_internal.h -@@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(security_setenforce) - hidden_proto(security_deny_unknown) - hidden_proto(selinux_boolean_sub) -+ hidden_proto(selinux_current_policy_path) - 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 -+++ b/libselinux/src/selinuxswig_python.i -@@ -10,6 +10,10 @@ - - import shutil, os, stat - -+DISABLED = -1 -+PERMISSIVE = 0 -+ENFORCING = 1 -+ - def restorecon(path, recursive=False): - """ Restore SELinux context on a given path """ - -@@ -74,6 +78,10 @@ def install(src, dest): - $1 = &temp; - } - -+%typemap(in, numinputs=0) void *(char *temp=NULL) { -+ $1 = temp; -+} -+ - /* 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 -+++ b/libselinux/src/setrans_internal.h -@@ -1,6 +1,7 @@ - /* Author: Trusted Computer Solutions, Inc. */ -+#include - --#define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix" -+#define SETRANS_UNIX_SOCKET SELINUX_TRANS_DIR "/.setrans-unix" - - #define RAW_TO_TRANS_CONTEXT 2 - #define TRANS_TO_RAW_CONTEXT 3 -diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c -index dd5aaa3..9d3ff3a 100644 ---- a/libselinux/utils/matchpathcon.c -+++ b/libselinux/utils/matchpathcon.c -@@ -12,11 +12,10 @@ - #include - #include - -- - static void usage(const char *progname) - { - fprintf(stderr, -- "usage: %s [-N] [-n] [-f file_contexts] [-p prefix] [-Vq] path...\n", -+ "usage: %s [-N] [-n] [-f file_contexts] [ -P policy_root_path ] [-p prefix] [-Vq] path...\n", - progname); - exit(1); - } -@@ -78,7 +77,7 @@ int main(int argc, char **argv) - if (argc < 2) - usage(argv[0]); - -- while ((opt = getopt(argc, argv, "m:Nnf:p:Vq")) > 0) { -+ while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) { - switch (opt) { - case 'n': - header = 0; -@@ -113,6 +112,15 @@ int main(int argc, char **argv) - exit(1); - } - break; -+ case 'P': -+ if (selinux_set_policy_root(optarg) < 0 ) { -+ fprintf(stderr, -+ "Error setting policy root %s: %s\n", -+ optarg, -+ errno ? strerror(errno) : "invalid"); -+ exit(1); -+ } -+ break; - case 'p': - if (init) { - fprintf(stderr, -diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c -index 6f79dd6..e019a07 100644 ---- a/libselinux/utils/sefcontext_compile.c -+++ b/libselinux/utils/sefcontext_compile.c -@@ -145,7 +145,7 @@ static int process_file(struct saved_data *data, const char *filename) - * 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) -+static int write_binary_file(struct saved_data *data, int fd) - { - struct spec *specs = data->spec_arr; - FILE *bin_file; -@@ -155,7 +155,7 @@ static int write_binary_file(struct saved_data *data, char *filename) - uint32_t i; - int rc; - -- bin_file = fopen(filename, "w"); -+ bin_file = fdopen(fd, "w"); - if (!bin_file) { - perror("fopen output_file"); - exit(EXIT_FAILURE); -@@ -321,7 +321,9 @@ int main(int argc, char *argv[]) - const char *path; - char stack_path[PATH_MAX + 1]; - int rc; -- -+ char *tmp= NULL; -+ int fd; -+ - if (argc != 2) { - fprintf(stderr, "usage: %s input_file\n", argv[0]); - exit(EXIT_FAILURE); -@@ -342,13 +344,29 @@ int main(int argc, char *argv[]) - 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 (asprintf(&tmp, "%sXXXXXX", stack_path) < 0) -+ return -1; -+ -+ fd = mkstemp(tmp); -+ if (fd < 0) -+ goto err; -+ -+ rc = write_binary_file(&data, fd); -+ - if (rc < 0) -- return rc; -+ goto err; - -+ rename(tmp, stack_path); - rc = free_specs(&data); - if (rc < 0) -- return rc; -+ goto err; - -- return 0; -+ rc = 0; -+out: -+ free(tmp); -+ return rc; -+err: -+ rc = -1; -+ goto out; - } diff --git a/libselinux.spec b/libselinux.spec index ec2a2d9..40773ec 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -9,8 +9,8 @@ Summary: SELinux library and simple utilities Name: libselinux -Version: 2.1.13 -Release: 21%{?dist} +Version: 2.2 +Release: 1%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -240,6 +240,32 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Thu Oct 31 2013 Dan Walsh - 2.2-1 +- Update to upstream + * Fix avc_has_perm() returns -1 even when SELinux is in permissive mode. + * Support overriding Makefile RANLIB from Sven Vermeulen. + * Update pkgconfig definition from Sven Vermeulen. + * Mount sysfs before trying to mount selinuxfs from Sven Vermeulen. + * Fix man pages from Laurent Bigonville. + * Support overriding PATH and LIBBASE in Makefiles from Laurent Bigonville. + * Fix LDFLAGS usage from Laurent Bigonville + * Avoid shadowing stat in load_mmap from Joe MacDonald. + * Support building on older PCRE libraries from Joe MacDonald. + * Fix handling of temporary file in sefcontext_compile from Dan Walsh. + * Fix procattr cache from Dan Walsh. + * Define python constants for getenforce result from Dan Walsh. + * Fix label substitution handling of / from Dan Walsh. + * Add selinux_current_policy_path from Dan Walsh. + * Change get_context_list to only return good matches from Dan Walsh. + * Support udev-197 and higher from Sven Vermeulen and Dan Walsh. + * Add support for local substitutions from Dan Walsh. + * Change setfilecon to not return ENOSUP if context is already correct from Dan Walsh. + * Python wrapper leak fixes from Dan Walsh. + * Export SELINUX_TRANS_DIR definition in selinux.h from Dan Walsh. + * Add selinux_systemd_contexts_path from Dan Walsh. + * Add selinux_set_policy_root from Dan Walsh. + * Add man page for sefcontext_compile from Dan Walsh. + * 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 diff --git a/sources b/sources index 26ecd0d..c3fa66e 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -44be70732a33b8e1fbe2f422e93fb8b3 libselinux-2.1.13.tgz +a970226626784d4ee760fd848cc5ca91 libselinux-2.2.tgz From 5f9e3146a2bd4e0156d21f876fe257145a317f68 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 25 Nov 2013 15:24:16 -0500 Subject: [PATCH 05/12] Update to upstream * Remove -lpthread from pkg-config file; it is not required. --- .gitignore | 1 + libselinux-rhat.patch | 201 ++++++++++++++++++++++++++++++++++++++++++ libselinux.spec | 6 +- sources | 2 +- 4 files changed, 208 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c3bf9bd..2e9cec3 100644 --- a/.gitignore +++ b/.gitignore @@ -196,3 +196,4 @@ libselinux-2.0.96.tgz /libselinux-2.1.12.tgz /libselinux-2.1.13.tgz /libselinux-2.2.tgz +/libselinux-2.2.1.tgz diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 1789ec0..c43fe51 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,3 +1,204 @@ +diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile +index 02dd829..6dfdb46 100644 +--- a/libselinux/src/Makefile ++++ b/libselinux/src/Makefile +@@ -114,7 +114,7 @@ $(LIBA): $(OBJS) + $(RANLIB) $@ + + $(LIBSO): $(LOBJS) +- $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro ++ $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -llzma -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro + ln -sf $@ $(TARGET) + + $(LIBPC): $(LIBPC).in ../VERSION +diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c +index e419f1a..fdeca93 100644 +--- a/libselinux/src/load_policy.c ++++ b/libselinux/src/load_policy.c +@@ -16,6 +16,82 @@ + #include + #include "policy.h" + #include ++#include ++ ++static char *lzmaread(int fd, size_t *rsize) { ++ int capacity = 64*1024; ++ char *buf = NULL; ++ int tmpsize = 8 * 1024; ++ unsigned char tmp[tmpsize]; ++ unsigned char tmp_out[tmpsize]; ++ size_t size = 0; ++ lzma_stream strm = LZMA_STREAM_INIT; ++ lzma_action action = LZMA_RUN; ++ lzma_ret ret; ++ ++ FILE *stream = fdopen (fd, "r"); ++ if (!stream) { ++ return NULL; ++ } ++ ret = lzma_stream_decoder(&strm, UINT64_MAX, ++ LZMA_CONCATENATED); ++ ++ strm.avail_in = 0; ++ strm.next_out = tmp_out; ++ strm.avail_out = tmpsize; ++ ++ buf = (char *) malloc (capacity); ++ if (!buf) ++ goto err; ++ ++ while (1) { ++ if (strm.avail_in == 0) { ++ strm.next_in = tmp; ++ strm.avail_in = fread(tmp, 1, tmpsize, stream); ++ ++ if (ferror(stream)) { ++ // POSIX says that fread() sets errno if ++ // an error occurred. ferror() doesn't ++ // touch errno. ++ goto err; ++ } ++ if (feof(stream)) action = LZMA_FINISH; ++ } ++ ++ ret = lzma_code(&strm, action); ++ ++ // Write and check write error before checking decoder error. ++ // This way as much data as possible gets written to output ++ // even if decoder detected an error. ++ if (strm.avail_out == 0 || ret != LZMA_OK) { ++ const size_t num = tmpsize - strm.avail_out; ++ if (num > capacity) { ++ buf = (char*) realloc (buf, size*2); ++ capacity = size; ++ } ++ memcpy (buf+size, tmp_out, num); ++ capacity -= num; ++ size += num; ++ strm.next_out = tmp_out; ++ strm.avail_out = tmpsize; ++ } ++ if (ret != LZMA_OK) { ++ if (ret == LZMA_STREAM_END) { ++ break; ++ } else { ++ goto err; ++ } ++ } ++ } ++ *rsize = size; ++ ++ goto exit; ++err: ++ free(buf); buf = NULL; ++exit: ++ lzma_end(&strm); ++ return buf; ++} + + int security_load_policy(void *data, size_t len) + { +@@ -55,7 +131,7 @@ int selinux_mkload_policy(int preservebools) + struct stat sb; + struct utsname uts; + size_t size; +- void *map, *data; ++ void *map = NULL, *data=NULL; + int fd, rc = -1, prot; + sepol_policydb_t *policydb; + sepol_policy_file_t *pf; +@@ -181,24 +257,28 @@ checkbool: + goto dlclose; + } + +- if (fstat(fd, &sb) < 0) { +- fprintf(stderr, +- "SELinux: Could not stat policy file %s: %s\n", +- path, strerror(errno)); +- goto close; +- } +- +- prot = PROT_READ; +- if (setlocaldefs || preservebools) +- prot |= PROT_WRITE; ++ data = lzmaread(fd,&size); + +- 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", ++ if (!data) { ++ if (fstat(fd, &sb) < 0) { ++ fprintf(stderr, ++ "SELinux: Could not stat policy file %s: %s\n", + path, strerror(errno)); +- goto close; ++ goto close; ++ } ++ ++ prot = PROT_READ; ++ if (setlocaldefs || preservebools) ++ prot |= PROT_WRITE; ++ ++ 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)); ++ goto close; ++ } + } + + if (vers > kernvers && usesepol) { +@@ -210,6 +290,8 @@ checkbool: + goto unmap; + } + policy_file_set_mem(pf, data, size); ++ if (!map) ++ free(data); + if (policydb_read(policydb, pf)) { + policy_file_free(pf); + policydb_free(policydb); +@@ -223,7 +305,8 @@ checkbool: + path); + policy_file_free(pf); + policydb_free(policydb); +- munmap(map, sb.st_size); ++ if (map) ++ munmap(map, sb.st_size); + close(fd); + vers--; + goto search; +@@ -275,7 +358,7 @@ checkbool: + #endif + } + +- ++ + rc = security_load_policy(data, size); + + if (rc) +@@ -286,7 +369,8 @@ checkbool: + unmap: + if (data != map) + free(data); +- munmap(map, sb.st_size); ++ if (map) ++ munmap(map, sb.st_size); + close: + close(fd); + dlclose: +@@ -410,7 +494,7 @@ int selinux_init_load_policy(int *enforce) + * already mounted and selinuxmnt set above. + */ + +- if (seconfig == -1) { ++ if (*enforce == -1) { + /* Runtime disable of SELinux. */ + rc = security_disable(); + if (rc == 0) { diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 2d7369e..2a00807 100644 --- a/libselinux/src/matchpathcon.c diff --git a/libselinux.spec b/libselinux.spec index 40773ec..2403b2d 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -9,7 +9,7 @@ Summary: SELinux library and simple utilities Name: libselinux -Version: 2.2 +Version: 2.2.1 Release: 1%{?dist} License: Public Domain Group: System Environment/Libraries @@ -240,6 +240,10 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Mon Nov 25 2013 Dan Walsh - 2.2.1-1 +- Update to upstream + * Remove -lpthread from pkg-config file; it is not required. + * Thu Oct 31 2013 Dan Walsh - 2.2-1 - Update to upstream * Fix avc_has_perm() returns -1 even when SELinux is in permissive mode. diff --git a/sources b/sources index c3fa66e..0d56678 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -a970226626784d4ee760fd848cc5ca91 libselinux-2.2.tgz +ada793adfb5683672f9cc8a99447939d libselinux-2.2.1.tgz From d6f11ce40d7cb8b902766121e19b58ef75f5890f Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 25 Nov 2013 15:49:35 -0500 Subject: [PATCH 06/12] Update to upstream * Remove -lpthread from pkg-config file; it is not required. - Add support for policy compressed with xv --- libselinux.spec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libselinux.spec b/libselinux.spec index 2403b2d..fdfa7d8 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -18,7 +18,7 @@ Source1: selinuxconlist.8 Source2: selinuxdefcon.8 Url: http://oss.tresys.com/git/selinux.git Patch1: libselinux-rhat.patch -BuildRequires: pkgconfig python-devel ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre-devel +BuildRequires: pkgconfig python-devel ruby-devel ruby libsepol-static >= %{libsepolver} swig pcre-devel xz-devel %if 0%{?with_python3} BuildRequires: python3-devel %endif # if with_python3 @@ -243,6 +243,7 @@ rm -rf %{buildroot} * Mon Nov 25 2013 Dan Walsh - 2.2.1-1 - Update to upstream * Remove -lpthread from pkg-config file; it is not required. +- Add support for policy compressed with xv * Thu Oct 31 2013 Dan Walsh - 2.2-1 - Update to upstream From 0662ba4d16646a494fbd3d96d9d28048c4253b95 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Thu, 5 Dec 2013 15:44:38 -0500 Subject: [PATCH 07/12] Remove togglesebool man page --- libselinux.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libselinux.spec b/libselinux.spec index fdfa7d8..680370b 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.2.1 -Release: 1%{?dist} +Release: 2%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -179,6 +179,7 @@ mv %{buildroot}%{_sbindir}/getconlist %{buildroot}%{_sbindir}/selinuxconlist install -d %{buildroot}%{_mandir}/man8/ install -m 644 %{SOURCE1} %{buildroot}%{_mandir}/man8/ install -m 644 %{SOURCE2} %{buildroot}%{_mandir}/man8/ +rm -f %{buildroot}%{_mandir}/man8/togglesebool* %clean rm -rf %{buildroot} @@ -240,6 +241,9 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Thu Dec 5 2013 Dan Walsh - 2.2.1-2 +- Remove togglesebool man page + * Mon Nov 25 2013 Dan Walsh - 2.2.1-1 - Update to upstream * Remove -lpthread from pkg-config file; it is not required. From 15fa31b994eb5f4b6f3c57e20c0a2ebd544c3b11 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Tue, 17 Dec 2013 11:07:44 -0500 Subject: [PATCH 08/12] Add golang support to libselinux --- libselinux-rhat.patch | 321 ++++++++++++++++++++++++++++++++++++++++++ libselinux.spec | 5 +- 2 files changed, 325 insertions(+), 1 deletion(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index c43fe51..ef89420 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,3 +1,324 @@ +diff --git a/libselinux/Makefile b/libselinux/Makefile +index fd4f0b1..51469bc 100644 +--- a/libselinux/Makefile ++++ b/libselinux/Makefile +@@ -1,4 +1,4 @@ +-SUBDIRS = src include utils man ++SUBDIRS = src include utils man golang + + DISABLE_AVC ?= n + DISABLE_SETRANS ?= n +diff --git a/libselinux/golang/Makefile b/libselinux/golang/Makefile +new file mode 100644 +index 0000000..a5f0692 +--- /dev/null ++++ b/libselinux/golang/Makefile +@@ -0,0 +1,17 @@ ++# Installation directories. ++PREFIX ?= $(DESTDIR)/usr ++GODIR ?= $(PREFIX)/share/gocode/selinux ++ ++all: ++ ++install: ++ [ -d $(GODIR) ] || mkdir -p $(GODIR) ++ install -m 644 selinux.go $(GODIR) ++ ++test: ++ ++clean: ++ ++indent: ++ ++relabel: +diff --git a/libselinux/golang/selinux.go b/libselinux/golang/selinux.go +new file mode 100644 +index 0000000..018c955 +--- /dev/null ++++ b/libselinux/golang/selinux.go +@@ -0,0 +1,282 @@ ++package selinux ++ ++/* ++ The selinux package is a go bindings to libselinux required to add selinux ++ support to docker. ++ ++ Author Dan Walsh ++ ++ Used some ideas/code from the go-ini packages https://github.com/vaughan0 ++ By Vaughan Newton ++*/ ++ ++// #cgo pkg-config: libselinux ++// #include ++// #include ++import "C" ++import ( ++ "encoding/binary" ++ "crypto/rand" ++ "unsafe" ++ "fmt" ++ "bufio" ++ "regexp" ++ "io" ++ "os" ++ "strings" ++) ++ ++var ( ++ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) ++ mcs_list = make(map[string]bool) ++) ++ ++func Matchpathcon(path string, mode int) (string, error) { ++ var con C.security_context_t ++ var scon string ++ rc, err := C.matchpathcon(C.CString(path),C.mode_t(mode), &con) ++ if rc == 0 { ++ scon = C.GoString(con) ++ C.free(unsafe.Pointer(con)) ++ } ++ return scon, err ++} ++ ++func Setfilecon(path,scon string) (int, error) { ++ rc, err := C.lsetfilecon(C.CString(path),C.CString(scon)) ++ return int(rc), err ++} ++ ++func Setexeccon(scon string) (int, error) { ++ var val *C.char ++ if ! Selinux_enabled() { ++ return 0, nil ++ } ++ if scon != "" { ++ val = C.CString(scon) ++ } else { ++ val = nil ++ } ++ rc, err := C.setexeccon(val) ++ return int(rc), err ++} ++ ++type Context struct { ++ con []string ++} ++func (c *Context) Set_user(user string) { ++ c.con[0]=user ++} ++func (c *Context) Get_user() string { ++ return c.con[0] ++} ++func (c *Context) Set_role(role string) { ++ c.con[1]=role ++} ++func (c *Context) Get_role() string { ++ return c.con[1] ++} ++func (c *Context) Set_type(setype string) { ++ c.con[2]=setype ++} ++func (c *Context) Get_type() string { ++ return c.con[2] ++} ++func (c *Context) Set_level(mls string) { ++ c.con[3]=mls ++} ++func (c *Context) Get_level() string { ++ return c.con[3] ++} ++func (c *Context) Get() string{ ++ return strings.Join(c.con,":") ++} ++func (c *Context) Set(scon string) { ++ c.con = strings.SplitN(scon,":",4) ++} ++func New_context(scon string) Context { ++ var con Context ++ con.Set(scon) ++ return con ++} ++ ++func Is_selinux_enabled() bool { ++ b := C.is_selinux_enabled() ++ if b > 0 { ++ return true; ++ } ++ return false ++} ++ ++func Selinux_enabled() bool { ++ b := C.is_selinux_enabled() ++ if b > 0 { ++ return true; ++ } ++ return false ++} ++ ++const ( ++ Enforcing = 1 ++ Permissive = 0 ++ Disabled = -1 ++) ++ ++func Selinux_getenforce() int { ++ return int(C.security_getenforce()) ++} ++ ++func Selinux_getenforcemode() (int) { ++ var enforce C.int ++ C.selinux_getenforcemode(&enforce) ++ return int(enforce) ++} ++ ++func mcs_add(mcs string) { ++ mcs_list[mcs] = true ++} ++ ++func mcs_delete(mcs string) { ++ mcs_list[mcs] = false ++} ++ ++func mcs_exists(mcs string) bool { ++ return mcs_list[mcs] ++} ++ ++func uniq_mcs(catRange uint32) string { ++ var n uint32 ++ var c1,c2 uint32 ++ var mcs string ++ for ;; { ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c1 = n % catRange ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c2 = n % catRange ++ if c1 == c2 { ++ continue ++ } else { ++ if c1 > c2 { ++ t := c1 ++ c1 = c2 ++ c2 = t ++ } ++ } ++ mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) ++ if mcs_exists(mcs) { ++ continue ++ } ++ mcs_add(mcs) ++ break ++ } ++ return mcs ++} ++func free_context(process_label string) { ++ var scon Context ++ scon = New_context(process_label) ++ mcs_delete(scon.Get_level()) ++} ++ ++func Get_lxc_contexts() (process_label string, file_label string) { ++ var val, key string ++ var bufin *bufio.Reader ++ if ! Selinux_enabled() { ++ return ++ } ++ lxc_path := C.GoString(C.selinux_lxc_contexts_path()) ++ file_label = "system_u:object_r:svirt_sandbox_file_t:s0" ++ process_label = "system_u:system_r:svirt_lxc_net_t:s0" ++ ++ in, err := os.Open(lxc_path) ++ if err != nil { ++ goto exit ++ } ++ ++ defer in.Close() ++ bufin = bufio.NewReader(in) ++ ++ for done := false; !done; { ++ var line string ++ if line, err = bufin.ReadString('\n'); err != nil { ++ if err == io.EOF { ++ done = true ++ } else { ++ goto exit ++ } ++ } ++ line = strings.TrimSpace(line) ++ if len(line) == 0 { ++ // Skip blank lines ++ continue ++ } ++ if line[0] == ';' || line[0] == '#' { ++ // Skip comments ++ continue ++ } ++ if groups := assignRegex.FindStringSubmatch(line); groups != nil { ++ key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) ++ if key == "process" { ++ process_label = strings.Trim(val,"\"") ++ } ++ if key == "file" { ++ file_label = strings.Trim(val,"\"") ++ } ++ } ++ } ++exit: ++ var scon Context ++ mcs := uniq_mcs(1024) ++ scon = New_context(process_label) ++ scon.Set_level(mcs) ++ process_label = scon.Get() ++ scon = New_context(file_label) ++ scon.Set_level(mcs) ++ file_label = scon.Get() ++ return process_label, file_label ++} ++ ++func CopyLevel (src, dest string) (string, error) { ++ if ! Selinux_enabled() { ++ return "", nil ++ } ++ if src == "" { ++ return "", nil ++ } ++ rc, err := C.security_check_context(C.CString(src)) ++ if rc != 0 { ++ return "", err ++ } ++ rc, err = C.security_check_context(C.CString(dest)) ++ if rc != 0 { ++ return "", err ++ } ++ scon := New_context(src) ++ tcon := New_context(dest) ++ tcon.Set_level(scon.Get_level()) ++ return tcon.Get(), nil ++} ++ ++func Test() { ++ var plabel,flabel string ++ if ! Selinux_enabled() { ++ return ++ } ++ ++ plabel, flabel = Get_lxc_contexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ free_context(plabel) ++ plabel, flabel = Get_lxc_contexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ free_context(plabel) ++ if Selinux_enabled() { ++ fmt.Println("Enabled") ++ } else { ++ fmt.Println("Disabled") ++ } ++ fmt.Println(Selinux_getenforce()) ++ fmt.Println(Selinux_getenforcemode()) ++ flabel,_ = Matchpathcon("/home/dwalsh/.emacs", 0) ++ fmt.Println(flabel) ++} diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 02dd829..6dfdb46 100644 --- a/libselinux/src/Makefile diff --git a/libselinux.spec b/libselinux.spec index 680370b..51fc680 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.2.1 -Release: 2%{?dist} +Release: 3%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -241,6 +241,9 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Tue Dec 17 2013 Dan Walsh - 2.2.1-3 +- Add golang support to selinux. + * Thu Dec 5 2013 Dan Walsh - 2.2.1-2 - Remove togglesebool man page From e79a10d304bcce6a3fea0734f219261bc1db9f13 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Tue, 17 Dec 2013 11:21:42 -0500 Subject: [PATCH 09/12] Add golang support to selinux. --- libselinux.spec | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libselinux.spec b/libselinux.spec index 51fc680..db3b12c 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -214,6 +214,8 @@ rm -rf %{buildroot} %{_libdir}/libselinux.so %{_libdir}/pkgconfig/libselinux.pc %dir %{_includedir}/selinux +%dir %{_datadir}/gocode/selinux +%{_datadir}/gocode/selinux/selinux.go %{_includedir}/selinux/* %{_mandir}/man3/* From f4752d088274eaed8d3817ff339d7fa67dc97075 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Wed, 18 Dec 2013 14:40:49 -0500 Subject: [PATCH 10/12] Mv selinux.go to /usr/share/gocode/src/selinux --- libselinux-rhat.patch | 4 ++-- libselinux.spec | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index ef89420..bf75861 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -10,13 +10,13 @@ index fd4f0b1..51469bc 100644 DISABLE_SETRANS ?= n diff --git a/libselinux/golang/Makefile b/libselinux/golang/Makefile new file mode 100644 -index 0000000..a5f0692 +index 0000000..e0be66f --- /dev/null +++ b/libselinux/golang/Makefile @@ -0,0 +1,17 @@ +# Installation directories. +PREFIX ?= $(DESTDIR)/usr -+GODIR ?= $(PREFIX)/share/gocode/selinux ++GODIR ?= $(PREFIX)/share/gocode/src/selinux + +all: + diff --git a/libselinux.spec b/libselinux.spec index db3b12c..ce9b775 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.2.1 -Release: 3%{?dist} +Release: 4%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -214,8 +214,8 @@ rm -rf %{buildroot} %{_libdir}/libselinux.so %{_libdir}/pkgconfig/libselinux.pc %dir %{_includedir}/selinux -%dir %{_datadir}/gocode/selinux -%{_datadir}/gocode/selinux/selinux.go +%dir %{_datadir}/gocode/src/selinux +%{_datadir}/gocode/src/selinux/selinux.go %{_includedir}/selinux/* %{_mandir}/man3/* @@ -243,6 +243,9 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Wed Dec 18 2013 Dan Walsh - 2.2.1-4 +- Mv selinux.go to /usr/share/gocode/src/selinux + * Tue Dec 17 2013 Dan Walsh - 2.2.1-3 - Add golang support to selinux. From e61de3d8f05d2d2bd3ffc452f24b46c8f866f549 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 23 Dec 2013 09:53:25 -0500 Subject: [PATCH 11/12] Verify context is not null when passed into lsetfilecon_raw --- libselinux-rhat.patch | 340 +++--------------------------------------- libselinux.spec | 5 +- 2 files changed, 23 insertions(+), 322 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index bf75861..4a55e0a 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,324 +1,3 @@ -diff --git a/libselinux/Makefile b/libselinux/Makefile -index fd4f0b1..51469bc 100644 ---- a/libselinux/Makefile -+++ b/libselinux/Makefile -@@ -1,4 +1,4 @@ --SUBDIRS = src include utils man -+SUBDIRS = src include utils man golang - - DISABLE_AVC ?= n - DISABLE_SETRANS ?= n -diff --git a/libselinux/golang/Makefile b/libselinux/golang/Makefile -new file mode 100644 -index 0000000..e0be66f ---- /dev/null -+++ b/libselinux/golang/Makefile -@@ -0,0 +1,17 @@ -+# Installation directories. -+PREFIX ?= $(DESTDIR)/usr -+GODIR ?= $(PREFIX)/share/gocode/src/selinux -+ -+all: -+ -+install: -+ [ -d $(GODIR) ] || mkdir -p $(GODIR) -+ install -m 644 selinux.go $(GODIR) -+ -+test: -+ -+clean: -+ -+indent: -+ -+relabel: -diff --git a/libselinux/golang/selinux.go b/libselinux/golang/selinux.go -new file mode 100644 -index 0000000..018c955 ---- /dev/null -+++ b/libselinux/golang/selinux.go -@@ -0,0 +1,282 @@ -+package selinux -+ -+/* -+ The selinux package is a go bindings to libselinux required to add selinux -+ support to docker. -+ -+ Author Dan Walsh -+ -+ Used some ideas/code from the go-ini packages https://github.com/vaughan0 -+ By Vaughan Newton -+*/ -+ -+// #cgo pkg-config: libselinux -+// #include -+// #include -+import "C" -+import ( -+ "encoding/binary" -+ "crypto/rand" -+ "unsafe" -+ "fmt" -+ "bufio" -+ "regexp" -+ "io" -+ "os" -+ "strings" -+) -+ -+var ( -+ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) -+ mcs_list = make(map[string]bool) -+) -+ -+func Matchpathcon(path string, mode int) (string, error) { -+ var con C.security_context_t -+ var scon string -+ rc, err := C.matchpathcon(C.CString(path),C.mode_t(mode), &con) -+ if rc == 0 { -+ scon = C.GoString(con) -+ C.free(unsafe.Pointer(con)) -+ } -+ return scon, err -+} -+ -+func Setfilecon(path,scon string) (int, error) { -+ rc, err := C.lsetfilecon(C.CString(path),C.CString(scon)) -+ return int(rc), err -+} -+ -+func Setexeccon(scon string) (int, error) { -+ var val *C.char -+ if ! Selinux_enabled() { -+ return 0, nil -+ } -+ if scon != "" { -+ val = C.CString(scon) -+ } else { -+ val = nil -+ } -+ rc, err := C.setexeccon(val) -+ return int(rc), err -+} -+ -+type Context struct { -+ con []string -+} -+func (c *Context) Set_user(user string) { -+ c.con[0]=user -+} -+func (c *Context) Get_user() string { -+ return c.con[0] -+} -+func (c *Context) Set_role(role string) { -+ c.con[1]=role -+} -+func (c *Context) Get_role() string { -+ return c.con[1] -+} -+func (c *Context) Set_type(setype string) { -+ c.con[2]=setype -+} -+func (c *Context) Get_type() string { -+ return c.con[2] -+} -+func (c *Context) Set_level(mls string) { -+ c.con[3]=mls -+} -+func (c *Context) Get_level() string { -+ return c.con[3] -+} -+func (c *Context) Get() string{ -+ return strings.Join(c.con,":") -+} -+func (c *Context) Set(scon string) { -+ c.con = strings.SplitN(scon,":",4) -+} -+func New_context(scon string) Context { -+ var con Context -+ con.Set(scon) -+ return con -+} -+ -+func Is_selinux_enabled() bool { -+ b := C.is_selinux_enabled() -+ if b > 0 { -+ return true; -+ } -+ return false -+} -+ -+func Selinux_enabled() bool { -+ b := C.is_selinux_enabled() -+ if b > 0 { -+ return true; -+ } -+ return false -+} -+ -+const ( -+ Enforcing = 1 -+ Permissive = 0 -+ Disabled = -1 -+) -+ -+func Selinux_getenforce() int { -+ return int(C.security_getenforce()) -+} -+ -+func Selinux_getenforcemode() (int) { -+ var enforce C.int -+ C.selinux_getenforcemode(&enforce) -+ return int(enforce) -+} -+ -+func mcs_add(mcs string) { -+ mcs_list[mcs] = true -+} -+ -+func mcs_delete(mcs string) { -+ mcs_list[mcs] = false -+} -+ -+func mcs_exists(mcs string) bool { -+ return mcs_list[mcs] -+} -+ -+func uniq_mcs(catRange uint32) string { -+ var n uint32 -+ var c1,c2 uint32 -+ var mcs string -+ for ;; { -+ binary.Read(rand.Reader, binary.LittleEndian, &n) -+ c1 = n % catRange -+ binary.Read(rand.Reader, binary.LittleEndian, &n) -+ c2 = n % catRange -+ if c1 == c2 { -+ continue -+ } else { -+ if c1 > c2 { -+ t := c1 -+ c1 = c2 -+ c2 = t -+ } -+ } -+ mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) -+ if mcs_exists(mcs) { -+ continue -+ } -+ mcs_add(mcs) -+ break -+ } -+ return mcs -+} -+func free_context(process_label string) { -+ var scon Context -+ scon = New_context(process_label) -+ mcs_delete(scon.Get_level()) -+} -+ -+func Get_lxc_contexts() (process_label string, file_label string) { -+ var val, key string -+ var bufin *bufio.Reader -+ if ! Selinux_enabled() { -+ return -+ } -+ lxc_path := C.GoString(C.selinux_lxc_contexts_path()) -+ file_label = "system_u:object_r:svirt_sandbox_file_t:s0" -+ process_label = "system_u:system_r:svirt_lxc_net_t:s0" -+ -+ in, err := os.Open(lxc_path) -+ if err != nil { -+ goto exit -+ } -+ -+ defer in.Close() -+ bufin = bufio.NewReader(in) -+ -+ for done := false; !done; { -+ var line string -+ if line, err = bufin.ReadString('\n'); err != nil { -+ if err == io.EOF { -+ done = true -+ } else { -+ goto exit -+ } -+ } -+ line = strings.TrimSpace(line) -+ if len(line) == 0 { -+ // Skip blank lines -+ continue -+ } -+ if line[0] == ';' || line[0] == '#' { -+ // Skip comments -+ continue -+ } -+ if groups := assignRegex.FindStringSubmatch(line); groups != nil { -+ key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) -+ if key == "process" { -+ process_label = strings.Trim(val,"\"") -+ } -+ if key == "file" { -+ file_label = strings.Trim(val,"\"") -+ } -+ } -+ } -+exit: -+ var scon Context -+ mcs := uniq_mcs(1024) -+ scon = New_context(process_label) -+ scon.Set_level(mcs) -+ process_label = scon.Get() -+ scon = New_context(file_label) -+ scon.Set_level(mcs) -+ file_label = scon.Get() -+ return process_label, file_label -+} -+ -+func CopyLevel (src, dest string) (string, error) { -+ if ! Selinux_enabled() { -+ return "", nil -+ } -+ if src == "" { -+ return "", nil -+ } -+ rc, err := C.security_check_context(C.CString(src)) -+ if rc != 0 { -+ return "", err -+ } -+ rc, err = C.security_check_context(C.CString(dest)) -+ if rc != 0 { -+ return "", err -+ } -+ scon := New_context(src) -+ tcon := New_context(dest) -+ tcon.Set_level(scon.Get_level()) -+ return tcon.Get(), nil -+} -+ -+func Test() { -+ var plabel,flabel string -+ if ! Selinux_enabled() { -+ return -+ } -+ -+ plabel, flabel = Get_lxc_contexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ free_context(plabel) -+ plabel, flabel = Get_lxc_contexts() -+ fmt.Println(plabel) -+ fmt.Println(flabel) -+ free_context(plabel) -+ if Selinux_enabled() { -+ fmt.Println("Enabled") -+ } else { -+ fmt.Println("Disabled") -+ } -+ fmt.Println(Selinux_getenforce()) -+ fmt.Println(Selinux_getenforcemode()) -+ flabel,_ = Matchpathcon("/home/dwalsh/.emacs", 0) -+ fmt.Println(flabel) -+} diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 02dd829..6dfdb46 100644 --- a/libselinux/src/Makefile @@ -520,6 +199,25 @@ index e419f1a..fdeca93 100644 /* Runtime disable of SELinux. */ rc = security_disable(); if (rc == 0) { +diff --git a/libselinux/src/lsetfilecon.c b/libselinux/src/lsetfilecon.c +index fd9bb26..932fc62 100644 +--- a/libselinux/src/lsetfilecon.c ++++ b/libselinux/src/lsetfilecon.c +@@ -9,7 +9,13 @@ + + int lsetfilecon_raw(const char *path, const security_context_t context) + { +- int rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, ++ int rc; ++ if (! context) { ++ errno=EINVAL; ++ return -1; ++ } ++ ++ rc = lsetxattr(path, XATTR_NAME_SELINUX, context, strlen(context) + 1, + 0); + if (rc < 0 && errno == ENOTSUP) { + security_context_t ccontext = NULL; diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 2d7369e..2a00807 100644 --- a/libselinux/src/matchpathcon.c diff --git a/libselinux.spec b/libselinux.spec index ce9b775..9c86123 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.2.1 -Release: 4%{?dist} +Release: 5%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -243,6 +243,9 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Mon Dec 23 2013 Dan Walsh - 2.2.1-5 +- Verify context is not null when passed into lsetfilecon_raw + * Wed Dec 18 2013 Dan Walsh - 2.2.1-4 - Mv selinux.go to /usr/share/gocode/src/selinux From 99813aab598de70ab744fe5b7478db92425c9d33 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Mon, 23 Dec 2013 10:14:52 -0500 Subject: [PATCH 12/12] Verify context is not null when passed into lsetfilecon_raw --- libselinux-rhat.patch | 321 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 4a55e0a..89dd991 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,3 +1,324 @@ +diff --git a/libselinux/Makefile b/libselinux/Makefile +index fd4f0b1..51469bc 100644 +--- a/libselinux/Makefile ++++ b/libselinux/Makefile +@@ -1,4 +1,4 @@ +-SUBDIRS = src include utils man ++SUBDIRS = src include utils man golang + + DISABLE_AVC ?= n + DISABLE_SETRANS ?= n +diff --git a/libselinux/golang/Makefile b/libselinux/golang/Makefile +new file mode 100644 +index 0000000..e0be66f +--- /dev/null ++++ b/libselinux/golang/Makefile +@@ -0,0 +1,17 @@ ++# Installation directories. ++PREFIX ?= $(DESTDIR)/usr ++GODIR ?= $(PREFIX)/share/gocode/src/selinux ++ ++all: ++ ++install: ++ [ -d $(GODIR) ] || mkdir -p $(GODIR) ++ install -m 644 selinux.go $(GODIR) ++ ++test: ++ ++clean: ++ ++indent: ++ ++relabel: +diff --git a/libselinux/golang/selinux.go b/libselinux/golang/selinux.go +new file mode 100644 +index 0000000..018c955 +--- /dev/null ++++ b/libselinux/golang/selinux.go +@@ -0,0 +1,282 @@ ++package selinux ++ ++/* ++ The selinux package is a go bindings to libselinux required to add selinux ++ support to docker. ++ ++ Author Dan Walsh ++ ++ Used some ideas/code from the go-ini packages https://github.com/vaughan0 ++ By Vaughan Newton ++*/ ++ ++// #cgo pkg-config: libselinux ++// #include ++// #include ++import "C" ++import ( ++ "encoding/binary" ++ "crypto/rand" ++ "unsafe" ++ "fmt" ++ "bufio" ++ "regexp" ++ "io" ++ "os" ++ "strings" ++) ++ ++var ( ++ assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`) ++ mcs_list = make(map[string]bool) ++) ++ ++func Matchpathcon(path string, mode int) (string, error) { ++ var con C.security_context_t ++ var scon string ++ rc, err := C.matchpathcon(C.CString(path),C.mode_t(mode), &con) ++ if rc == 0 { ++ scon = C.GoString(con) ++ C.free(unsafe.Pointer(con)) ++ } ++ return scon, err ++} ++ ++func Setfilecon(path,scon string) (int, error) { ++ rc, err := C.lsetfilecon(C.CString(path),C.CString(scon)) ++ return int(rc), err ++} ++ ++func Setexeccon(scon string) (int, error) { ++ var val *C.char ++ if ! Selinux_enabled() { ++ return 0, nil ++ } ++ if scon != "" { ++ val = C.CString(scon) ++ } else { ++ val = nil ++ } ++ rc, err := C.setexeccon(val) ++ return int(rc), err ++} ++ ++type Context struct { ++ con []string ++} ++func (c *Context) Set_user(user string) { ++ c.con[0]=user ++} ++func (c *Context) Get_user() string { ++ return c.con[0] ++} ++func (c *Context) Set_role(role string) { ++ c.con[1]=role ++} ++func (c *Context) Get_role() string { ++ return c.con[1] ++} ++func (c *Context) Set_type(setype string) { ++ c.con[2]=setype ++} ++func (c *Context) Get_type() string { ++ return c.con[2] ++} ++func (c *Context) Set_level(mls string) { ++ c.con[3]=mls ++} ++func (c *Context) Get_level() string { ++ return c.con[3] ++} ++func (c *Context) Get() string{ ++ return strings.Join(c.con,":") ++} ++func (c *Context) Set(scon string) { ++ c.con = strings.SplitN(scon,":",4) ++} ++func New_context(scon string) Context { ++ var con Context ++ con.Set(scon) ++ return con ++} ++ ++func Is_selinux_enabled() bool { ++ b := C.is_selinux_enabled() ++ if b > 0 { ++ return true; ++ } ++ return false ++} ++ ++func Selinux_enabled() bool { ++ b := C.is_selinux_enabled() ++ if b > 0 { ++ return true; ++ } ++ return false ++} ++ ++const ( ++ Enforcing = 1 ++ Permissive = 0 ++ Disabled = -1 ++) ++ ++func Selinux_getenforce() int { ++ return int(C.security_getenforce()) ++} ++ ++func Selinux_getenforcemode() (int) { ++ var enforce C.int ++ C.selinux_getenforcemode(&enforce) ++ return int(enforce) ++} ++ ++func mcs_add(mcs string) { ++ mcs_list[mcs] = true ++} ++ ++func mcs_delete(mcs string) { ++ mcs_list[mcs] = false ++} ++ ++func mcs_exists(mcs string) bool { ++ return mcs_list[mcs] ++} ++ ++func uniq_mcs(catRange uint32) string { ++ var n uint32 ++ var c1,c2 uint32 ++ var mcs string ++ for ;; { ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c1 = n % catRange ++ binary.Read(rand.Reader, binary.LittleEndian, &n) ++ c2 = n % catRange ++ if c1 == c2 { ++ continue ++ } else { ++ if c1 > c2 { ++ t := c1 ++ c1 = c2 ++ c2 = t ++ } ++ } ++ mcs = fmt.Sprintf("s0:c%d,c%d", c1, c2) ++ if mcs_exists(mcs) { ++ continue ++ } ++ mcs_add(mcs) ++ break ++ } ++ return mcs ++} ++func free_context(process_label string) { ++ var scon Context ++ scon = New_context(process_label) ++ mcs_delete(scon.Get_level()) ++} ++ ++func Get_lxc_contexts() (process_label string, file_label string) { ++ var val, key string ++ var bufin *bufio.Reader ++ if ! Selinux_enabled() { ++ return ++ } ++ lxc_path := C.GoString(C.selinux_lxc_contexts_path()) ++ file_label = "system_u:object_r:svirt_sandbox_file_t:s0" ++ process_label = "system_u:system_r:svirt_lxc_net_t:s0" ++ ++ in, err := os.Open(lxc_path) ++ if err != nil { ++ goto exit ++ } ++ ++ defer in.Close() ++ bufin = bufio.NewReader(in) ++ ++ for done := false; !done; { ++ var line string ++ if line, err = bufin.ReadString('\n'); err != nil { ++ if err == io.EOF { ++ done = true ++ } else { ++ goto exit ++ } ++ } ++ line = strings.TrimSpace(line) ++ if len(line) == 0 { ++ // Skip blank lines ++ continue ++ } ++ if line[0] == ';' || line[0] == '#' { ++ // Skip comments ++ continue ++ } ++ if groups := assignRegex.FindStringSubmatch(line); groups != nil { ++ key, val = strings.TrimSpace(groups[1]), strings.TrimSpace(groups[2]) ++ if key == "process" { ++ process_label = strings.Trim(val,"\"") ++ } ++ if key == "file" { ++ file_label = strings.Trim(val,"\"") ++ } ++ } ++ } ++exit: ++ var scon Context ++ mcs := uniq_mcs(1024) ++ scon = New_context(process_label) ++ scon.Set_level(mcs) ++ process_label = scon.Get() ++ scon = New_context(file_label) ++ scon.Set_level(mcs) ++ file_label = scon.Get() ++ return process_label, file_label ++} ++ ++func CopyLevel (src, dest string) (string, error) { ++ if ! Selinux_enabled() { ++ return "", nil ++ } ++ if src == "" { ++ return "", nil ++ } ++ rc, err := C.security_check_context(C.CString(src)) ++ if rc != 0 { ++ return "", err ++ } ++ rc, err = C.security_check_context(C.CString(dest)) ++ if rc != 0 { ++ return "", err ++ } ++ scon := New_context(src) ++ tcon := New_context(dest) ++ tcon.Set_level(scon.Get_level()) ++ return tcon.Get(), nil ++} ++ ++func Test() { ++ var plabel,flabel string ++ if ! Selinux_enabled() { ++ return ++ } ++ ++ plabel, flabel = Get_lxc_contexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ free_context(plabel) ++ plabel, flabel = Get_lxc_contexts() ++ fmt.Println(plabel) ++ fmt.Println(flabel) ++ free_context(plabel) ++ if Selinux_enabled() { ++ fmt.Println("Enabled") ++ } else { ++ fmt.Println("Disabled") ++ } ++ fmt.Println(Selinux_getenforce()) ++ fmt.Println(Selinux_getenforcemode()) ++ flabel,_ = Matchpathcon("/home/dwalsh/.emacs", 0) ++ fmt.Println(flabel) ++} diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 02dd829..6dfdb46 100644 --- a/libselinux/src/Makefile