Blob Blame History Raw
From 82b9638be653c3f0a3710e67436a0c167469e0c7 Mon Sep 17 00:00:00 2001
From: Kay Sievers <kay@vrfy.org>
Date: Tue, 17 Apr 2012 16:05:03 +0200
Subject: [PATCH] selinux: unify systemd and udev code (cherry picked from
 commit e9a5ef7cddcfcdb29b5aef3896931132b6fd5165)

Conflicts:

	Makefile.am
	src/libudev/libudev-private.h
	src/test/test-udev.c
	src/udev/udev-node.c
	src/udev/udev.h
	src/udev/udevadm.c
	src/udev/udevd.c
---
 src/core/main.c         |    2 +-
 src/core/mount-setup.c  |    5 +++--
 src/core/socket.c       |    7 ++++---
 src/shared/label.c      |   47 +++++++++++++----------------------------------
 src/shared/label.h      |    7 +++----
 src/tmpfiles/tmpfiles.c |   17 +++++++++++++++--
 6 files changed, 39 insertions(+), 46 deletions(-)

diff --git a/src/core/main.c b/src/core/main.c
index 80ef8b1..e6b3353 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1222,7 +1222,7 @@ int main(int argc, char *argv[]) {
 
                 log_open();
 
-                if (label_init() < 0)
+                if (label_init(NULL) < 0)
                         goto finish;
 
                 if (!is_reexec)
diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c
index dd7938e..eeec251 100644
--- a/src/core/mount-setup.c
+++ b/src/core/mount-setup.c
@@ -329,13 +329,14 @@ static int symlink_and_label(const char *old_path, const char *new_path) {
         assert(old_path);
         assert(new_path);
 
-        if ((r = label_symlinkfile_set(new_path)) < 0)
+        r = label_context_set(new_path, S_IFLNK);
+        if (r < 0)
                 return r;
 
         if (symlink(old_path, new_path) < 0)
                 r = -errno;
 
-        label_file_clear();
+        label_context_clear();
 
         return r;
 }
diff --git a/src/core/socket.c b/src/core/socket.c
index 87d6d86..d03b35c 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -762,7 +762,8 @@ static int fifo_address_create(
 
         mkdir_parents(path, directory_mode);
 
-        if ((r = label_fifofile_set(path)) < 0)
+        r = label_context_set(path, S_IFIFO);
+        if (r < 0)
                 goto fail;
 
         /* Enforce the right access mode for the fifo */
@@ -784,7 +785,7 @@ static int fifo_address_create(
                 goto fail;
         }
 
-        label_file_clear();
+        label_context_clear();
 
         if (fstat(fd, &st) < 0) {
                 r = -errno;
@@ -804,7 +805,7 @@ static int fifo_address_create(
         return 0;
 
 fail:
-        label_file_clear();
+        label_context_clear();
 
         if (fd >= 0)
                 close_nointr_nofail(fd);
diff --git a/src/shared/label.c b/src/shared/label.c
index 2c887a0..433b768 100644
--- a/src/shared/label.c
+++ b/src/shared/label.c
@@ -51,7 +51,7 @@ void label_retest_selinux(void) {
 
 #endif
 
-int label_init(void) {
+int label_init(const char *prefix) {
         int r = 0;
 
 #ifdef HAVE_SELINUX
@@ -67,7 +67,15 @@ int label_init(void) {
         before_mallinfo = mallinfo();
         before_timestamp = now(CLOCK_MONOTONIC);
 
-        label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+        if (prefix) {
+                struct selinux_opt options[] = {
+                        { .type = SELABEL_OPT_SUBSET, .value = prefix },
+                };
+
+                label_hnd = selabel_open(SELABEL_CTX_FILE, options, ELEMENTSOF(options));
+        } else
+                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");
@@ -177,36 +185,7 @@ fail:
         return r;
 }
 
-int label_fifofile_set(const char *path) {
-        int r = 0;
-
-#ifdef HAVE_SELINUX
-        security_context_t filecon = NULL;
-
-        if (!use_selinux() || !label_hnd)
-                return 0;
-
-        r = selabel_lookup_raw(label_hnd, &filecon, path, S_IFIFO);
-        if (r < 0)
-                r = -errno;
-        else if (r == 0) {
-                r = setfscreatecon(filecon);
-                if (r < 0) {
-                        log_error("Failed to set SELinux file context on %s: %m", path);
-                        r = -errno;
-                }
-
-                freecon(filecon);
-        }
-
-        if (r < 0 && security_getenforce() == 0)
-                r = 0;
-#endif
-
-        return r;
-}
-
-int label_symlinkfile_set(const char *path) {
+int label_context_set(const char *path, mode_t mode) {
         int r = 0;
 
 #ifdef HAVE_SELINUX
@@ -215,7 +194,7 @@ int label_symlinkfile_set(const char *path) {
         if (!use_selinux() || !label_hnd)
                 return 0;
 
-        r = selabel_lookup_raw(label_hnd, &filecon, path, S_IFLNK);
+        r = selabel_lookup_raw(label_hnd, &filecon, path, mode);
         if (r < 0)
                 r = -errno;
         else if (r == 0) {
@@ -253,7 +232,7 @@ int label_socket_set(const char *label) {
         return 0;
 }
 
-void label_file_clear(void) {
+void label_context_clear(void) {
 
 #ifdef HAVE_SELINUX
         if (!use_selinux())
diff --git a/src/shared/label.h b/src/shared/label.h
index ead4483..6166bc3 100644
--- a/src/shared/label.h
+++ b/src/shared/label.h
@@ -26,7 +26,7 @@
 #include <stdbool.h>
 #include <sys/socket.h>
 
-int label_init(void);
+int label_init(const char *prefix);
 void label_finish(void);
 
 int label_fix(const char *path, bool ignore_enoent);
@@ -34,9 +34,8 @@ int label_fix(const char *path, bool ignore_enoent);
 int label_socket_set(const char *label);
 void label_socket_clear(void);
 
-int label_fifofile_set(const char *path);
-int label_symlinkfile_set(const char *path);
-void label_file_clear(void);
+int label_context_set(const char *path, mode_t mode);
+void label_context_clear(void);
 
 void label_free(const char *label);
 
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index c5f6fc0..d3ea592 100644
--- a/src/tmpfiles/tmpfiles.c
+++ b/src/tmpfiles/tmpfiles.c
@@ -562,7 +562,7 @@ static int glob_item(Item *i, int (*action)(Item *, const char *)) {
 }
 
 static int create_item(Item *i) {
-        int r;
+        int r, e;
         mode_t u;
         struct stat st;
 
@@ -584,8 +584,12 @@ static int create_item(Item *i) {
                         i->type == TRUNCATE_FILE ? O_CREAT|O_TRUNC : 0;
 
                 u = umask(0);
+                label_context_set(i->path, S_IFREG);
                 fd = open(i->path, flags|O_NDELAY|O_CLOEXEC|O_WRONLY|O_NOCTTY|O_NOFOLLOW, i->mode);
+                e = errno;
+                label_context_clear();
                 umask(u);
+                errno = e;
 
                 if (fd < 0) {
                         if (i->type == WRITE_FILE && errno == ENOENT)
@@ -696,7 +700,12 @@ static int create_item(Item *i) {
         case CREATE_SYMLINK: {
                 char *x;
 
+                label_context_set(i->path, S_IFLNK);
                 r = symlink(i->argument, i->path);
+                e = errno;
+                label_context_clear();
+                errno = e;
+
                 if (r < 0 && errno != EEXIST) {
                         log_error("symlink(%s, %s) failed: %m", i->argument, i->path);
                         return -errno;
@@ -722,8 +731,12 @@ static int create_item(Item *i) {
         case CREATE_CHAR_DEVICE: {
 
                 u = umask(0);
+                label_context_set(i->path, CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR);
                 r = mknod(i->path, i->mode | (i->type == CREATE_BLOCK_DEVICE ? S_IFBLK : S_IFCHR), i->major_minor);
+                e = errno;
+                label_context_clear();
                 umask(u);
+                errno = e;
 
                 if (r < 0 && errno != EEXIST) {
                         log_error("Failed to create device node %s: %m", i->path);
@@ -1248,7 +1261,7 @@ int main(int argc, char *argv[]) {
 
         umask(0022);
 
-        label_init();
+        label_init(NULL);
 
         items = hashmap_new(string_hash_func, string_compare_func);
         globs = hashmap_new(string_hash_func, string_compare_func);