libselinux/libselinux-rhat.patch
Dan Walsh c1553db668 Update to upstream
* audit2why: make sure path is nul terminated
        * utils: new file context regex compiler
        * label_file: use precompiled filecontext when possible
        * do not leak mmapfd
        * sefcontontext_compile: Add error handling to help debug problems in libsemanage.
        * man: make selinux.8 mention service man pages
        * audit2why: Fix segfault if finish() called twice
        * audit2why: do not leak on multiple init() calls
        * mode_to_security_class: interface to translate a mode_t in to a security class
        * audit2why: Cleanup audit2why analysys function
        * man: Fix program synopsis and function prototypes in man pages
        * man: Fix man pages formatting
        * man: Fix typo in man page
        * man: Add references and man page links to _raw function variants
        * Use ENOTSUP instead of EOPNOTSUPP for getfilecon functions
        * man: context_new(3): fix the return value description
        * selinux_status_open: handle error from sysconf
        * selinux_status_open: do not leak statusfd on exec
        * Fix errors found by coverity
        * Change boooleans.subs to booleans.subs_dist.
        * optimize set*con functions
        * pkg-config do not specifc ruby version
        * unmap file contexts on selabel_close()
        * do not leak file contexts with mmap'd backend
        * sefcontext_compile: do not leak fd on error
        * matchmediacon: do not leak fd
        * src/label_android_property: do not leak fd on error
2013-02-07 12:33:50 -05:00

542 lines
15 KiB
Diff

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
--- 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) {
}
#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 +305,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 +315,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 +349,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 +375,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/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
+++ 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/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 <unistd.h>
#include <pthread.h>
#include "selinux_internal.h"
+#include "policy.h"
#include "get_default_type_internal.h"
#define SELINUXDIR "/etc/selinux/"
@@ -296,13 +297,57 @@ const char *selinux_removable_context_path(void)
hidden_def(selinux_removable_context_path)
+char *selinux_binary_policy_path_min_max(int min, int *max)
+{
+ int ret;
+ char *path = NULL;
+
+ 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;
+ }
+err:
+ free(path);
+ return NULL;
+}
+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)
+{
+ 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..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)