summaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
authorDaniel J Walsh <dwalsh@redhat.com>2010-07-28 09:39:54 -0400
committerLennart Poettering <lennart@poettering.net>2010-08-03 23:45:22 +0200
commit56cf987fe74270bde4e16c7ec9e0414a9030723b (patch)
treeba36afd8f8da67dd0ed744997a2e4167e2883cc6 /src/util.c
parent8b33e5ca72def2b79ffcd9b7e96f8f40f6bd4a20 (diff)
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 07/28/2010 05:57 AM, Kay Sievers wrote: > On Wed, Jul 28, 2010 at 11:43, Lennart Poettering > <lennart@poettering.net> wrote: >> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote: >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file >>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1 >>> comm="systemd" name="autofs" dev=devtmpfs ino=9482 >>> scontext=system_u:system_r:init_t:s0 >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file >>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1 >>> comm="systemd" name="autofs" dev=devtmpfs ino=9482 >>> scontext=system_u:system_r:init_t:s0 >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file >>> >>> Lennart, we talked about this earlier. I think this is caused by the >>> modprobe calls to create /dev/autofs. Since udev is not created at the >>> point that init loads the kernel modules, the devices get created with >>> the wrong label. Once udev starts the labels get fixed. >>> >>> I can allow init_t to read device_t chr_files. >> >> Hmm, I think a cleaner fix would be to make systemd relabel this device >> properly before accessing it? Given that this is only one device this >> should not be a problem for us to maintain, I think? How would the >> fixing of the label work? Would we have to spawn restorecon for this, or >> can we actually do this in C without too much work? > > I guess we can just do what udev is doing, and call setfilecon(), with > a context of an earlier matchpathcon(). > > Kay > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel Here is the updated patch with a fix for the labeling of /dev/autofs -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/ iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk =pC2e
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c244
1 files changed, 241 insertions, 3 deletions
diff --git a/src/util.c b/src/util.c
index da8a6c3336..2279efac49 100644
--- a/src/util.c
+++ b/src/util.c
@@ -56,6 +56,244 @@
#include "log.h"
#include "strv.h"
+#if HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+
+static struct selabel_handle *label_hnd = NULL;
+
+static inline int use_selinux(void) {
+ static int use_selinux_ind = -1;
+
+ if (use_selinux_ind == -1)
+ use_selinux_ind = (is_selinux_enabled() == 1);
+
+ return use_selinux_ind;
+}
+
+static int label_get_file_label_from_path(
+ const char *label,
+ const char *path,
+ const char *class,
+ security_context_t *fcon) {
+
+ security_context_t dir_con = NULL;
+ security_class_t sclass;
+ int r = 0;
+
+ r = getfilecon(path, &dir_con);
+ if (r >= 0) {
+ r = -1;
+ if ((sclass = string_to_security_class(class)) != 0)
+ r = security_compute_create((security_context_t) label, dir_con, sclass, fcon);
+ }
+ if (r < 0)
+ r = -errno;
+
+ freecon(dir_con);
+ return r;
+}
+
+#endif
+
+int label_init(void) {
+ int r = 0;
+
+#if HAVE_SELINUX
+ if (use_selinux()) {
+ label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+ if (!label_hnd) {
+ log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m");
+ r = (security_getenforce() == 1) ? -errno : 0;
+ }
+ }
+#endif
+
+ return r;
+}
+
+int label_fix(const char *path) {
+ int r = 0;
+#if HAVE_SELINUX
+ struct stat st;
+ security_context_t fcon;
+ if (use_selinux()) {
+ r = lstat(path, &st);
+
+ if (r == 0) {
+ r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
+
+ if (r == 0) {
+ r = setfilecon(path, fcon);
+ freecon(fcon);
+ }
+ }
+ if (r < 0) {
+ log_error("Unable to fix label of %s: %m", path);
+ r = (security_getenforce() == 1) ? -errno : 0;
+ }
+ }
+#endif
+ return r;
+}
+
+void label_finish(void) {
+
+#if HAVE_SELINUX
+ if (use_selinux())
+ selabel_close(label_hnd);
+#endif
+
+}
+
+int label_get_socket_label_from_exe(
+ const char *exe,
+ char **label) {
+ int r = 0;
+
+#if HAVE_SELINUX
+ security_context_t mycon = NULL, fcon = NULL;
+ security_class_t sclass;
+
+ r = getcon(&mycon);
+ if (r < 0)
+ goto fail;
+
+ r = getfilecon(exe, &fcon);
+ if (r < 0)
+ goto fail;
+
+ sclass = string_to_security_class("process");
+ r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+ if (r == 0)
+ log_debug("SELinux Socket context for %s will be set to %s", exe, *label);
+
+fail:
+ if (r< 0 && security_getenforce() == 1)
+ r = -errno;
+
+ freecon(mycon);
+ freecon(fcon);
+#endif
+
+ return r;
+}
+
+int label_fifofile_set(const char *label, const char *path) {
+ int r = 0;
+
+#if HAVE_SELINUX
+ security_context_t filecon = NULL;
+ if (use_selinux() && label) {
+ if (((r = label_get_file_label_from_path(label, path, "fifo_file", &filecon)) == 0)) {
+ if ((r = setfscreatecon(filecon)) < 0) {
+ log_error("Failed to set SELinux file context (%s) on %s: %m", label, path);
+ r = -errno;
+ }
+
+ freecon(filecon);
+ }
+
+ if (r < 0 && security_getenforce() == 0)
+ r = 0;
+ }
+#endif
+
+ return r;
+}
+
+int label_socket_set(const char *label) {
+
+#if HAVE_SELINUX
+ if (use_selinux() && setsockcreatecon((security_context_t) label) < 0) {
+ log_error("Failed to set SELinux context (%s) on socket: %m", label);
+ if (security_getenforce() == 1)
+ return -errno;
+ }
+#endif
+
+ return 0;
+}
+
+void label_file_clear(void) {
+
+#if HAVE_SELINUX
+ if (use_selinux())
+ setfscreatecon(NULL);
+#endif
+
+ return;
+}
+
+void label_free(const char *label) {
+
+#if HAVE_SELINUX
+ if (use_selinux())
+ freecon((security_context_t) label);
+#endif
+
+ return;
+}
+
+void label_socket_clear(void) {
+
+#if HAVE_SELINUX
+ if (use_selinux())
+ setsockcreatecon(NULL);
+#endif
+
+ return;
+}
+
+static int label_mkdir(
+ const char *path,
+ mode_t mode) {
+
+#if HAVE_SELINUX
+ int r;
+ security_context_t fcon = NULL;
+
+ if (use_selinux()) {
+ if (path[0] == '/') {
+ r = selabel_lookup_raw(label_hnd, &fcon, path, mode);
+ }
+ else {
+ char *cwd = NULL;
+ char *newpath = NULL;
+ cwd = getcwd(NULL,0);
+ if ((! cwd) || (asprintf(&newpath, "%s/%s",cwd,path) < 0)) {
+ free(cwd);
+ return -errno;
+ }
+ r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode);
+ free(cwd);
+ free(newpath);
+ }
+
+ if (r == 0)
+ r = setfscreatecon(fcon);
+
+ if ((r < 0) && (errno != ENOENT)) {
+ log_error("Failed to set security context %s for %s", fcon, path);
+
+ if (security_getenforce() == 1)
+ goto finish;
+ }
+ }
+ r = mkdir(path, mode);
+
+finish:
+ if (use_selinux()) {
+ setfscreatecon(NULL);
+ freecon(fcon);
+ }
+
+ return r;
+#else
+ return mkdir(path, mode);
+#endif
+}
+
bool streq_ptr(const char *a, const char *b) {
/* Like streq(), but tries to make sense of NULL pointers */
@@ -969,7 +1207,7 @@ char *file_in_same_dir(const char *path, const char *filename) {
int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
struct stat st;
- if (mkdir(path, mode) >= 0)
+ if (label_mkdir(path, mode) >= 0)
if (chmod_and_chown(path, mode, uid, gid) < 0)
return -errno;
@@ -1012,7 +1250,7 @@ int mkdir_parents(const char *path, mode_t mode) {
if (!(t = strndup(path, e - path)))
return -ENOMEM;
- r = mkdir(t, mode);
+ r = label_mkdir(t, mode);
free(t);
if (r < 0 && errno != EEXIST)
@@ -1028,7 +1266,7 @@ int mkdir_p(const char *path, mode_t mode) {
if ((r = mkdir_parents(path, mode)) < 0)
return r;
- if (mkdir(path, mode) < 0 && errno != EEXIST)
+ if (label_mkdir(path, mode) < 0 && errno != EEXIST)
return -errno;
return 0;