2013-02-15 16:02:20 +00:00
|
|
|
diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h
|
|
|
|
index a4079aa..82954c2 100644
|
|
|
|
--- a/libselinux/include/selinux/selinux.h
|
|
|
|
+++ b/libselinux/include/selinux/selinux.h
|
|
|
|
@@ -498,6 +498,7 @@ 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 const char *selinux_failsafe_context_path(void);
|
|
|
|
extern const char *selinux_removable_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..503c52c 100644
|
|
|
|
--- a/libselinux/man/man3/selinux_binary_policy_path.3
|
|
|
|
+++ b/libselinux/man/man3/selinux_binary_policy_path.3
|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
.TH "selinux_binary_policy_path" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation"
|
|
|
|
.SH "NAME"
|
|
|
|
-selinux_path, selinux_policy_root, selinux_binary_policy_path,
|
|
|
|
+selinux_path, selinux_policy_root, selinux_binary_policy_path, selinux_current_policy_path,
|
|
|
|
selinux_failsafe_context_path, selinux_removable_context_path,
|
|
|
|
selinux_default_context_path, selinux_user_contexts_path,
|
|
|
|
selinux_file_context_path, selinux_media_context_path,
|
|
|
|
@@ -17,6 +17,8 @@ directories and files
|
|
|
|
.sp
|
|
|
|
.B const char *selinux_binary_policy_path(void);
|
|
|
|
.sp
|
|
|
|
+.B const char *selinux_current_policy_path(void);
|
|
|
|
+.sp
|
|
|
|
.B const char *selinux_failsafe_context_path(void);
|
|
|
|
.sp
|
|
|
|
.B const char *selinux_removable_context_path(void);
|
|
|
|
@@ -55,6 +57,9 @@ returns the top-level policy directory.
|
|
|
|
.BR selinux_binary_policy_path ()
|
|
|
|
returns the binary policy file loaded into kernel.
|
|
|
|
.sp
|
|
|
|
+.BR selinux_current_policy_path ()
|
|
|
|
+returns the currently loaded policy file from the kernel.
|
|
|
|
+.sp
|
|
|
|
.BR selinux_default_type_path ()
|
|
|
|
returns the context file mapping roles to default types.
|
|
|
|
.sp
|
|
|
|
diff --git a/libselinux/man/man3/selinux_current_policy_path.3 b/libselinux/man/man3/selinux_current_policy_path.3
|
|
|
|
new file mode 100644
|
|
|
|
index 0000000..175a611
|
|
|
|
--- /dev/null
|
|
|
|
+++ b/libselinux/man/man3/selinux_current_policy_path.3
|
|
|
|
@@ -0,0 +1 @@
|
|
|
|
+.so man3/selinux_binary_policy_path.3
|
2012-03-29 18:39:18 +00:00
|
|
|
diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c
|
2013-02-15 16:02:20 +00:00
|
|
|
index ffe381b..560bc25 100644
|
2012-03-29 18:39:18 +00:00
|
|
|
--- a/libselinux/src/audit2why.c
|
|
|
|
+++ b/libselinux/src/audit2why.c
|
2013-02-15 16:02:20 +00:00
|
|
|
@@ -210,27 +210,12 @@ static int __policy_init(const char *init_path)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
- vers = sepol_policy_kern_vers_max();
|
|
|
|
- if (vers < 0) {
|
|
|
|
- snprintf(errormsg, sizeof(errormsg),
|
|
|
|
- "Could not get policy version: %s\n",
|
|
|
|
- strerror(errno));
|
|
|
|
- PyErr_SetString( PyExc_ValueError, errormsg);
|
|
|
|
- return 1;
|
|
|
|
- }
|
|
|
|
- snprintf(path, PATH_MAX, "%s.%d",
|
|
|
|
- selinux_binary_policy_path(), vers);
|
|
|
|
- fp = fopen(path, "r");
|
|
|
|
- while (!fp && errno == ENOENT && --vers) {
|
|
|
|
- snprintf(path, PATH_MAX, "%s.%d",
|
|
|
|
- selinux_binary_policy_path(), vers);
|
|
|
|
- fp = fopen(path, "r");
|
|
|
|
- }
|
|
|
|
+ fp = fopen(selinux_current_policy_path(), "r");
|
|
|
|
if (!fp) {
|
|
|
|
snprintf(errormsg, sizeof(errormsg),
|
|
|
|
- "unable to open %s.%d: %s\n",
|
|
|
|
- selinux_binary_policy_path(),
|
|
|
|
- security_policyvers(), strerror(errno));
|
|
|
|
+ "unable to open %s: %s\n",
|
|
|
|
+ selinux_current_policy_path(),
|
|
|
|
+ strerror(errno));
|
|
|
|
PyErr_SetString( PyExc_ValueError, errormsg);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
@@ -310,10 +295,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) {
|
2012-11-19 20:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define RETURN(X) \
|
|
|
|
- PyTuple_SetItem(result, 0, Py_BuildValue("i", X)); \
|
|
|
|
- return result;
|
|
|
|
+ { \
|
|
|
|
+ return Py_BuildValue("iO", (X), Py_None); \
|
|
|
|
+ }
|
2012-11-16 21:49:57 +00:00
|
|
|
|
|
|
|
static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) {
|
|
|
|
+ char *reason_buf = NULL;
|
|
|
|
security_context_t scon;
|
|
|
|
security_context_t tcon;
|
|
|
|
char *tclassstr;
|
2013-02-15 16:02:20 +00:00
|
|
|
@@ -328,10 +315,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
|
2012-11-19 20:17:16 +00:00
|
|
|
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;
|
2013-02-15 16:02:20 +00:00
|
|
|
@@ -342,22 +325,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
|
2012-11-19 20:17:16 +00:00
|
|
|
/* 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;
|
|
|
|
|
2013-02-15 16:02:20 +00:00
|
|
|
@@ -377,21 +359,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
|
2012-11-19 20:17:16 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
perm = string_to_av_perm(tclass, permstr);
|
|
|
|
- if (!perm) {
|
|
|
|
+ if (!perm)
|
|
|
|
RETURN(BADPERM)
|
|
|
|
- }
|
|
|
|
+
|
|
|
|
av |= perm;
|
2012-11-16 21:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Reproduce the computation. */
|
|
|
|
- rc = sepol_compute_av_reason(ssid, tsid, tclass, av, &avd, &reason);
|
2012-11-19 20:17:16 +00:00
|
|
|
- if (rc < 0) {
|
2013-01-04 22:27:39 +00:00
|
|
|
+ rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0);
|
2012-11-19 20:17:16 +00:00
|
|
|
+ if (rc < 0)
|
2012-11-16 21:49:57 +00:00
|
|
|
RETURN(BADCOMPUTE)
|
2012-11-19 20:17:16 +00:00
|
|
|
- }
|
|
|
|
|
|
|
|
- if (!reason) {
|
|
|
|
+ if (!reason)
|
|
|
|
RETURN(ALLOW)
|
|
|
|
- }
|
|
|
|
+
|
|
|
|
if (reason & SEPOL_COMPUTEAV_TE) {
|
|
|
|
avc->ssid = ssid;
|
|
|
|
avc->tsid = tsid;
|
2013-02-15 16:02:20 +00:00
|
|
|
@@ -404,28 +385,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args
|
2012-11-19 20:17:16 +00:00
|
|
|
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);
|
|
|
|
}
|
2012-11-16 21:49:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (reason & SEPOL_COMPUTEAV_CONS) {
|
2012-11-19 20:17:16 +00:00
|
|
|
- RETURN(CONSTRAINT);
|
|
|
|
+ if (reason_buf) {
|
|
|
|
+ PyObject *result = NULL;
|
|
|
|
+ result = Py_BuildValue("is", CONSTRAINT, reason_buf);
|
|
|
|
+ free(reason_buf);
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+ RETURN(CONSTRAINT)
|
2012-11-16 21:49:57 +00:00
|
|
|
}
|
|
|
|
|
2013-02-07 17:33:50 +00:00
|
|
|
if (reason & SEPOL_COMPUTEAV_RBAC)
|
2012-03-29 18:39:18 +00:00
|
|
|
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;
|
|
|
|
}
|
2012-01-23 16:28:11 +00:00
|
|
|
|
2013-02-07 17:33:50 +00:00
|
|
|
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;
|
2011-09-02 12:58:11 +00:00
|
|
|
|
2013-02-07 17:33:50 +00:00
|
|
|
@@ -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,
|
|
|
|
}
|
|
|
|
}
|
2011-09-02 12:58:11 +00:00
|
|
|
|
2013-02-07 17:33:50 +00:00
|
|
|
+ if (!nordered)
|
|
|
|
+ goto failsafe;
|
2013-01-25 14:35:30 +00:00
|
|
|
+
|
2013-02-07 17:33:50 +00:00
|
|
|
/* 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);
|
2011-09-02 12:58:11 +00:00
|
|
|
|
2013-02-07 17:33:50 +00:00
|
|
|
- /* 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;
|
|
|
|
}
|
2012-09-14 09:59:45 +00:00
|
|
|
|
2013-01-04 22:27:39 +00:00
|
|
|
out:
|
2013-02-07 17:33:50 +00:00
|
|
|
@@ -523,14 +520,6 @@ int get_ordered_context_list(const char *user,
|
2013-01-04 22:27:39 +00:00
|
|
|
}
|
2013-02-07 17:33:50 +00:00
|
|
|
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)
|
2010-12-21 21:29:19 +00:00
|
|
|
diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c
|
2012-09-14 09:59:45 +00:00
|
|
|
index 2d7369e..2a00807 100644
|
2010-12-21 21:29:19 +00:00
|
|
|
--- a/libselinux/src/matchpathcon.c
|
|
|
|
+++ b/libselinux/src/matchpathcon.c
|
2011-08-30 15:08:49 +00:00
|
|
|
@@ -2,6 +2,7 @@
|
2009-03-27 18:25:16 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
+#include <syslog.h>
|
|
|
|
#include "selinux_internal.h"
|
|
|
|
#include "label_internal.h"
|
|
|
|
#include "callbacks.h"
|
2011-08-30 15:08:49 +00:00
|
|
|
@@ -62,7 +63,7 @@ static void
|
2009-03-27 18:25:16 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
- vfprintf(stderr, fmt, ap);
|
|
|
|
+ vsyslog(LOG_ERR, fmt, ap);
|
|
|
|
va_end(ap);
|
|
|
|
}
|
2009-01-27 20:00:47 +00:00
|
|
|
|
2013-02-15 16:02:20 +00:00
|
|
|
diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c
|
|
|
|
index 296f357..4913c55 100644
|
|
|
|
--- a/libselinux/src/selinux_config.c
|
|
|
|
+++ b/libselinux/src/selinux_config.c
|
|
|
|
@@ -8,6 +8,7 @@
|
|
|
|
#include <limits.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <pthread.h>
|
|
|
|
+#include "policy.h"
|
|
|
|
#include "selinux_internal.h"
|
|
|
|
#include "get_default_type_internal.h"
|
|
|
|
|
|
|
|
@@ -303,6 +304,29 @@ const char *selinux_binary_policy_path(void)
|
|
|
|
|
|
|
|
hidden_def(selinux_binary_policy_path)
|
|
|
|
|
|
|
|
+const char *selinux_current_policy_path(void)
|
|
|
|
+{
|
|
|
|
+ int rc = 0;
|
|
|
|
+ int vers = 0;
|
|
|
|
+ static char policy_path[PATH_MAX];
|
|
|
|
+
|
|
|
|
+ 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;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return policy_path;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+hidden_def(selinux_current_policy_path)
|
|
|
|
+
|
|
|
|
const char *selinux_file_context_path(void)
|
|
|
|
{
|
|
|
|
return get_path(FILE_CONTEXTS);
|
|
|
|
diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h
|
|
|
|
index 2c7c85c..4a4aebc 100644
|
|
|
|
--- a/libselinux/src/selinux_internal.h
|
|
|
|
+++ b/libselinux/src/selinux_internal.h
|
|
|
|
@@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy)
|
|
|
|
hidden_proto(security_setenforce)
|
|
|
|
hidden_proto(security_deny_unknown)
|
|
|
|
hidden_proto(selinux_boolean_sub)
|
|
|
|
+ hidden_proto(selinux_current_policy_path)
|
|
|
|
hidden_proto(selinux_binary_policy_path)
|
|
|
|
hidden_proto(selinux_booleans_subs_path)
|
|
|
|
hidden_proto(selinux_default_context_path)
|