libselinux/libselinux-rhat.patch

2442 lines
80 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
index ffe381b..2d68482 100644
--- a/libselinux/src/audit2why.c
+++ b/libselinux/src/audit2why.c
@@ -310,10 +310,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 +330,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 +340,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 +374,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 +400,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/get_context_list.c b/libselinux/src/get_context_list.c
index b9e8002..355730a 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) {
@@ -465,31 +465,28 @@ int get_ordered_context_list(const char *user,
}
}
+ 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 +520,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/matchpathcon.c b/libselinux/src/matchpathcon.c
index 2d7369e..2a00807 100644
--- a/libselinux/src/matchpathcon.c
+++ b/libselinux/src/matchpathcon.c
@@ -2,6 +2,7 @@
#include <string.h>
#include <errno.h>
#include <stdio.h>
+#include <syslog.h>
#include "selinux_internal.h"
#include "label_internal.h"
#include "callbacks.h"
@@ -62,7 +63,7 @@ static void
{
va_list ap;
va_start(ap, fmt);
- vfprintf(stderr, fmt, ap);
+ vsyslog(LOG_ERR, fmt, ap);
va_end(ap);
}
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
/* 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
/* 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
#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);
+
+/*
+ * 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 <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -54,6 +59,7 @@
#include <sepol/policydb/services.h>
#include <sepol/policydb/conditional.h>
#include <sepol/policydb/flask.h>
+#include <sepol/policydb/util.h>
#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;
+ }
+ stack[next_stack_entry] = expr_ptr;
+ next_stack_entry++;
+}
+
+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;
+ unsigned int i;
+ char tmp_buf[128];
+ /* if -type_names->types is 0, then output string <empty_set> */
+ int empty_set = 0;
+
+ 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], "<empty_set> ");
+ cat_expr_buf(expr_list[expr_counter], "} ");
+ }
+ return;
+}
+
+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);
+}
+
+/* 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)
{
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
+<openbox_config xmlns="http://openbox.org/3.4/rc"
+ xmlns:xi="http://www.w3.org/2001/XInclude">
+<applications>
+ <application class="*">
+ <decor>no</decor>
+ <desktop>all</desktop>
+ <maximized>yes</maximized>
+ </application>
+</applications>
+</openbox_config>
+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 <dwalsh@redhat.com>
-
-.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 <jdennis@redhat.com>
+ *
+ * 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 <Python.h>
+
+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 <jdennis@redhat.com>
+#
+# 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 <dwalsh@redhat.com>
+
+.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 <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <libgen.h>
#include <semanage/modules.h>
@@ -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":