From 5e85dc35bb6da71a925401cc5469f6a5e5ec0d6f Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Thu, 14 Feb 2013 07:59:56 -0500 Subject: [PATCH] Revert some changes which are causing the wrong policy version file to be created --- libselinux-rhat.patch | 2470 ++++++++++++++++++++++++++++++++++++----- libselinux.spec | 5 +- 2 files changed, 2189 insertions(+), 286 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index 6531ddd..16d56c7 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,111 +1,8 @@ -diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index a4079aa..aba6e33 100644 ---- a/libselinux/include/selinux/selinux.h -+++ b/libselinux/include/selinux/selinux.h -@@ -498,7 +498,9 @@ extern const char *selinux_policy_root(void); - - /* These functions return the paths to specific files under the - policy root directory. */ -+extern const char *selinux_current_policy_path(void); - extern const char *selinux_binary_policy_path(void); -+extern char *selinux_binary_policy_path_min_max(int min, int *max); - extern const char *selinux_failsafe_context_path(void); - extern const char *selinux_removable_context_path(void); - extern const char *selinux_default_context_path(void); -diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3 -index ec97dcf..68f8fdf 100644 ---- a/libselinux/man/man3/selinux_binary_policy_path.3 -+++ b/libselinux/man/man3/selinux_binary_policy_path.3 -@@ -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); -@@ -52,8 +54,11 @@ returns the top-level SELinux configuration directory. - .BR selinux_policy_root () - returns the top-level policy directory. - .sp -+.BR selinux_current_policy_path() -+returns the binary policy file loaded into the kernel -+.sp - .BR selinux_binary_policy_path () --returns the binary policy file loaded into kernel. -+returns the binary policy file on disk - .sp - .BR selinux_default_type_path () - returns the context file mapping roles to default types. diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c -index ffe381b..73c07aa 100644 +index ffe381b..2d68482 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c -@@ -191,49 +191,24 @@ static PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) - static int __policy_init(const char *init_path) - { - FILE *fp; -- int vers = 0; -- char path[PATH_MAX]; -+ const char *path; - char errormsg[PATH_MAX]; - struct sepol_policy_file *pf = NULL; - int rc; - unsigned int cnt; - -- path[PATH_MAX-1] = '\0'; -- if (init_path) { -- strncpy(path, init_path, PATH_MAX-1); -- fp = fopen(path, "r"); -- if (!fp) { -- snprintf(errormsg, sizeof(errormsg), -- "unable to open %s: %s\n", -- path, strerror(errno)); -- PyErr_SetString( PyExc_ValueError, errormsg); -- 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"); -- } -- if (!fp) { -- snprintf(errormsg, sizeof(errormsg), -- "unable to open %s.%d: %s\n", -- selinux_binary_policy_path(), -- security_policyvers(), strerror(errno)); -- PyErr_SetString( PyExc_ValueError, errormsg); -- return 1; -- } -+ if (init_path) -+ path = init_path; -+ else -+ path = selinux_current_policy_path(); -+ -+ fp = fopen(path, "r"); -+ if (!fp) { -+ snprintf(errormsg, sizeof(errormsg), -+ "unable to open %s: %s\n", -+ path, strerror(errno)); -+ PyErr_SetString( PyExc_ValueError, errormsg); -+ return 1; - } - - avc = calloc(sizeof(struct avc_t), 1); -@@ -310,10 +285,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { +@@ -310,10 +310,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { } #define RETURN(X) \ @@ -120,7 +17,7 @@ index ffe381b..73c07aa 100644 security_context_t scon; security_context_t tcon; char *tclassstr; -@@ -328,10 +305,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args +@@ -328,10 +330,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args struct sepol_av_decision avd; int rc; int i=0; @@ -131,7 +28,7 @@ index ffe381b..73c07aa 100644 if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj)) return NULL; -@@ -342,22 +315,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args +@@ -342,22 +340,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args /* should raise an error here. */ if (numlines < 0) return NULL; /* Not a list */ @@ -161,7 +58,7 @@ index ffe381b..73c07aa 100644 /* Convert the permission list to an AV. */ av = 0; -@@ -377,21 +349,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args +@@ -377,21 +374,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args #endif perm = string_to_av_perm(tclass, permstr); @@ -189,7 +86,7 @@ index ffe381b..73c07aa 100644 if (reason & SEPOL_COMPUTEAV_TE) { avc->ssid = ssid; avc->tsid = tsid; -@@ -404,28 +375,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args +@@ -404,28 +400,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args RETURN(TERULE) } } else { @@ -327,112 +224,6 @@ index b9e8002..355730a 100644 } hidden_def(get_ordered_context_list) -diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c -index 10e29b9..888dab5 100644 ---- a/libselinux/src/load_policy.c -+++ b/libselinux/src/load_policy.c -@@ -49,8 +49,9 @@ int load_setlocaldefs hidden = 1; - int selinux_mkload_policy(int preservebools) - { - int kernvers = security_policyvers(); -- int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers; -+ int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION; - int setlocaldefs = load_setlocaldefs; -+ char *pol_path = NULL; - char path[PATH_MAX]; - struct stat sb; - struct utsname uts; -@@ -162,29 +163,24 @@ checkbool: - maxvers = max(kernvers, maxvers); - } - -- vers = maxvers; -- search: -- snprintf(path, sizeof(path), "%s.%d", -- selinux_binary_policy_path(), vers); -- fd = open(path, O_RDONLY); -- while (fd < 0 && errno == ENOENT -- && --vers >= minvers) { -- /* Check prior versions to see if old policy is available */ -- snprintf(path, sizeof(path), "%s.%d", -- selinux_binary_policy_path(), vers); -- fd = open(path, O_RDONLY); -+search: -+ pol_path = selinux_binary_policy_path_min_max(minvers, &maxvers); -+ if (!pol_path) { -+ fprintf(stderr, "SELinux: unable to find usable policy file: %s\n", -+ strerror(errno)); -+ goto dlclose; - } -+ -+ fd = open(pol_path, O_RDONLY); - if (fd < 0) { -- fprintf(stderr, -- "SELinux: Could not open policy file <= %s.%d: %s\n", -- selinux_binary_policy_path(), maxvers, strerror(errno)); -+ fprintf(stderr, "SELinux: Could not open policy file %s: %s\n", -+ pol_path, strerror(errno)); - goto dlclose; - } - - if (fstat(fd, &sb) < 0) { -- fprintf(stderr, -- "SELinux: Could not stat policy file %s: %s\n", -- path, strerror(errno)); -+ fprintf(stderr, "SELinux: Could not stat policy file %s: %s\n", -+ pol_path, strerror(errno)); - goto close; - } - -@@ -195,13 +191,12 @@ checkbool: - size = sb.st_size; - data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { -- fprintf(stderr, -- "SELinux: Could not map policy file %s: %s\n", -- path, strerror(errno)); -+ fprintf(stderr, "SELinux: Could not map policy file %s: %s\n", -+ pol_path, strerror(errno)); - goto close; - } - -- if (vers > kernvers && usesepol) { -+ if (maxvers > kernvers && usesepol) { - /* Need to downgrade to kernel-supported version. */ - if (policy_file_create(&pf)) - goto unmap; -@@ -220,12 +215,12 @@ checkbool: - /* Downgrade failed, keep searching. */ - fprintf(stderr, - "SELinux: Could not downgrade policy file %s, searching for an older version.\n", -- path); -+ pol_path); - policy_file_free(pf); - policydb_free(policydb); - munmap(map, sb.st_size); - close(fd); -- vers--; -+ maxvers--; - goto search; - } - policy_file_free(pf); -@@ -281,7 +276,7 @@ checkbool: - if (rc) - fprintf(stderr, - "SELinux: Could not load policy file %s: %s\n", -- path, strerror(errno)); -+ pol_path, strerror(errno)); - - unmap: - if (data != map) -@@ -296,6 +291,7 @@ checkbool: - if (libsepolh) - dlclose(libsepolh); - #endif -+ free(pol_path); - return rc; - } - diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index 2d7369e..2a00807 100644 --- a/libselinux/src/matchpathcon.c @@ -454,88 +245,2197 @@ index 2d7369e..2a00807 100644 va_end(ap); } -diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index 296f357..cb65666 100644 ---- a/libselinux/src/selinux_config.c -+++ b/libselinux/src/selinux_config.c -@@ -9,6 +9,7 @@ - #include - #include - #include "selinux_internal.h" -+#include "policy.h" - #include "get_default_type_internal.h" +diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h +index c27275e..0165eed 100644 +--- a/libsepol/include/sepol/policydb/policydb.h ++++ b/libsepol/include/sepol/policydb/policydb.h +@@ -683,10 +683,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + #define POLICYDB_VERSION_ROLETRANS 26 + #define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27 + #define POLICYDB_VERSION_DEFAULT_TYPE 28 ++#define POLICYDB_VERSION_CONSTRAINT_NAMES 29 - #define SELINUXDIR "/etc/selinux/" -@@ -296,13 +297,57 @@ const char *selinux_removable_context_path(void) + /* Range of policy versions we understand*/ + #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE +-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_DEFAULT_TYPE ++#define POLICYDB_VERSION_MAX POLICYDB_VERSION_CONSTRAINT_NAMES - hidden_def(selinux_removable_context_path) + /* Module versions and specific changes*/ + #define MOD_POLICYDB_VERSION_BASE 4 +@@ -704,9 +705,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); + #define MOD_POLICYDB_VERSION_TUNABLE_SEP 14 + #define MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 15 + #define MOD_POLICYDB_VERSION_DEFAULT_TYPE 16 ++#define MOD_POLICYDB_VERSION_CONSTRAINT_NAMES 17 -+char *selinux_binary_policy_path_min_max(int min, int *max) -+{ -+ int ret; -+ char *path = NULL; + #define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE +-#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_DEFAULT_TYPE ++#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_CONSTRAINT_NAMES + + #define POLICYDB_CONFIG_MLS 1 + +diff --git a/libsepol/include/sepol/policydb/services.h b/libsepol/include/sepol/policydb/services.h +index aef0c7b..1969a10 100644 +--- a/libsepol/include/sepol/policydb/services.h ++++ b/libsepol/include/sepol/policydb/services.h +@@ -58,6 +58,38 @@ extern int sepol_compute_av_reason(sepol_security_id_t ssid, + struct sepol_av_decision *avd, + unsigned int *reason); + ++/* ++ * Same as above, but also returns the constraint expression calculations ++ * whether allowed or denied in a buffer. This buffer is allocated by ++ * this call and must be free'd by the caller using free(3). The contraint ++ * buffer will contain any constraints in infix notation. ++ * If the SHOW_GRANTED flag is set it will show granted and denied ++ * constraints. The default is to show only denied constraints. ++ */ ++#define SHOW_GRANTED 1 ++extern int sepol_compute_av_reason_buffer(sepol_security_id_t ssid, ++ sepol_security_id_t tsid, ++ sepol_security_class_t tclass, ++ sepol_access_vector_t requested, ++ struct sepol_av_decision *avd, ++ unsigned int *reason, ++ char **reason_buf, ++ unsigned int flags); ++/* ++ * Return a class ID associated with the class string representation ++ * specified by `class_name'. ++ */ ++extern int sepol_class_name_to_id(const char *class_name, ++ sepol_security_class_t *tclass); + -+ while(*max >= min) { -+ ret = asprintf(&path, "%s.%d", get_path(BINPOLICY), *max); -+ if (ret < 0) -+ goto err; -+ ret = access(path, R_OK); -+ if (!ret) -+ return path; -+ free(path); -+ path = NULL; -+ *max = *max - 1; ++/* ++ * Return a permission av bit associated with tclass and the string ++ * representation of the `perm_name'. ++ */ ++extern int sepol_perm_name_to_av(sepol_security_class_t tclass, ++ const char *perm_name, ++ sepol_access_vector_t *av); ++ + /* + * Compute a SID to use for labeling a new object in the + * class `tclass' based on a SID pair. +diff --git a/libsepol/src/expand.c b/libsepol/src/expand.c +index f0555bb..6fd992f 100644 +--- a/libsepol/src/expand.c ++++ b/libsepol/src/expand.c +@@ -384,6 +384,17 @@ static int constraint_node_clone(constraint_node_t ** dst, + new_expr->op = expr->op; + if (new_expr->expr_type == CEXPR_NAMES) { + if (new_expr->attr & CEXPR_TYPE) { ++ /* ++ * Copy over constraint policy source types and/or ++ * attributes for sepol_compute_av_reason_buffer(3) so that ++ * utilities can analyse constraint errors. ++ */ ++ if (map_ebitmap(&expr->type_names->types, ++ &new_expr->type_names->types, ++ state->typemap)) { ++ ERR(NULL, "Failed to map type_names->types"); ++ goto out_of_mem; ++ } + /* Type sets require expansion and conversion. */ + if (expand_convert_type_set(state->out, + state-> +diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c +index 1f49261..8c7efbc 100644 +--- a/libsepol/src/policydb.c ++++ b/libsepol/src/policydb.c +@@ -165,6 +165,13 @@ static struct policydb_compat_info policydb_compat[] = { + .target_platform = SEPOL_TARGET_SELINUX, + }, + { ++ .type = POLICY_KERN, ++ .version = POLICYDB_VERSION_CONSTRAINT_NAMES, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_NODE6 + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, ++ { + .type = POLICY_BASE, + .version = MOD_POLICYDB_VERSION_BASE, + .sym_num = SYM_NUM, +@@ -256,6 +263,13 @@ static struct policydb_compat_info policydb_compat[] = { + .target_platform = SEPOL_TARGET_SELINUX, + }, + { ++ .type = POLICY_BASE, ++ .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, ++ .sym_num = SYM_NUM, ++ .ocon_num = OCON_NODE6 + 1, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, ++ { + .type = POLICY_MOD, + .version = MOD_POLICYDB_VERSION_BASE, + .sym_num = SYM_NUM, +@@ -346,6 +360,13 @@ static struct policydb_compat_info policydb_compat[] = { + .ocon_num = 0, + .target_platform = SEPOL_TARGET_SELINUX, + }, ++ { ++ .type = POLICY_MOD, ++ .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, ++ .sym_num = SYM_NUM, ++ .ocon_num = 0, ++ .target_platform = SEPOL_TARGET_SELINUX, ++ }, + }; + + #if 0 +@@ -2019,6 +2040,10 @@ static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, + if (p->policy_type != POLICY_KERN && + type_set_read(e->type_names, fp)) + return -1; ++ else if (p->policy_type == POLICY_KERN && ++ p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && ++ type_set_read(e->type_names, fp)) ++ return -1; + break; + default: + return -1; +diff --git a/libsepol/src/services.c b/libsepol/src/services.c +index 7fac4a0..43ec07e 100644 +--- a/libsepol/src/services.c ++++ b/libsepol/src/services.c +@@ -43,6 +43,11 @@ + * Implementation of the security services. + */ + ++/* The initial sizes malloc'd for sepol_compute_av_reason_buffer() support */ ++#define REASON_BUF_SIZE 2048 ++#define EXPR_BUF_SIZE 1024 ++#define STACK_LEN 32 ++ + #include + #include + #include +@@ -54,6 +59,7 @@ + #include + #include + #include ++#include + + #include "debug.h" + #include "private.h" +@@ -70,6 +76,50 @@ static int selinux_enforcing = 1; + static sidtab_t mysidtab, *sidtab = &mysidtab; + static policydb_t mypolicydb, *policydb = &mypolicydb; + ++/* Used by sepol_compute_av_reason_buffer() to keep track of entries */ ++static int reason_buf_used; ++static int reason_buf_len; ++ ++/* Stack services for RPN to infix conversion. */ ++static char **stack; ++static int stack_len; ++static int next_stack_entry; ++ ++static void push(char * expr_ptr) ++{ ++ if (next_stack_entry >= stack_len) { ++ char **new_stack = stack; ++ int new_stack_len; ++ ++ if (stack_len == 0) ++ new_stack_len = STACK_LEN; ++ else ++ new_stack_len = stack_len * 2; ++ ++ new_stack = realloc(stack, new_stack_len * sizeof(*stack)); ++ if (!new_stack) { ++ ERR(NULL, "unable to allocate stack space"); ++ return; ++ } ++ stack_len = new_stack_len; ++ stack = new_stack; + } -+err: -+ free(path); -+ return NULL; ++ stack[next_stack_entry] = expr_ptr; ++ next_stack_entry++; +} -+hidden_def(selinux_binary_policy_path_min_max) + - const char *selinux_binary_policy_path(void) - { - return get_path(BINPOLICY); - } -- - hidden_def(selinux_binary_policy_path) - -+const char *selinux_current_policy_path(void) ++static char *pop(void) +{ ++ next_stack_entry--; ++ if (next_stack_entry < 0) { ++ next_stack_entry = 0; ++ ERR(NULL, "pop called with no stack entries"); ++ return NULL; ++ } ++ return stack[next_stack_entry]; ++} ++/* End Stack services */ ++ + int hidden sepol_set_sidtab(sidtab_t * s) + { + sidtab = s; +@@ -113,20 +163,195 @@ int sepol_set_policydb_from_file(FILE * fp) + static uint32_t latest_granting = 0; + + /* +- * Return the boolean value of a constraint expression +- * when it is applied to the specified source and target ++ * cat_expr_buf adds a string to an expression buffer and handles realloc's if ++ * buffer is too small. The array of expression text buffer pointers and its ++ * counter are globally defined here as constraint_expr_eval_reason() sets ++ * them up and cat_expr_buf updates the e_buf pointer if the buffer is realloc'ed. ++ */ ++static int expr_counter; ++static char **expr_list; ++static int expr_buf_used; ++static int expr_buf_len; ++ ++static void cat_expr_buf(char *e_buf, char *string) ++{ ++ int len, new_buf_len; ++ char *p, *new_buf = e_buf; ++ ++ while (1) { ++ p = e_buf + expr_buf_used; ++ len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string); ++ if (len < 0 || len >= expr_buf_len - expr_buf_used) { ++ new_buf_len = expr_buf_len + EXPR_BUF_SIZE; ++ new_buf = realloc(e_buf, new_buf_len); ++ if (!new_buf) { ++ ERR(NULL, "failed to realloc expr buffer"); ++ return; ++ } ++ /* Update the new ptr in the expr list and locally + new len */ ++ expr_list[expr_counter] = new_buf; ++ e_buf = new_buf; ++ expr_buf_len = new_buf_len; ++ } else { ++ expr_buf_used += len; ++ return; ++ } ++ } ++} ++ ++/* ++ * If the POLICY_KERN version is < POLICYDB_VERSION_CONSTRAINT_NAMES, ++ * then just return. ++ * ++ * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES, ++ * then for 'types' only, read the types_names->types list as it will ++ * contain a list of types and attributes that were defined in the ++ * policy source. ++ */ ++static void get_names_list(constraint_expr_t *e, int type) ++{ ++ ebitmap_t *types; ++ types = &e->type_names->types; + int rc = 0; -+ int vers = 0; -+ static char policy_path[PATH_MAX]; ++ unsigned int i; ++ char tmp_buf[128]; ++ /* if -type_names->types is 0, then output string */ ++ int empty_set = 0; + -+ snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt); -+ if (access(policy_path, F_OK) != 0 ) { -+ 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; ++ if (policydb->policy_type == POLICY_KERN && ++ policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && ++ type == CEXPR_TYPE) { ++ /* ++ * Process >= POLICYDB_VERSION_CONSTRAINT_NAMES with CEXPR_TYPE, then ++ * obtain the list of names defined in the policy source. ++ */ ++ cat_expr_buf(expr_list[expr_counter], "{ POLICY_SOURCE: "); ++ for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { ++ if ((rc = ebitmap_get_bit(types, i)) == 0) ++ continue; ++ /* Collect entries */ ++ snprintf(tmp_buf, sizeof(tmp_buf), "%s ", policydb->p_type_val_to_name[i]); ++ cat_expr_buf(expr_list[expr_counter], tmp_buf); ++ empty_set++; ++ } ++ if (empty_set == 0) ++ cat_expr_buf(expr_list[expr_counter], " "); ++ cat_expr_buf(expr_list[expr_counter], "} "); + } -+ -+ return policy_path; ++ return; +} + -+hidden_def(selinux_current_policy_path) ++static void msgcat(char *src, char *tgt, char *rel, int failed) ++{ ++ char tmp_buf[1024]; ++ if (failed) ++ snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ", ++ src, rel, tgt); ++ else ++ snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Pass-) ", ++ src, rel, tgt); ++ cat_expr_buf(expr_list[expr_counter], tmp_buf); ++} + - const char *selinux_file_context_path(void) ++/* Returns a buffer with class, statement type and permissions */ ++static char *get_class_info(sepol_security_class_t tclass, ++ constraint_node_t *constraint, ++ context_struct_t * xcontext) ++{ ++ constraint_expr_t *e; ++ int mls, state_num; ++ ++ /* Find if MLS statement or not */ ++ mls = 0; ++ for (e = constraint->expr; e; e = e->next) { ++ if (e->attr >= CEXPR_L1L2) { ++ mls = 1; ++ break; ++ } ++ } ++ ++ /* Determine statement type */ ++ char *statements[] = { ++ "constrain ", /* 0 */ ++ "mlsconstrain ", /* 1 */ ++ "validatetrans ", /* 2 */ ++ "mlsvalidatetrans ", /* 3 */ ++ 0 }; ++ ++ if (xcontext == NULL) ++ state_num = mls + 0; ++ else ++ state_num = mls + 2; ++ ++ int class_buf_len = 0; ++ int new_class_buf_len; ++ int len, buf_used; ++ char *class_buf = NULL, *p; ++ char *new_class_buf = NULL; ++ ++ while (1) { ++ new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; ++ new_class_buf = realloc(class_buf, new_class_buf_len); ++ if (!new_class_buf) ++ return NULL; ++ class_buf_len = new_class_buf_len; ++ class_buf = new_class_buf; ++ buf_used = 0; ++ p = class_buf; ++ ++ /* Add statement type */ ++ len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); ++ if (len < 0 || len >= class_buf_len - buf_used) ++ continue; ++ ++ /* Add class entry */ ++ p += len; ++ buf_used += len; ++ len = snprintf(p, class_buf_len - buf_used, "%s ", ++ policydb->p_class_val_to_name[tclass - 1]); ++ if (len < 0 || len >= class_buf_len - buf_used) ++ continue; ++ ++ /* Add permission entries */ ++ p += len; ++ buf_used += len; ++ len = snprintf(p, class_buf_len - buf_used, "{%s } (", ++ sepol_av_to_string(policydb, tclass, constraint->permissions)); ++ if (len < 0 || len >= class_buf_len - buf_used) ++ continue; ++ break; ++ } ++ return class_buf; ++} ++ ++/* ++ * Modified version of constraint_expr_eval that will process each ++ * constraint as before but adds the information to text buffers that ++ * will hold various components. The expression will be in RPN format, ++ * therefore there is a stack based RPN to infix converter to produce ++ * the final readable constraint. ++ * ++ * Return the boolean value of a constraint expression ++ * when it is applied to the specified source and target + * security contexts. + * + * xcontext is a special beast... It is used by the validatetrans rules + * only. For these rules, scontext is the context before the transition, + * tcontext is the context after the transition, and xcontext is the context + * of the process performing the transition. All other callers of +- * constraint_expr_eval should pass in NULL for xcontext. ++ * constraint_expr_eval_reason should pass in NULL for xcontext. ++ * ++ * This function will also build a buffer as the constraint is processed ++ * for analysis. If this option is not required, then: ++ * 'tclass' should be '0' and r_buf MUST be NULL. + */ +-static int constraint_expr_eval(context_struct_t * scontext, ++static int constraint_expr_eval_reason(context_struct_t * scontext, + context_struct_t * tcontext, + context_struct_t * xcontext, +- constraint_expr_t * cexpr) ++ sepol_security_class_t tclass, ++ constraint_node_t *constraint, ++ char **r_buf, ++ unsigned int flags) { - return get_path(FILE_CONTEXTS); -diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h -index 2c7c85c..008aa6d 100644 ---- a/libselinux/src/selinux_internal.h -+++ b/libselinux/src/selinux_internal.h -@@ -61,7 +61,9 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(security_deny_unknown) - hidden_proto(selinux_boolean_sub) - hidden_proto(selinux_binary_policy_path) -+ hidden_proto(selinux_binary_policy_path_min_max) - hidden_proto(selinux_booleans_subs_path) -+ hidden_proto(selinux_current_policy_path) - hidden_proto(selinux_default_context_path) - hidden_proto(selinux_securetty_types_path) - hidden_proto(selinux_failsafe_context_path) + uint32_t val1, val2; + context_struct_t *c; +@@ -136,56 +361,137 @@ static int constraint_expr_eval(context_struct_t * scontext, + int s[CEXPR_MAXDEPTH]; + int sp = -1; + +- for (e = cexpr; e; e = e->next) { ++ char tmp_buf[128]; ++ ++/* ++ * Define the s_t_x_num values that make up r1, t2 etc. in text strings ++ * Set 1 = source, 2 = target, 3 = xcontext for validatetrans ++ */ ++#define SOURCE 1 ++#define TARGET 2 ++#define XTARGET 3 ++ ++ int s_t_x_num = SOURCE; ++ ++ /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ ++ int u_r_t = 0; ++ ++ char *name1, *name2; ++ char *src = NULL; ++ char *tgt = NULL; ++ ++ int rc = 0, x; ++ ++ char *class_buf = NULL; ++ ++ class_buf = get_class_info(tclass, constraint, xcontext); ++ if (!class_buf) { ++ ERR(NULL, "failed to allocate class buffer"); ++ return -ENOMEM; ++ } ++ ++ /* Original function but with buffer support */ ++ int expr_list_len = 0; ++ expr_counter = 0; ++ expr_list = NULL; ++ for (e = constraint->expr; e; e = e->next) { ++ /* Allocate a stack to hold expression buffer entries */ ++ if (expr_counter >= expr_list_len) { ++ char **new_expr_list = expr_list; ++ int new_expr_list_len; ++ ++ if (expr_list_len == 0) ++ new_expr_list_len = STACK_LEN; ++ else ++ new_expr_list_len = expr_list_len * 2; ++ ++ new_expr_list = realloc(expr_list, new_expr_list_len * sizeof(*expr_list)); ++ if (!new_expr_list) { ++ ERR(NULL, "failed to allocate expr buffer stack"); ++ rc = -ENOMEM; ++ goto out; ++ } ++ expr_list_len = new_expr_list_len; ++ expr_list = new_expr_list; ++ } ++ ++ /* ++ * malloc a buffer to store each expression text component. If the ++ * buffer is too small cat_expr_buf() will realloc extra space. ++ */ ++ expr_buf_len = EXPR_BUF_SIZE; ++ expr_list[expr_counter] = malloc(expr_buf_len); ++ if (!expr_list[expr_counter]) { ++ ERR(NULL, "failed to allocate expr buffer"); ++ rc = -ENOMEM; ++ goto out; ++ } ++ expr_buf_used = 0; ++ ++ /* Now process each expression of the constraint */ + switch (e->expr_type) { + case CEXPR_NOT: + BUG_ON(sp < 0); + s[sp] = !s[sp]; ++ cat_expr_buf(expr_list[expr_counter], "not"); + break; + case CEXPR_AND: + BUG_ON(sp < 1); + sp--; + s[sp] &= s[sp + 1]; ++ cat_expr_buf(expr_list[expr_counter], "and"); + break; + case CEXPR_OR: + BUG_ON(sp < 1); + sp--; + s[sp] |= s[sp + 1]; ++ cat_expr_buf(expr_list[expr_counter], "or"); + break; + case CEXPR_ATTR: + if (sp == (CEXPR_MAXDEPTH - 1)) +- return 0; ++ goto out; ++ + switch (e->attr) { + case CEXPR_USER: + val1 = scontext->user; + val2 = tcontext->user; ++ free(src); src = strdup("u1"); ++ free(tgt); tgt = strdup("u2"); + break; + case CEXPR_TYPE: + val1 = scontext->type; + val2 = tcontext->type; ++ free(src); src = strdup("t1"); ++ free(tgt); tgt = strdup("t2"); + break; + case CEXPR_ROLE: + val1 = scontext->role; + val2 = tcontext->role; + r1 = policydb->role_val_to_struct[val1 - 1]; + r2 = policydb->role_val_to_struct[val2 - 1]; ++ name1 = policydb->p_role_val_to_name[r1->s.value - 1]; ++ name2 = policydb->p_role_val_to_name[r2->s.value - 1]; ++ snprintf(tmp_buf, sizeof(tmp_buf), "r1=%s", name1); ++ free(src); src = strdup(tmp_buf); ++ snprintf(tmp_buf, sizeof(tmp_buf), "r2=%s ", name2); ++ free(tgt); tgt = strdup(tmp_buf); ++ + switch (e->op) { + case CEXPR_DOM: +- s[++sp] = +- ebitmap_get_bit(&r1->dominates, +- val2 - 1); ++ s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); ++ msgcat(src, tgt, "dom", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_DOMBY: +- s[++sp] = +- ebitmap_get_bit(&r2->dominates, +- val1 - 1); ++ s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); ++ msgcat(src, tgt, "domby", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_INCOMP: +- s[++sp] = +- (!ebitmap_get_bit +- (&r1->dominates, val2 - 1) +- && !ebitmap_get_bit(&r2->dominates, +- val1 - 1)); ++ s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1) ++ && !ebitmap_get_bit(&r2->dominates, val1 - 1)); ++ msgcat(src, tgt, "incomp", s[sp] == 0); ++ expr_counter++; + continue; + default: + break; +@@ -194,110 +500,327 @@ static int constraint_expr_eval(context_struct_t * scontext, + case CEXPR_L1L2: + l1 = &(scontext->range.level[0]); + l2 = &(tcontext->range.level[0]); ++ free(src); src = strdup("l1"); ++ free(tgt); tgt = strdup("l2"); + goto mls_ops; + case CEXPR_L1H2: + l1 = &(scontext->range.level[0]); + l2 = &(tcontext->range.level[1]); ++ free(src); src = strdup("l1"); ++ free(tgt); tgt = strdup("h2"); + goto mls_ops; + case CEXPR_H1L2: + l1 = &(scontext->range.level[1]); + l2 = &(tcontext->range.level[0]); ++ free(src); src = strdup("h1"); ++ free(tgt); tgt = strdup("L2"); + goto mls_ops; + case CEXPR_H1H2: + l1 = &(scontext->range.level[1]); + l2 = &(tcontext->range.level[1]); ++ free(src); src = strdup("h1"); ++ free(tgt); tgt = strdup("h2"); + goto mls_ops; + case CEXPR_L1H1: + l1 = &(scontext->range.level[0]); + l2 = &(scontext->range.level[1]); ++ free(src); src = strdup("l1"); ++ free(tgt); tgt = strdup("h1"); + goto mls_ops; + case CEXPR_L2H2: + l1 = &(tcontext->range.level[0]); + l2 = &(tcontext->range.level[1]); +- goto mls_ops; +- mls_ops: ++ free(src); src = strdup("l2"); ++ free(tgt); tgt = strdup("h2"); ++ mls_ops: + switch (e->op) { + case CEXPR_EQ: + s[++sp] = mls_level_eq(l1, l2); ++ msgcat(src, tgt, "eq", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_NEQ: + s[++sp] = !mls_level_eq(l1, l2); ++ msgcat(src, tgt, "neq", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_DOM: + s[++sp] = mls_level_dom(l1, l2); ++ msgcat(src, tgt, "dom", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_DOMBY: + s[++sp] = mls_level_dom(l2, l1); ++ msgcat(src, tgt, "domby", s[sp] == 0); ++ expr_counter++; + continue; + case CEXPR_INCOMP: + s[++sp] = mls_level_incomp(l2, l1); ++ msgcat(src, tgt, "incomp", s[sp] == 0); ++ expr_counter++; + continue; + default: + BUG(); +- return 0; ++ goto out; + } + break; + default: + BUG(); +- return 0; ++ goto out; + } + + switch (e->op) { + case CEXPR_EQ: + s[++sp] = (val1 == val2); ++ msgcat(src, tgt, "eq", s[sp] == 0); + break; + case CEXPR_NEQ: + s[++sp] = (val1 != val2); ++ msgcat(src, tgt, "neq", s[sp] == 0); + break; + default: + BUG(); +- return 0; ++ goto out; + } + break; + case CEXPR_NAMES: + if (sp == (CEXPR_MAXDEPTH - 1)) +- return 0; ++ goto out; ++ s_t_x_num = SOURCE; + c = scontext; +- if (e->attr & CEXPR_TARGET) ++ if (e->attr & CEXPR_TARGET) { ++ s_t_x_num = TARGET; + c = tcontext; +- else if (e->attr & CEXPR_XTARGET) { ++ } else if (e->attr & CEXPR_XTARGET) { ++ s_t_x_num = XTARGET; + c = xcontext; +- if (!c) { +- BUG(); +- return 0; +- } + } +- if (e->attr & CEXPR_USER) ++ if (!c) { ++ BUG(); ++ goto out; ++ } ++ if (e->attr & CEXPR_USER) { ++ u_r_t = CEXPR_USER; + val1 = c->user; +- else if (e->attr & CEXPR_ROLE) ++ name1 = policydb->p_user_val_to_name[val1 - 1]; ++ snprintf(tmp_buf, sizeof(tmp_buf), "u%d=%s ", ++ s_t_x_num, name1); ++ free(src); src = strdup(tmp_buf); ++ } ++ else if (e->attr & CEXPR_ROLE) { ++ u_r_t = CEXPR_ROLE; + val1 = c->role; +- else if (e->attr & CEXPR_TYPE) ++ name1 = policydb->p_role_val_to_name[val1 - 1]; ++ snprintf(tmp_buf, sizeof(tmp_buf), "r%d=%s ", s_t_x_num, name1); ++ free(src); src = strdup(tmp_buf); ++ } ++ else if (e->attr & CEXPR_TYPE) { ++ u_r_t = CEXPR_TYPE; + val1 = c->type; ++ name1 = policydb->p_type_val_to_name[val1 - 1]; ++ snprintf(tmp_buf, sizeof(tmp_buf), ++ "t%d=%s ", s_t_x_num, name1); ++ free(src); src = strdup(tmp_buf); ++ } + else { + BUG(); +- return 0; ++ goto out; + } + + switch (e->op) { + case CEXPR_EQ: ++ switch (u_r_t) { ++ case CEXPR_USER: ++ free(tgt); tgt=strdup("USER_ENTRY"); ++ break; ++ case CEXPR_ROLE: ++ free(tgt); tgt=strdup("ROLE_ENTRY"); ++ break; ++ case CEXPR_TYPE: ++ free(tgt); tgt=strdup("TYPE_ENTRY"); ++ break; ++ default: ++ ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t); ++ break; ++ } ++ + s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); ++ msgcat(src, tgt, "eq", s[sp] == 0); ++ if (s[sp] == 0) { ++ get_names_list(e, u_r_t); ++ } + break; ++ + case CEXPR_NEQ: ++ switch (u_r_t) { ++ case CEXPR_USER: ++ free(tgt); tgt=strdup("USER_ENTRY"); ++ break; ++ case CEXPR_ROLE: ++ free(tgt); tgt=strdup("ROLE_ENTRY"); ++ break; ++ case CEXPR_TYPE: ++ free(tgt); tgt=strdup("TYPE_ENTRY"); ++ break; ++ default: ++ ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t); ++ break; ++ } ++ + s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); ++ msgcat(src, tgt, "neq", s[sp] == 0); ++ if (s[sp] == 0) { ++ get_names_list(e, u_r_t); ++ } + break; + default: + BUG(); +- return 0; ++ goto out; + } + break; + default: + BUG(); +- return 0; ++ goto out; + } ++ expr_counter++; ++ } ++ ++ /* ++ * At this point each expression of the constraint is in ++ * expr_list[n+1] and in RPN format. Now convert to 'infix' ++ */ ++ ++ /* ++ * Save expr count but zero expr_counter to detect if 'BUG(); goto out;' ++ * was called as we need to release any used expr_list malloc's. Normally ++ * they are released by the RPN to infix code. ++ */ ++ int expr_count = expr_counter; ++ expr_counter = 0; ++ ++ /* ++ * The array of expression answer buffer pointers and counter. Generate ++ * the same number of answer buffer entries as expression buffers (as ++ * there will never be more required). ++ */ ++ char **answer_list; ++ int answer_counter = 0; ++ ++ answer_list = malloc(expr_count * sizeof(*answer_list)); ++ if (!answer_list) { ++ ERR(NULL, "failed to allocate answer stack"); ++ rc = -ENOMEM; ++ goto out; + } + +- BUG_ON(sp != 0); +- return s[0]; ++ /* The pop operands */ ++ char *a; ++ char *b; ++ int a_len, b_len; ++ ++ /* Convert constraint from RPN to infix notation. */ ++ for (x = 0; x != expr_count; x++) { ++ if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], ++ "or", 2) == 0) { ++ b = pop(); ++ b_len = strlen(b); ++ a = pop(); ++ a_len = strlen(a); ++ ++ /* get a buffer to hold the answer */ ++ answer_list[answer_counter] = malloc(a_len + b_len + 8); ++ if (!answer_list[answer_counter]) { ++ ERR(NULL, "failed to allocate answer buffer"); ++ rc = -ENOMEM; ++ goto out; ++ } ++ memset(answer_list[answer_counter], '\0', a_len + b_len + 8); ++ ++ sprintf(answer_list[answer_counter], "%s %s %s", a, expr_list[x], b); ++ push(answer_list[answer_counter++]); ++ free(a); ++ free(b); ++ } else if (strncmp(expr_list[x], "not", 3) == 0) { ++ b = pop(); ++ b_len = strlen(b); ++ ++ answer_list[answer_counter] = malloc(b_len + 8); ++ if (!answer_list[answer_counter]) { ++ ERR(NULL, "failed to allocate answer buffer"); ++ rc = -ENOMEM; ++ goto out; ++ } ++ memset(answer_list[answer_counter], '\0', b_len + 8); ++ ++ if (strncmp(b, "not", 3) == 0) ++ sprintf(answer_list[answer_counter], "%s (%s)", expr_list[x], b); ++ else ++ sprintf(answer_list[answer_counter], "%s%s", expr_list[x], b); ++ push(answer_list[answer_counter++]); ++ free(b); ++ } else { ++ push(expr_list[x]); ++ } ++ } ++ /* Get the final answer from tos and build constraint text */ ++ a = pop(); ++ ++ /* Constraint calculation: rc = 0 is denied, rc = 1 is granted */ ++ sprintf(tmp_buf,"Constraint %s\n", s[0] ? "GRANTED" : "DENIED"); ++ ++ int len, new_buf_len; ++ char *p, **new_buf = r_buf; ++ /* ++ * These contain the constraint components that are added to the ++ * callers reason buffer. ++ */ ++ char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; ++ ++ /* ++ * This will add the constraints to the callers reason buffer (who is ++ * responsible for freeing the memory). It will handle any realloc's ++ * should the buffer be too short. ++ * The reason_buf_used and reason_buf_len counters are defined globally ++ * as multiple constraints can be in the buffer. ++ */ ++ if (r_buf && ((s[0] == 0) || ((s[0] == 1 && ++ (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { ++ for (x = 0; buffers[x] != NULL; x++) { ++ while (1) { ++ p = *r_buf + reason_buf_used; ++ len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]); ++ if (len < 0 || len >= reason_buf_len - reason_buf_used) { ++ new_buf_len = reason_buf_len + REASON_BUF_SIZE; ++ *new_buf = realloc(*r_buf, new_buf_len); ++ if (!new_buf) { ++ ERR(NULL, "failed to realloc reason buffer"); ++ goto out1; ++ } ++ **r_buf = **new_buf; ++ reason_buf_len = new_buf_len; ++ continue; ++ } else { ++ reason_buf_used += len; ++ break; ++ } ++ } ++ } ++ } ++ ++out1: ++ rc = s[0]; ++ free(a); ++ ++out: ++ free(class_buf); ++ free(src); ++ free(tgt); ++ ++ if (expr_counter) { ++ for (x = 0; expr_list[x] != NULL; x++) ++ free(expr_list[x]); ++ } ++ return rc; + } + + /* +@@ -309,7 +832,9 @@ static int context_struct_compute_av(context_struct_t * scontext, + sepol_security_class_t tclass, + sepol_access_vector_t requested, + struct sepol_av_decision *avd, +- unsigned int *reason) ++ unsigned int *reason, ++ char **r_buf, ++ unsigned int flags) + { + constraint_node_t *constraint; + struct role_allow *ra; +@@ -384,8 +909,8 @@ static int context_struct_compute_av(context_struct_t * scontext, + constraint = tclass_datum->constraints; + while (constraint) { + if ((constraint->permissions & (avd->allowed)) && +- !constraint_expr_eval(scontext, tcontext, NULL, +- constraint->expr)) { ++ !constraint_expr_eval_reason(scontext, tcontext, NULL, ++ tclass, constraint, r_buf, flags)) { + avd->allowed = + (avd->allowed) & ~(constraint->permissions); + } +@@ -460,8 +985,8 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid, + + constraint = tclass_datum->validatetrans; + while (constraint) { +- if (!constraint_expr_eval(ocontext, ncontext, tcontext, +- constraint->expr)) { ++ if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, ++ 0, constraint, NULL, 0)) { + return -EPERM; + } + constraint = constraint->next; +@@ -494,11 +1019,59 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid, + } + + rc = context_struct_compute_av(scontext, tcontext, tclass, +- requested, avd, reason); ++ requested, avd, reason, NULL, 0); + out: + return rc; + } + ++/* ++ * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to ++ * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd ++ * in the constraint_expr_eval_reason() function. ++ */ ++int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid, ++ sepol_security_id_t tsid, ++ sepol_security_class_t tclass, ++ sepol_access_vector_t requested, ++ struct sepol_av_decision *avd, ++ unsigned int *reason, ++ char **reason_buf, ++ unsigned int flags) ++{ ++ *reason_buf = malloc(REASON_BUF_SIZE); ++ if (!*reason_buf) { ++ ERR(NULL, "failed to allocate reason buffer"); ++ return -ENOMEM; ++ } ++ /* ++ * These are defined globally as the buffer can contain multiple ++ * constraint statements so need to keep track ++ */ ++ reason_buf_used = 0; ++ reason_buf_len = REASON_BUF_SIZE; ++ ++ context_struct_t *scontext = 0, *tcontext = 0; ++ int rc = 0; ++ ++ scontext = sepol_sidtab_search(sidtab, ssid); ++ if (!scontext) { ++ ERR(NULL, "unrecognized SID %d", ssid); ++ rc = -EINVAL; ++ goto out; ++ } ++ tcontext = sepol_sidtab_search(sidtab, tsid); ++ if (!tcontext) { ++ ERR(NULL, "unrecognized SID %d", tsid); ++ rc = -EINVAL; ++ goto out; ++ } ++ ++ rc = context_struct_compute_av(scontext, tcontext, tclass, ++ requested, avd, reason, reason_buf, flags); ++out: ++ return rc; ++} ++ + int hidden sepol_compute_av(sepol_security_id_t ssid, + sepol_security_id_t tsid, + sepol_security_class_t tclass, +@@ -511,6 +1084,70 @@ int hidden sepol_compute_av(sepol_security_id_t ssid, + } + + /* ++ * Return a class ID associated with the class string specified by ++ * class_name. ++ */ ++int hidden sepol_class_name_to_id(const char *class_name, ++ sepol_security_class_t *tclass) ++{ ++ char *class = NULL; ++ sepol_security_class_t id; ++ ++ for (id = 1; ; id++) { ++ if ((class = policydb->p_class_val_to_name[id - 1]) == NULL) { ++ ERR(NULL, "could not convert %s to class id", class_name); ++ return STATUS_ERR; ++ } ++ if ((strcmp(class, class_name)) == 0) { ++ *tclass = id; ++ return STATUS_SUCCESS; ++ } ++ } ++} ++ ++/* ++ * Return access vector bit associated with the class ID and permission ++ * string. ++ */ ++int hidden sepol_perm_name_to_av(sepol_security_class_t tclass, ++ const char *perm_name, ++ sepol_access_vector_t *av) ++{ ++ class_datum_t *tclass_datum; ++ perm_datum_t *perm_datum; ++ ++ if (!tclass || tclass > policydb->p_classes.nprim) { ++ ERR(NULL, "unrecognized class %d", tclass); ++ return -EINVAL; ++ } ++ tclass_datum = policydb->class_val_to_struct[tclass - 1]; ++ ++ /* Check for unique perms then the common ones (if any) */ ++ perm_datum = (perm_datum_t *) ++ hashtab_search(tclass_datum->permissions.table, ++ (hashtab_key_t)perm_name); ++ if (perm_datum != NULL) { ++ *av = 0x1 << (perm_datum->s.value - 1); ++ return STATUS_SUCCESS; ++ } ++ ++ if (tclass_datum->comdatum == NULL) ++ goto out; ++ ++ perm_datum = (perm_datum_t *) ++ hashtab_search(tclass_datum->comdatum->permissions.table, ++ (hashtab_key_t)perm_name); ++ ++ if (perm_datum != NULL) { ++ *av = 0x1 << (perm_datum->s.value - 1); ++ return STATUS_SUCCESS; ++ } ++out: ++ ERR(NULL, "could not convert %s to av bit", perm_name); ++ return STATUS_ERR; ++} ++ ++/* + * Write the security context string representation of + * the context associated with `sid' into a dynamically + * allocated string of the correct size. Set `*scontext' +@@ -1339,7 +1976,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid, + rc = context_struct_compute_av(fromcon, &usercon, + SECCLASS_PROCESS, + PROCESS__TRANSITION, +- &avd, &reason); ++ &avd, &reason, NULL, 0); + if (rc || !(avd.allowed & PROCESS__TRANSITION)) + continue; + rc = sepol_sidtab_context_to_sid(sidtab, &usercon, +diff --git a/libsepol/src/write.c b/libsepol/src/write.c +index 55992f8..6fe73e6 100644 +--- a/libsepol/src/write.c ++++ b/libsepol/src/write.c +@@ -893,8 +893,11 @@ static int write_cons_helper(policydb_t * p, + if (ebitmap_write(&e->names, fp)) { + return POLICYDB_ERROR; + } +- if (p->policy_type != POLICY_KERN && +- type_set_write(e->type_names, fp)) { ++ if ((p->policy_type != POLICY_KERN && ++ type_set_write(e->type_names, fp)) || ++ (p->policy_type == POLICY_KERN && ++ (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) && ++ type_set_write(e->type_names, fp))) { + return POLICYDB_ERROR; + } + break; +diff --git a/policycoreutils/Makefile b/policycoreutils/Makefile +index 3980799..6624804 100644 +--- a/policycoreutils/Makefile ++++ b/policycoreutils/Makefile +@@ -1,4 +1,4 @@ +-SUBDIRS = sepolicy setfiles semanage load_policy newrole run_init sandbox secon audit2allow audit2why sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool scripts po man gui ++SUBDIRS = sepolicy setfiles semanage semanage/default_encoding load_policy newrole run_init sandbox secon audit2allow sestatus semodule_package semodule semodule_link semodule_expand semodule_deps sepolgen-ifgen setsebool scripts po man gui + + INOTIFYH = $(shell ls /usr/include/sys/inotify.h 2>/dev/null) + +diff --git a/policycoreutils/audit2allow/Makefile b/policycoreutils/audit2allow/Makefile +index 88635d4..fc290ea 100644 +--- a/policycoreutils/audit2allow/Makefile ++++ b/policycoreutils/audit2allow/Makefile +@@ -5,14 +5,19 @@ LIBDIR ?= $(PREFIX)/lib + MANDIR ?= $(PREFIX)/share/man + LOCALEDIR ?= /usr/share/locale + +-all: ; ++all: audit2why ++ ++audit2why: ++ ln -sf audit2allow audit2why + + install: all + -mkdir -p $(BINDIR) + install -m 755 audit2allow $(BINDIR) ++ (cd $(BINDIR); ln -sf audit2allow audit2why) + install -m 755 sepolgen-ifgen $(BINDIR) + -mkdir -p $(MANDIR)/man1 + install -m 644 audit2allow.1 $(MANDIR)/man1/ ++ install -m 644 audit2why.1 $(MANDIR)/man1/ + + clean: + rm -f *~ +diff --git a/policycoreutils/audit2allow/audit2allow b/policycoreutils/audit2allow/audit2allow +index 8e0c396..9bd66f5 100644 +--- a/policycoreutils/audit2allow/audit2allow ++++ b/policycoreutils/audit2allow/audit2allow +@@ -18,7 +18,7 @@ + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + # + +-import sys ++import sys, os + + import sepolgen.audit as audit + import sepolgen.policygen as policygen +@@ -29,6 +29,8 @@ import sepolgen.defaults as defaults + import sepolgen.module as module + from sepolgen.sepolgeni18n import _ + import selinux.audit2why as audit2why ++import locale ++locale.setlocale(locale.LC_ALL, '') + + class AuditToPolicy: + VERSION = "%prog .1" +@@ -80,8 +82,7 @@ class AuditToPolicy: + parser.add_option("--interface-info", dest="interface_info", help="file name of interface information") + parser.add_option("--debug", dest="debug", action="store_true", default=False, + help="leave generated modules for -M") +- +- parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=False, ++ parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0])=="audit2why"), + help="Translates SELinux audit messages into a description of why the access was denied") + + options, args = parser.parse_args() +diff --git a/policycoreutils/audit2allow/audit2why.1 b/policycoreutils/audit2allow/audit2why.1 +new file mode 100644 +index 0000000..a9e8893 +--- /dev/null ++++ b/policycoreutils/audit2allow/audit2why.1 +@@ -0,0 +1 @@ ++.so man1/audit2allow.1 +diff --git a/policycoreutils/audit2why/Makefile b/policycoreutils/audit2why/Makefile +deleted file mode 100644 +index 63eb8b3..0000000 +--- a/policycoreutils/audit2why/Makefile ++++ /dev/null +@@ -1,18 +0,0 @@ +-# Installation directories. +-PREFIX ?= $(DESTDIR)/usr +-BINDIR ?= $(PREFIX)/bin +-MANDIR ?= $(PREFIX)/share/man +- +-TARGETS=audit2why +- +-all: $(TARGETS) +- +-install: all +- -mkdir -p $(BINDIR) +- install -m 755 $(TARGETS) $(BINDIR) +- -mkdir -p $(MANDIR)/man1 +- install -m 644 audit2why.1 $(MANDIR)/man1/ +- +-clean: +- +-relabel: +diff --git a/policycoreutils/audit2why/audit2why b/policycoreutils/audit2why/audit2why +deleted file mode 100644 +index 21a72aa..0000000 +--- a/policycoreutils/audit2why/audit2why ++++ /dev/null +@@ -1,2 +0,0 @@ +-#!/bin/sh +-/usr/bin/audit2allow -w $* +diff --git a/policycoreutils/audit2why/audit2why.1 b/policycoreutils/audit2why/audit2why.1 +deleted file mode 100644 +index a9e8893..0000000 +--- a/policycoreutils/audit2why/audit2why.1 ++++ /dev/null +@@ -1 +0,0 @@ +-.so man1/audit2allow.1 +diff --git a/policycoreutils/gui/Makefile b/policycoreutils/gui/Makefile +index b5abbb9..1148b36 100644 +--- a/policycoreutils/gui/Makefile ++++ b/policycoreutils/gui/Makefile +@@ -1,7 +1,10 @@ + # Installation directories. + PREFIX ?= ${DESTDIR}/usr ++SYSCONFDIR ?= ${DESTDIR}/etc + BINDIR ?= $(PREFIX)/bin + SHAREDIR ?= $(PREFIX)/share/system-config-selinux ++DATADIR ?= $(PREFIX)/share ++PAMDIR ?= $(SYSCONFDIR)/pam.d + + TARGETS= \ + booleansPage.py \ +@@ -16,6 +19,7 @@ portsPage.py \ + semanagePage.py \ + statusPage.py \ + system-config-selinux.glade \ ++system-config-selinux.png \ + usersPage.py + + all: $(TARGETS) system-config-selinux.py polgengui.py +@@ -23,10 +27,21 @@ all: $(TARGETS) system-config-selinux.py polgengui.py + install: all + -mkdir -p $(SHAREDIR) + -mkdir -p $(BINDIR) ++ -mkdir -p $(DATADIR)/pixmaps ++ -mkdir -p $(DATADIR)/icons/hicolor/24x24/apps ++ -mkdir -p $(SYSCONFDIR) ++ -mkdir -p $(PAMDIR) ++ -mkdir -p $(SYSCONFDIR)/security/console.apps/system-config-selinux + install -m 755 system-config-selinux.py $(SHAREDIR) + install -m 755 polgengui.py $(SHAREDIR) + install -m 755 sepolgen $(BINDIR) + install -m 644 $(TARGETS) $(SHAREDIR) ++ install -m 644 system-config-selinux.png $(DATADIR)/pixmaps ++ install -m 644 system-config-selinux.png $(DATADIR)/icons/hicolor/24x24/apps ++ install -m 644 system-config-selinux.png $(DATADIR)/system-config-selinux ++ install -m 644 *.desktop $(DATADIR)/system-config-selinux ++ install -m 644 system-config-selinux.pam $(PAMDIR)/system-config-selinux ++ install -m 644 system-config-selinux.console $(SYSCONFDIR)/security/console.apps/system-config-selinux + + clean: + +diff --git a/policycoreutils/gui/selinux-polgengui.desktop b/policycoreutils/gui/selinux-polgengui.desktop +new file mode 100644 +index 0000000..0c2f399 +--- /dev/null ++++ b/policycoreutils/gui/selinux-polgengui.desktop +@@ -0,0 +1,67 @@ ++[Desktop Entry] ++Name=SELinux Policy Generation Tool ++Name[bn_IN]=SELinux Policy নির্মাণের সামগ্রী ++Name[ca]=Eina de generació de polítiques del SELinux ++Name[da]=Regelsætgenereringsværktøj til SELinux ++Name[de]=Tool zur Erstellung von SELinux-Richtlinien ++Name[es]=Generador de Políticas de SELinux ++Name[fi]=SELinux-käytäntöjen generointityökalu ++Name[fr]=Outil de génération de stratégies SELinux ++Name[gu]=SELinux પોલિસી બનાવટ સાધન ++Name[hi]=SELinux पॉलिसी जनन औजार ++Name[it]=Tool di generazione della policy di SELinux ++Name[ja]=SELinux ポリシー生成ツール ++Name[kn]=SELinux ಪಾಲಿಸಿ ಉತ್ಪಾದನಾ ಉಪಕರಣ ++Name[ko]=SELinux 정책 생성 도구 ++Name[ml]=SELinux പോളിസി ഉത്പാദന പ്രയോഗം ++Name[mr]=SELinux करार निर्माण साधन ++Name[nl]=SELinux tactiek generatie gereedschap ++Name[or]=SELinux ନୀତି ସୃଷ୍ଟି ଉପକରଣ ++Name[pa]=SELinux ਪਾਲਿਸੀ ਨਿਰਮਾਣ ਜੰਤਰ ++Name[pl]=Narzędzie tworzenia polityki SELinuksa ++Name[pt]=Ferramenta de Geração de Políticas SELinux ++Name[pt_BR]=Ferramenta de criação de políticas do SELinux ++Name[ru]=Средство создания политики SELinux ++Name[sv]=Genereringsverktyg för SELinuxpolicy ++Name[ta]=SELinux பாலிசி உற்பத்தி கருவி ++Name[te]=SELinux నిర్వహణ ++Name[uk]=Утиліта генерації правил SELinux ++Name[zh_CN]=SELinux 策略生成工具 ++Name[zh_TW]=SELinux 政策產生工具(SELinux Policy Generation Tool) ++Comment=Generate SELinux policy modules ++Comment[bn_IN]=SELinux নিয়মনীতির মডিউল নির্মাণ করুন ++Comment[ca]=Genera els mòduls de les polítiques de SELinux ++Comment[da]=Generér SELinux-regelsætmodul ++Comment[de]=Tool zur Erstellung von SELinux-Richtlinien ++Comment[es]=Generar módulos de política de SELinux ++Comment[fi]=Generoi SELinuxin käytäntömoduuleja ++Comment[fr]=Génére des modules de stratégie SELinux ++Comment[gu]=SELinux પોલિસી મોડ્યુલોને ઉત્પન્ન કરો ++Comment[hi]=नया पॉलिसी मॉड्यूल उत्पन्न करें ++Comment[it]=Genera moduli della politica di SELinux ++Comment[ja]=新しいポリシーモジュールの作成 ++Comment[kn]=SELinux ಪಾಲಿಸಿ ಘಟಕಗಳನ್ನು ಉತ್ಪಾದಿಸು ++Comment[ko]=SELinux 정책 모듈 생성 ++Comment[ml]=SELinux യ പോളിസി ഘങ്ങള്‍ തയ്യാറാക്കുക ++Comment[mr]=SELinux करार घटके निर्माण करा ++Comment[nl]=Maak een SELinux tactiek module aan ++Comment[or]=SELinux ନୀତି ଏକକାଂଶ ସୃଷ୍ଟିକରନ୍ତୁ ++Comment[pa]=SELinux ਪਾਲਿਸੀ ਮੈਡਿਊਲ ਬਣਾਓ ++Comment[pl]=Tworzenie nowych modułów polityki SELinuksa ++Comment[pt]=Gerar módulos de políticas SELinux ++Comment[pt_BR]=Gerar módulos de política do SELinux ++Comment[ru]=Генерация модулей политики SELinux ++Comment[sv]=Generera SELinux-policymoduler ++Comment[ta]=SELinux கொள்கை தொகுதியை உருவாக்கவும் ++Comment[te]=SELinux పాలసీ మాడ్యూళ్ళను వుద్భవింపచేయుము ++Comment[uk]=Створення модулів контролю доступу SELinux ++Comment[zh_CN]=生成 SELinux 策略模块 ++Comment[zh_TW]=產生 SELinux 政策模組 ++StartupNotify=true ++Icon=system-config-selinux ++Exec=/usr/bin/selinux-polgengui ++Type=Application ++Terminal=false ++Categories=System;Security; ++X-Desktop-File-Install-Version=0.2 ++Keywords=policy;security;selinux;avc;permission;mac; +diff --git a/policycoreutils/gui/system-config-selinux.console b/policycoreutils/gui/system-config-selinux.console +new file mode 100644 +index 0000000..42b48a3 +--- /dev/null ++++ b/policycoreutils/gui/system-config-selinux.console +@@ -0,0 +1,3 @@ ++USER=root ++PROGRAM=/usr/share/system-config-selinux/system-config-selinux.py ++SESSION=true +diff --git a/policycoreutils/gui/system-config-selinux.desktop b/policycoreutils/gui/system-config-selinux.desktop +new file mode 100644 +index 0000000..8822ce2 +--- /dev/null ++++ b/policycoreutils/gui/system-config-selinux.desktop +@@ -0,0 +1,67 @@ ++[Desktop Entry] ++Name=SELinux Management ++Name[bn_IN]=SELinux পরিচালনা ++Name[da]=Håndtering af SELinux ++Name[de]=SELinux-Management ++Name[ca]=Gestió de SELinux ++Name[es]=Administración de SELinux ++Name[fi]=SELinuxin ylläpito ++Name[fr]=Gestion de SELinux ++Name[gu]=SELinux સંચાલન ++Name[hi]=SELinux प्रबंधन ++Name[jp]=SELinux 管理 ++Name[it]=Gestione di SELinux ++Name[kn]=SELinux ವ್ಯವಸ್ಥಾಪನೆ ++Name[ko]=SELinux 관리 ++Name[ml]=SELinux മാനേജ്മെന്റ് ++Name[mr]=SELinux मॅनेजमेंट ++Name[nl]=SELinux beheer ++Name[or]=SELinux ପରିଚାଳନା ++Name[pa]=SELinux ਮੈਨੇਜਮੈਂਟ ++Name[pl]=Zarządzanie SELinuksem ++Name[pt_BR]=Gerenciamento do SELinux ++Name[pt]=Gestão de SELinux ++Name[ru]=Управление SELinux ++Name[sv]=SELinux-hantering ++Name[ta]=SELinux மேலாண்மை ++Name[te]=SELinux నిర్వహణ ++Name[uk]=Керування SELinux ++Name[zh_CN]=SELinux 管理 ++Name[zh_TW]=SELinux 管理 ++Comment=Configure SELinux in a graphical setting ++Comment[bn_IN]=গ্রাফিক্যাল পরিবেশে SELinux কনফিগার করুন ++Comment[ca]=Configura SELinuc an mode de preferències gràfiques ++Comment[da]=Konfigurér SELinux i et grafisk miljø ++Comment[de]=SELinux in einer grafischen Einstellung konfigurieren ++Comment[es]=Defina SELinux en una configuración de interfaz gráfica ++Comment[fi]=Tee SELinuxin asetukset graafisesti ++Comment[fr]=Configure SELinux dans un environnement graphique ++Comment[gu]=ગ્રાફિકલ સુયોજનમાં SELinux ને રૂપરેખાંકિત કરો ++Comment[hi]=SELinux को आलेखी सेटिंग में विन्यस्त करें ++Comment[it]=Configura SELinux in una impostazione grafica ++Comment[jp]=グラフィカルな設定画面で SELinux を設定する ++Comment[ko]=SELinux를 그래픽 사용자 인터페이스로 설정 ++Comment[kn]=SELinux ಅನ್ನು ಒಂದು ಚಿತ್ರಾತ್ಮಕ ಸಿದ್ದತೆಯಲ್ಲಿ ಸಂರಚಿಸಿ ++Comment[ml]=ഒരു ഗ്രാഫിക്കല്‍ സജ്ജീകരണത്തില്‍ SELinux ക്രമീകരിയ്ക്കുക ++Comment[mr]=ग्राफिकल सेटिंगमध्ये SELinux संरचीत करा ++Comment[nl]=Configureer SELinux in een grafische omgeving ++Comment[or]=SELinux କୁ ଆଲେଖିକ ସଂରଚନାରେ ବିନ୍ୟାସ କରନ୍ତୁ ++Comment[pa]=SELinux ਨੂੰ ਗਰਾਫੀਕਲ ਸੈਟਿੰਗ ਵਿੱਚ ਸੰਰਚਿਤ ਕਰੋ ++Comment[pl]=Konfiguracja SELinuksa w trybie graficznym ++Comment[pt]=Configurar o SELinux num ambiente gráfico ++Comment[pt_BR]=Configure o SELinux em uma configuração gráfica ++Comment[ru]=Настройка SELinux в графическом режиме ++Comment[sv]=Konfigurera SELinux i en grafisk miljö ++Comment[ta]=SELinuxஐ ஒரு வரைகலை அமைவில் கட்டமைக்கவும் ++Comment[te]=SELinuxను గ్రాఫికల్ అమర్పునందు ఆకృతీకరించుము ++Comment[uk]=Засіб для налаштування SELinux з графічним інтерфейсом ++Comment[zh_CN]=在图形设置中配置 SELinux ++Comment[zh_TW]=在圖形話設定中配置 SELinux ++StartupNotify=true ++Icon=system-config-selinux ++Exec=/usr/bin/system-config-selinux ++Type=Application ++Terminal=false ++Categories=System;Security; ++X-Desktop-File-Install-Version=0.2 ++Keywords=policy;security;selinux;avc;permission;mac; +diff --git a/policycoreutils/gui/system-config-selinux.pam b/policycoreutils/gui/system-config-selinux.pam +new file mode 100644 +index 0000000..6a8c230 +--- /dev/null ++++ b/policycoreutils/gui/system-config-selinux.pam +@@ -0,0 +1,8 @@ ++#%PAM-1.0 ++auth sufficient pam_rootok.so ++auth sufficient pam_timestamp.so ++auth include system-auth ++session required pam_permit.so ++session optional pam_xauth.so ++session optional pam_timestamp.so ++account required pam_permit.so +diff --git a/policycoreutils/gui/system-config-selinux.png b/policycoreutils/gui/system-config-selinux.png +new file mode 100644 +index 0000000..68ffcb7 +Binary files /dev/null and b/policycoreutils/gui/system-config-selinux.png differ +diff --git a/policycoreutils/newrole/newrole.c b/policycoreutils/newrole/newrole.c +index 8fbf2d0..3753ef4 100644 +--- a/policycoreutils/newrole/newrole.c ++++ b/policycoreutils/newrole/newrole.c +@@ -680,7 +680,7 @@ static int relabel_tty(const char *ttyn, security_context_t new_context, + security_context_t * tty_context, + security_context_t * new_tty_context) + { +- int fd; ++ int fd, rc; + int enforcing = security_getenforce(); + security_context_t tty_con = NULL; + security_context_t new_tty_con = NULL; +@@ -699,7 +699,13 @@ static int relabel_tty(const char *ttyn, security_context_t new_context, + fprintf(stderr, _("Error! Could not open %s.\n"), ttyn); + return fd; + } +- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ /* this craziness is to make sure we cann't block on open and deadlock */ ++ rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ if (rc) { ++ fprintf(stderr, _("Error! Could not clear O_NONBLOCK on %s\n"), ttyn); ++ close(fd); ++ return rc; ++ } + + if (fgetfilecon(fd, &tty_con) < 0) { + fprintf(stderr, _("%s! Could not get current context " +@@ -1010,9 +1016,9 @@ int main(int argc, char *argv[]) + int fd; + pid_t childPid = 0; + char *shell_argv0 = NULL; ++ int rc; + + #ifdef USE_PAM +- int rc; + int pam_status; /* pam return code */ + pam_handle_t *pam_handle; /* opaque handle used by all PAM functions */ + +@@ -1226,15 +1232,23 @@ int main(int argc, char *argv[]) + fd = open(ttyn, O_RDONLY | O_NONBLOCK); + if (fd != 0) + goto err_close_pam; +- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ if (rc) ++ goto err_close_pam; ++ + fd = open(ttyn, O_RDWR | O_NONBLOCK); + if (fd != 1) + goto err_close_pam; +- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ if (rc) ++ goto err_close_pam; ++ + fd = open(ttyn, O_RDWR | O_NONBLOCK); + if (fd != 2) + goto err_close_pam; +- fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ rc = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK); ++ if (rc) ++ goto err_close_pam; + + } + /* +diff --git a/policycoreutils/po/Makefile b/policycoreutils/po/Makefile +index a377996..9c1486e 100644 +--- a/policycoreutils/po/Makefile ++++ b/policycoreutils/po/Makefile +@@ -81,12 +81,16 @@ POTFILES = \ + ../sepolicy/sepolicy/templates/var_log.py \ + ../sepolicy/sepolicy/templates/var_run.py \ + ../sepolicy/sepolicy/templates/var_spool.py \ ++ booleans.py + + #default:: clean + + all:: $(MOFILES) + +-$(POTFILE): $(POTFILES) ++booleans.py: ++ sepolicy booleans -a > booleans.py ++ ++$(POTFILE): $(POTFILES) booleans.py + $(XGETTEXT) --keyword=_ --keyword=N_ $(POTFILES) + @if cmp -s $(NLSPACKAGE).po $(POTFILE); then \ + rm -f $(NLSPACKAGE).po; \ +@@ -95,6 +99,7 @@ $(POTFILE): $(POTFILES) + fi; \ + + update-po: Makefile $(POTFILE) refresh-po ++ @rm -f booleans.py + + refresh-po: Makefile + for cat in $(POFILES); do \ +diff --git a/policycoreutils/restorecond/Makefile b/policycoreutils/restorecond/Makefile +index 3074542..3b704d8 100644 +--- a/policycoreutils/restorecond/Makefile ++++ b/policycoreutils/restorecond/Makefile +@@ -5,6 +5,7 @@ LIBDIR ?= $(PREFIX)/lib + MANDIR = $(PREFIX)/share/man + AUTOSTARTDIR = $(DESTDIR)/etc/xdg/autostart + DBUSSERVICEDIR = $(DESTDIR)/usr/share/dbus-1/services ++SYSTEMDDIR ?= $(DESTDIR)/usr/lib/systemd + + autostart_DATA = sealertauto.desktop + INITDIR = $(DESTDIR)/etc/rc.d/init.d +@@ -39,7 +40,8 @@ install: all + install -m 644 restorecond.desktop $(AUTOSTARTDIR)/restorecond.desktop + -mkdir -p $(DBUSSERVICEDIR) + install -m 600 org.selinux.Restorecond.service $(DBUSSERVICEDIR)/org.selinux.Restorecond.service +- ++ -mkdir -p $(SYSTEMDDIR)/system ++ install -m 644 restorecond.service $(SYSTEMDDIR)/system/ + relabel: install + /sbin/restorecon $(SBINDIR)/restorecond + +diff --git a/policycoreutils/restorecond/restorecond.service b/policycoreutils/restorecond/restorecond.service +new file mode 100644 +index 0000000..11f4ffd +--- /dev/null ++++ b/policycoreutils/restorecond/restorecond.service +@@ -0,0 +1,12 @@ ++[Unit] ++Description=Restorecon maintaining path file context ++After=syslog.target ++ConditionPathExists=/etc/selinux/restorecond.conf ++ ++[Service] ++Type=oneshot ++ExecStart=/usr/sbin/restorecond ++RemainAfterExit=yes ++ ++[Install] ++WantedBy=multi-user.target +diff --git a/policycoreutils/restorecond/user.c b/policycoreutils/restorecond/user.c +index 00a646f..2c28676 100644 +--- a/policycoreutils/restorecond/user.c ++++ b/policycoreutils/restorecond/user.c +@@ -54,6 +54,7 @@ static const char *PATH="/org/selinux/Restorecond"; + static const char *INTERFACE="org.selinux.RestorecondIface"; + static const char *RULE="type='signal',interface='org.selinux.RestorecondIface'"; + ++static int local_lock_fd = -1; + + static DBusHandlerResult + signal_filter (DBusConnection *connection __attribute__ ((__unused__)), DBusMessage *message, void *user_data) +@@ -201,17 +202,18 @@ static int local_server() { + perror("asprintf"); + return -1; + } +- int fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); ++ local_lock_fd = open(ptr, O_CREAT | O_WRONLY | O_NOFOLLOW | O_CLOEXEC, S_IRUSR | S_IWUSR); + if (debug_mode) + g_warning ("Lock file: %s", ptr); + + free(ptr); +- if (fd < 0) { ++ if (local_lock_fd < 0) { + if (debug_mode) + perror("open"); + return -1; + } +- if (flock(fd, LOCK_EX | LOCK_NB) < 0) { ++ if (flock(local_lock_fd, LOCK_EX | LOCK_NB) < 0) { ++ close(local_lock_fd); + if (debug_mode) + perror("flock"); + return -1; +@@ -226,6 +228,12 @@ static int local_server() { + return 0; + } + ++static void end_local_server(void) { ++ if (local_lock_fd >= 0) ++ close(local_lock_fd); ++ local_lock_fd = -1; ++} ++ + int server(int master_fd, const char *watch_file) { + GMainLoop *loop; + +@@ -253,6 +261,7 @@ int server(int master_fd, const char *watch_file) { + g_main_loop_run (loop); + + end: ++ end_local_server(); + g_main_loop_unref (loop); + return 0; + } +diff --git a/policycoreutils/sandbox/sandbox b/policycoreutils/sandbox/sandbox +index b629006..6631c2d 100644 +--- a/policycoreutils/sandbox/sandbox ++++ b/policycoreutils/sandbox/sandbox +@@ -243,7 +243,7 @@ class Sandbox: + copyfile(f, "/tmp", self.__tmpdir) + copyfile(f, "/var/tmp", self.__tmpdir) + +- def __setup_sandboxrc(self, wm = "/usr/bin/matchbox-window-manager -use_titlebar no"): ++ def __setup_sandboxrc(self, wm = "/usr/bin/openbox"): + execfile =self.__homedir + "/.sandboxrc" + fd = open(execfile, "w+") + if self.__options.session: +@@ -333,7 +333,7 @@ sandbox [-h] [-c] [-l level ] [-[X|M] [-H homedir] [-T tempdir]] [-I includefile + + parser.add_option("-W", "--windowmanager", dest="wm", + type="string", +- default="/usr/bin/matchbox-window-manager -use_titlebar no", ++ default="/usr/bin/openbox", + help=_("alternate window manager")) + + parser.add_option("-l", "--level", dest="level", +diff --git a/policycoreutils/sandbox/sandbox.8 b/policycoreutils/sandbox/sandbox.8 +index 521afcd..a50eef2 100644 +--- a/policycoreutils/sandbox/sandbox.8 ++++ b/policycoreutils/sandbox/sandbox.8 +@@ -70,7 +70,7 @@ Specifies the windowsize when creating an X based Sandbox. The default windowsiz + \fB\-W windowmanager\fR + Select alternative window manager to run within + .B sandbox -X. +-Default to /usr/bin/matchbox-window-manager. ++Default to /usr/bin/openbox. + .TP + \fB\-X\fR + Create an X based Sandbox for gui apps, temporary files for +diff --git a/policycoreutils/sandbox/sandboxX.sh b/policycoreutils/sandbox/sandboxX.sh +index 23de6f6..171bb05 100644 +--- a/policycoreutils/sandbox/sandboxX.sh ++++ b/policycoreutils/sandbox/sandboxX.sh +@@ -6,6 +6,20 @@ export TITLE="Sandbox $context -- `grep ^#TITLE: ~/.sandboxrc | /usr/bin/cut -b8 + [ -z $2 ] && export DPI="96" || export DPI="$2" + trap "exit 0" HUP + ++mkdir -p ~/.config/openbox ++cat > ~/.config/openbox/rc.xml << EOF ++ ++ ++ ++ no ++ all ++ yes ++ ++ ++ ++EOF ++ + (/usr/bin/Xephyr -title "$TITLE" -terminate -screen $SCREENSIZE -dpi $DPI -nolisten tcp -displayfd 5 5>&1 2>/dev/null) | while read D; do + export DISPLAY=:$D + cat > ~/seremote << __EOF +diff --git a/policycoreutils/sandbox/seunshare.c b/policycoreutils/sandbox/seunshare.c +index dbd5977..f10df39 100644 +--- a/policycoreutils/sandbox/seunshare.c ++++ b/policycoreutils/sandbox/seunshare.c +@@ -962,7 +962,7 @@ int main(int argc, char **argv) { + char *LANG = NULL; + int rc = -1; + +- if (unshare(CLONE_NEWNS) < 0) { ++ if (unshare(CLONE_NEWNS | CLONE_NEWIPC) < 0) { + perror(_("Failed to unshare")); + goto childerr; + } +diff --git a/policycoreutils/scripts/Makefile b/policycoreutils/scripts/Makefile +index 201a988..f5d6e9d 100644 +--- a/policycoreutils/scripts/Makefile ++++ b/policycoreutils/scripts/Makefile +@@ -9,23 +9,12 @@ LOCALEDIR ?= $(PREFIX)/share/locale + .PHONY: all genhomedircon + all: fixfiles genhomedircon chcat + +-genhomedircon: +- @echo "#!/bin/sh" > genhomedircon +- @echo >> genhomedircon +- @if [ -z "${SEMODULE_PATH}" ]; then \ +- echo "${USRSBINDIR}/semodule -Bn" >> genhomedircon; \ +- else \ +- echo "${SEMODULE_PATH}/semodule -Bn" >> genhomedircon; \ +- fi +- + install: all + -mkdir -p $(BINDIR) + install -m 755 chcat $(BINDIR) + install -m 755 fixfiles $(SBINDIR) +- install -m 755 genhomedircon $(USRSBINDIR) + -mkdir -p $(MANDIR)/man8 + install -m 644 fixfiles.8 $(MANDIR)/man8/ +- install -m 644 genhomedircon.8 $(MANDIR)/man8/ + install -m 644 chcat.8 $(MANDIR)/man8/ + + clean: +diff --git a/policycoreutils/scripts/genhomedircon.8 b/policycoreutils/scripts/genhomedircon.8 +deleted file mode 100644 +index 8ec509c..0000000 +--- a/policycoreutils/scripts/genhomedircon.8 ++++ /dev/null +@@ -1,24 +0,0 @@ +-.TH GENHOMEDIRCON "12" "Sep 2011" "Security Enhanced Linux" "SELinux" +-.SH NAME +-genhomedircon \- generate SELinux file context configuration entries for user home directories +-.SH SYNOPSIS +-.B genhomedircon +-is a script that executes +-.B semodule +-to rebuild the currently active SELinux policy (without reloading it) and to create the +-labels for each user home directory based on directory paths returned by calls to getpwent(). +- +-The latter functionality depends on the "usepasswd" parameter being set to "true" (default) +-in /etc/selinux/semanage.conf. +- +-This script is usually executed by +-.B semanage +-although this default behavior can be optionally modified by setting to "true" the +-"disable-genhomedircon" in /etc/selinux/semanage.conf. +- +-.SH AUTHOR +-This manual page was written by +-.I Dan Walsh +- +-.SH "SEE ALSO" +-semanage.conf(5), semodule(8), semanage(8), getpwent(3), getpwent_r(3) +diff --git a/policycoreutils/semanage/default_encoding/Makefile b/policycoreutils/semanage/default_encoding/Makefile +new file mode 100644 +index 0000000..e15a877 +--- /dev/null ++++ b/policycoreutils/semanage/default_encoding/Makefile +@@ -0,0 +1,8 @@ ++all: ++ LDFLAGS="" python setup.py build ++ ++install: all ++ LDFLAGS="" python setup.py install --root=$(DESTDIR)/ ++ ++clean: ++ rm -rf build *~ +diff --git a/policycoreutils/semanage/default_encoding/default_encoding.c b/policycoreutils/semanage/default_encoding/default_encoding.c +new file mode 100644 +index 0000000..023b8f4 +--- /dev/null ++++ b/policycoreutils/semanage/default_encoding/default_encoding.c +@@ -0,0 +1,57 @@ ++/* ++ * Authors: ++ * John Dennis ++ * ++ * Copyright (C) 2009 Red Hat ++ * see file 'COPYING' for use and warranty information ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ */ ++ ++#include ++ ++PyDoc_STRVAR(setdefaultencoding_doc, ++"setdefaultencoding(encoding='utf-8')\n\ ++\n\ ++Set the current default string encoding used by the Unicode implementation.\n\ ++Defaults to utf-8." ++); ++ ++static PyObject * ++setdefaultencoding(PyObject *self, PyObject *args, PyObject *kwds) ++{ ++ static char *kwlist[] = {"utf-8", NULL}; ++ char *encoding; ++ ++ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s:setdefaultencoding", kwlist, &encoding)) ++ return NULL; ++ ++ if (PyUnicode_SetDefaultEncoding(encoding)) ++ return NULL; ++ ++ Py_RETURN_NONE; ++} ++ ++static PyMethodDef methods[] = { ++ {"setdefaultencoding", (PyCFunction)setdefaultencoding, METH_VARARGS|METH_KEYWORDS, setdefaultencoding_doc}, ++ {NULL, NULL} /* sentinel */ ++}; ++ ++ ++PyMODINIT_FUNC ++initdefault_encoding_utf8(void) ++{ ++ PyUnicode_SetDefaultEncoding("utf-8"); ++ Py_InitModule3("default_encoding_utf8", methods, "Forces the default encoding to utf-8"); ++} +diff --git a/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py b/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py +new file mode 100644 +index 0000000..ccb6b8b +--- /dev/null ++++ b/policycoreutils/semanage/default_encoding/policycoreutils/__init__.py +@@ -0,0 +1,17 @@ ++# ++# Copyright (C) 2006,2007,2008, 2009 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++# +diff --git a/policycoreutils/semanage/default_encoding/setup.py b/policycoreutils/semanage/default_encoding/setup.py +new file mode 100644 +index 0000000..e2befdb +--- /dev/null ++++ b/policycoreutils/semanage/default_encoding/setup.py +@@ -0,0 +1,38 @@ ++# Authors: ++# John Dennis ++# ++# Copyright (C) 2009 Red Hat ++# see file 'COPYING' for use and warranty information ++# ++# This program is free software; you can redistribute it and/or ++# modify it under the terms of the GNU General Public License as ++# published by the Free Software Foundation. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program; if not, write to the Free Software ++# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ++ ++from distutils.core import setup, Extension ++ ++default_encoding_utf8 = Extension('policycoreutils.default_encoding_utf8', ['default_encoding.c']) ++ ++setup(name = 'policycoreutils-default-encoding', ++ version = '0.1', ++ description = 'Forces the default encoding in Python to be utf-8', ++ long_description = 'Forces the default encoding in Python to be utf-8', ++ author = 'John Dennis', ++ author_email = 'jdennis@redhat.com', ++ maintainer = 'John Dennis', ++ maintainer_email = 'jdennis@redhat.com', ++ license = 'GPLv3+', ++ platforms = 'posix', ++ url = '', ++ download_url = '', ++ ext_modules = [default_encoding_utf8], ++ packages=["policycoreutils"], ++) +diff --git a/policycoreutils/semanage/semanage b/policycoreutils/semanage/semanage +index 6e33c85..49e4709 100644 +--- a/policycoreutils/semanage/semanage ++++ b/policycoreutils/semanage/semanage +@@ -20,6 +20,7 @@ + # 02111-1307 USA + # + # ++import policycoreutils.default_encoding_utf8 + import sys, getopt, re + import seobject + import selinux +@@ -32,7 +33,7 @@ gettext.textdomain(PROGNAME) + try: + gettext.install(PROGNAME, + localedir="/usr/share/locale", +- unicode=False, ++ unicode=True, + codeset = 'utf-8') + except IOError: + import __builtin__ +diff --git a/policycoreutils/semanage/seobject.py b/policycoreutils/semanage/seobject.py +index 85bc37f..02b1acd 100644 +--- a/policycoreutils/semanage/seobject.py ++++ b/policycoreutils/semanage/seobject.py +@@ -32,11 +32,10 @@ from IPy import IP + import gettext + gettext.bindtextdomain(PROGNAME, "/usr/share/locale") + gettext.textdomain(PROGNAME) +-try: +- gettext.install(PROGNAME, localedir = "/usr/share/locale", unicode = 1) +-except IOError: +- import __builtin__ +- __builtin__.__dict__['_'] = unicode ++ ++import gettext ++translation=gettext.translation(PROGNAME, localedir = "/usr/share/locale", fallback=True) ++_=translation.ugettext + + import syslog + +@@ -461,7 +460,9 @@ class loginRecords(semanageRecords): + if rc < 0: + raise ValueError(_("Could not check if login mapping for %s is defined") % name) + if exists: +- raise ValueError(_("Login mapping for %s is already defined") % name) ++ semanage_seuser_key_free(k) ++ return self.__modify(name, sename, serange) ++ + if name[0] == '%': + try: + grp.getgrnam(name[1:]) +@@ -731,7 +732,8 @@ class seluserRecords(semanageRecords): + if rc < 0: + raise ValueError(_("Could not check if SELinux user %s is defined") % name) + if exists: +- raise ValueError(_("SELinux user %s is already defined") % name) ++ semanage_user_key_free(k) ++ return self.__modify(name, roles, selevel, serange, prefix) + + (rc, u) = semanage_user_create(self.sh) + if rc < 0: +@@ -1274,7 +1276,8 @@ class nodeRecords(semanageRecords): + + (rc, exists) = semanage_node_exists(self.sh, k) + if exists: +- raise ValueError(_("Addr %s already defined") % addr) ++ semanage_node_key_free(k) ++ return self.__modify(addr, mask, self.protocol[proto], serange, ctype) + + (rc, node) = semanage_node_create(self.sh) + if rc < 0: +@@ -1475,7 +1478,8 @@ class interfaceRecords(semanageRecords): + if rc < 0: + raise ValueError(_("Could not check if interface %s is defined") % interface) + if exists: +- raise ValueError(_("Interface %s already defined") % interface) ++ semanage_iface_key_free(k) ++ return self.__modify(interface, serange, ctype) + + (rc, iface) = semanage_iface_create(self.sh) + if rc < 0: +@@ -1777,7 +1781,8 @@ class fcontextRecords(semanageRecords): + raise ValueError(_("Could not check if file context for %s is defined") % target) + + if exists: +- raise ValueError(_("File context for %s already defined") % target) ++ semanage_fcontext_key_free(k) ++ return self.__modify(target, type, ftype, serange, seuser) + + (rc, fcontext) = semanage_fcontext_create(self.sh) + if rc < 0: +diff --git a/policycoreutils/semodule/Makefile b/policycoreutils/semodule/Makefile +index 4c5243a..036c418 100644 +--- a/policycoreutils/semodule/Makefile ++++ b/policycoreutils/semodule/Makefile +@@ -11,7 +11,7 @@ LDLIBS = -lsepol -lselinux -lsemanage -L$(LIBDIR) + SEMODULE_OBJS = semodule.o + + .PHONY: all semodule_path +-all: semodule semodule_path ++all: semodule semodule_path genhomedircon + + semodule_path: + @echo -n $(SBINDIR) > ../scripts/semodule_path +@@ -19,11 +19,16 @@ semodule_path: + semodule: $(SEMODULE_OBJS) + $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + ++genhomedircon: ++ ln -sf semodule genhomedircon ++ + install: all + -mkdir -p $(SBINDIR) + install -m 755 semodule $(SBINDIR) ++ (cd $(SBINDIR); ln -sf semodule genhomedircon) + test -d $(MANDIR)/man8 || install -m 755 -d $(MANDIR)/man8 + install -m 644 semodule.8 $(MANDIR)/man8/ ++ install -m 644 genhomedircon.8 $(MANDIR)/man8/ + + relabel: + +diff --git a/policycoreutils/semodule/genhomedircon.8 b/policycoreutils/semodule/genhomedircon.8 +new file mode 100644 +index 0000000..8ec509c +--- /dev/null ++++ b/policycoreutils/semodule/genhomedircon.8 +@@ -0,0 +1,24 @@ ++.TH GENHOMEDIRCON "12" "Sep 2011" "Security Enhanced Linux" "SELinux" ++.SH NAME ++genhomedircon \- generate SELinux file context configuration entries for user home directories ++.SH SYNOPSIS ++.B genhomedircon ++is a script that executes ++.B semodule ++to rebuild the currently active SELinux policy (without reloading it) and to create the ++labels for each user home directory based on directory paths returned by calls to getpwent(). ++ ++The latter functionality depends on the "usepasswd" parameter being set to "true" (default) ++in /etc/selinux/semanage.conf. ++ ++This script is usually executed by ++.B semanage ++although this default behavior can be optionally modified by setting to "true" the ++"disable-genhomedircon" in /etc/selinux/semanage.conf. ++ ++.SH AUTHOR ++This manual page was written by ++.I Dan Walsh ++ ++.SH "SEE ALSO" ++semanage.conf(5), semodule(8), semanage(8), getpwent(3), getpwent_r(3) +diff --git a/policycoreutils/semodule/semodule.c b/policycoreutils/semodule/semodule.c +index 17b4fa5..6947b37 100644 +--- a/policycoreutils/semodule/semodule.c ++++ b/policycoreutils/semodule/semodule.c +@@ -19,6 +19,7 @@ + #include + #include + #include ++#include + + #include + +@@ -284,8 +285,12 @@ int main(int argc, char *argv[]) + int i, commit = 0; + int result; + int status = EXIT_FAILURE; +- ++ char *genhomedirconargv[] = { "genhomedircon", "-B", "-n" }; + create_signal_handlers(); ++ if (strcmp(basename(argv[0]), "genhomedircon") == 0) { ++ argc = 3; ++ argv=genhomedirconargv; ++ } + parse_command_line(argc, argv); + + if (build) +diff --git a/policycoreutils/sepolicy/sepolicy/__init__.py b/policycoreutils/sepolicy/sepolicy/__init__.py +index 5e7415c..37cd5dd 100644 +--- a/policycoreutils/sepolicy/sepolicy/__init__.py ++++ b/policycoreutils/sepolicy/sepolicy/__init__.py +@@ -145,10 +145,7 @@ def policy(policy_file): + raise ValueError(_("Failed to read %s policy file") % policy_file) + + +-policy_file = selinux.selinux_current_policy_path() +-if not policy_file: +- policy_file = __get_installed_policy() +- ++policy_file = __get_installed_policy() + try: + policy(policy_file) + except ValueError, e: +diff --git a/policycoreutils/setfiles/restorecon.8 b/policycoreutils/setfiles/restorecon.8 +index 80b6d6e..07c5ee2 100644 +--- a/policycoreutils/setfiles/restorecon.8 ++++ b/policycoreutils/setfiles/restorecon.8 +@@ -4,10 +4,10 @@ restorecon \- restore file(s) default SELinux security contexts. + + .SH "SYNOPSIS" + .B restorecon +-.I [\-o outfilename] [\-R] [\-n] [\-p] [\-v] [\-e directory] pathname... ++.I [\-R] [\-n] [\-p] [\-v] [\-e directory] pathname... + .P + .B restorecon +-.I \-f infilename [\-o outfilename] [\-e directory] [\-R] [\-n] [\-p] [\-v] [\-F] ++.I \-f infilename [\-e directory] [\-R] [\-n] [\-p] [\-v] [\-F] + + .SH "DESCRIPTION" + This manual page describes the +@@ -49,7 +49,7 @@ ignore files that do not exist. + don't change any file labels (passive check). + .TP + .B \-o outfilename +-save list of files with incorrect context in outfilename. ++Deprecated, SELinux policy will probably block this access. Use shell redirection to save list of files with incorrect context in filename. + .TP + .B \-p + show progress by printing * every STAR_COUNT files. (If you relabel the entire OS, this will show you the percentage complete.) +diff --git a/policycoreutils/setfiles/setfiles.8 b/policycoreutils/setfiles/setfiles.8 +index 89d2a49..12bca43 100644 +--- a/policycoreutils/setfiles/setfiles.8 ++++ b/policycoreutils/setfiles/setfiles.8 +@@ -4,7 +4,7 @@ setfiles \- set SELinux file security contexts. + + .SH "SYNOPSIS" + .B setfiles +-.I [\-c policy] [\-d] [\-l] [\-n] [\-e directory] [\-o filename] [\-q] [\-s] [\-v] [\-W] [\-F] spec_file pathname... ++.I [\-c policy] [\-d] [\-l] [\-n] [\-e directory] [\-q] [\-s] [\-v] [\-W] [\-F] spec_file pathname... + .SH "DESCRIPTION" + This manual page describes the + .BR setfiles +@@ -57,7 +57,7 @@ log changes in file labels to syslog. + don't change any file labels (passive check). + .TP + .B \-o filename +-save list of files with incorrect context in filename. ++Deprecated, SELinux policy will probably block this access. Use shell redirection to save list of files with incorrect context in filename. + .TP + .B \-p + show progress by printing * every STAR_COUNT files. (If you relabel the entire OS, this will show you the percentage complete.) +diff --git a/policycoreutils/setfiles/setfiles.c b/policycoreutils/setfiles/setfiles.c +index b11e49f..d3f02ae 100644 +--- a/policycoreutils/setfiles/setfiles.c ++++ b/policycoreutils/setfiles/setfiles.c +@@ -45,14 +45,14 @@ void usage(const char *const name) + { + if (iamrestorecon) { + fprintf(stderr, +- "usage: %s [-iFnprRv0] [-e excludedir] [-o filename] pathname...\n" +- "usage: %s [-iFnprRv0] [-e excludedir] [-o filename] -f filename\n", ++ "usage: %s [-iFnprRv0] [-e excludedir] pathname...\n" ++ "usage: %s [-iFnprRv0] [-e excludedir] -f filename\n", + name, name); + } else { + fprintf(stderr, +- "usage: %s [-dilnpqvFW] [-e excludedir] [-o filename] [-r alt_root_path] spec_file pathname...\n" +- "usage: %s [-dilnpqvFW] [-e excludedir] [-o filename] [-r alt_root_path] spec_file -f filename\n" +- "usage: %s -s [-dilnpqvFW] [-o filename] spec_file\n" ++ "usage: %s [-dilnpqvFW] [-e excludedir] [-r alt_root_path] spec_file pathname...\n" ++ "usage: %s [-dilnpqvFW] [-e excludedir] [-r alt_root_path] spec_file -f filename\n" ++ "usage: %s -s [-dilnpqvFW] spec_file\n" + "usage: %s -c policyfile spec_file\n", + name, name, name, name); + } +diff --git a/sepolgen/src/sepolgen/audit.py b/sepolgen/src/sepolgen/audit.py +index d636091..9ca35a7 100644 +--- a/sepolgen/src/sepolgen/audit.py ++++ b/sepolgen/src/sepolgen/audit.py +@@ -259,7 +259,7 @@ class AVCMessage(AuditMessage): + raise ValueError("Error during access vector computation") + + if self.type == audit2why.CONSTRAINT: +- self.data = [] ++ self.data = [ self.data ] + if self.scontext.user != self.tcontext.user: + self.data.append("user") + if self.scontext.role != self.tcontext.role and self.tcontext.role != "object_r": diff --git a/libselinux.spec b/libselinux.spec index 0d41c36..ada1688 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -10,7 +10,7 @@ Summary: SELinux library and simple utilities Name: libselinux Version: 2.1.13 -Release: 1%{?dist} +Release: 2%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -241,6 +241,9 @@ rm -rf %{buildroot} %{ruby_sitearch}/selinux.so %changelog +* Thu Feb 14 2013 Dan Walsh - 2.1.13-2 +- Revert some changes which are causing the wrong policy version file to be created + * Thu Feb 7 2013 Dan Walsh - 2.1.13-1 - Update to upstream * audit2why: make sure path is nul terminated