chiark / gitweb /
selinux: unify systemd and udev code
authorKay Sievers <kay@vrfy.org>
Tue, 17 Apr 2012 14:05:03 +0000 (16:05 +0200)
committerKay Sievers <kay@vrfy.org>
Tue, 17 Apr 2012 14:05:28 +0000 (16:05 +0200)
14 files changed:
Makefile.am
src/core/main.c
src/core/mount-setup.c
src/core/socket.c
src/libudev/libudev-private.h
src/libudev/libudev-selinux-private.c [deleted file]
src/shared/label.c
src/shared/label.h
src/test/test-udev.c
src/tmpfiles/tmpfiles.c
src/udev/udev-node.c
src/udev/udev.h
src/udev/udevadm.c
src/udev/udevd.c

index 1371a77..13c4ed1 100644 (file)
@@ -1340,19 +1340,12 @@ libudev_private_la_SOURCES =\
        src/libudev/libudev-device-private.c \
        src/libudev/libudev-queue-private.c
 
-if HAVE_SELINUX
-libudev_private_la_SOURCES +=\
-       src/libudev/libudev-selinux-private.c
-endif
-
 libudev_private_la_CFLAGS = \
        $(AM_CFLAGS) \
-       $(SELINUX_CFLAGS)
        -fvisibility=default
 
 libudev_private_la_LIBADD = \
-       libsystemd-shared.la \
-       $(SELINUX_LIBS)
+       libsystemd-shared.la
 
 # ------------------------------------------------------------------------------
 MANPAGES += \
index 9bcedbe..e3ea868 100644 (file)
@@ -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)
index 52fe523..30046a5 100644 (file)
@@ -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;
 }
index a439717..31aff5b 100644 (file)
@@ -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);
index 4bdbb0a..eb2657a 100644 (file)
@@ -173,20 +173,4 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
                                       char *result, size_t maxsize, int read_value);
 unsigned long long ts_usec(const struct timespec *ts);
 unsigned long long now_usec(void);
-
-/* libudev-selinux-private.c */
-#ifndef HAVE_SELINUX
-static inline void udev_selinux_init(struct udev *udev) {}
-static inline void udev_selinux_exit(struct udev *udev) {}
-static inline void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode) {}
-static inline void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode) {}
-static inline void udev_selinux_resetfscreatecon(struct udev *udev) {}
-#else
-void udev_selinux_init(struct udev *udev);
-void udev_selinux_exit(struct udev *udev);
-void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode);
-void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode);
-void udev_selinux_resetfscreatecon(struct udev *udev);
-#endif
-
 #endif
diff --git a/src/libudev/libudev-selinux-private.c b/src/libudev/libudev-selinux-private.c
deleted file mode 100644 (file)
index 03ca168..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * libudev - interface to udev device information
- *
- * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <selinux/selinux.h>
-
-#include "libudev.h"
-#include "libudev-private.h"
-
-static int selinux_enabled;
-security_context_t selinux_prev_scontext;
-
-void udev_selinux_init(struct udev *udev)
-{
-        /* record the present security context */
-        selinux_enabled = (is_selinux_enabled() > 0);
-        dbg(udev, "selinux=%i\n", selinux_enabled);
-        if (!selinux_enabled)
-                return;
-        matchpathcon_init_prefix(NULL, TEST_PREFIX "/dev");
-        if (getfscreatecon(&selinux_prev_scontext) < 0) {
-                err(udev, "getfscreatecon failed\n");
-                selinux_prev_scontext = NULL;
-        }
-}
-
-void udev_selinux_exit(struct udev *udev)
-{
-        if (!selinux_enabled)
-                return;
-        freecon(selinux_prev_scontext);
-        selinux_prev_scontext = NULL;
-}
-
-void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode)
-{
-        security_context_t scontext = NULL;
-
-        if (!selinux_enabled)
-                return;
-        if (matchpathcon(file, mode, &scontext) < 0) {
-                err(udev, "matchpathcon(%s) failed\n", file);
-                return;
-        }
-        if (lsetfilecon(file, scontext) < 0)
-                err(udev, "setfilecon %s failed: %m\n", file);
-        freecon(scontext);
-}
-
-void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode)
-{
-        security_context_t scontext = NULL;
-
-        if (!selinux_enabled)
-                return;
-
-        if (matchpathcon(file, mode, &scontext) < 0) {
-                err(udev, "matchpathcon(%s) failed\n", file);
-                return;
-        }
-        if (setfscreatecon(scontext) < 0)
-                err(udev, "setfscreatecon %s failed: %m\n", file);
-        freecon(scontext);
-}
-
-void udev_selinux_resetfscreatecon(struct udev *udev)
-{
-        if (!selinux_enabled)
-                return;
-        if (setfscreatecon(selinux_prev_scontext) < 0)
-                err(udev, "setfscreatecon failed: %m\n");
-}
index dce6f45..bd38f0b 100644 (file)
@@ -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())
index ccf405b..3f880e3 100644 (file)
@@ -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);
 
index a39ba72..64bb5cb 100644 (file)
@@ -50,7 +50,7 @@ int main(int argc, char *argv[])
         if (udev == NULL)
                 exit(EXIT_FAILURE);
         log_debug("version %s\n", VERSION);
-        udev_selinux_init(udev);
+        label_init("/dev");
 
         sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
 
@@ -113,7 +113,7 @@ out:
         udev_event_unref(event);
         udev_device_unref(dev);
         udev_rules_unref(rules);
-        udev_selinux_exit(udev);
+        label_finish();
         udev_unref(udev);
         if (err != 0)
                 return EXIT_FAILURE;
index 1591308..5db827e 100644 (file)
@@ -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);
index 20aa7c8..3c9846f 100644 (file)
@@ -91,7 +91,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
                                 buf[len] = '\0';
                                 if (strcmp(target, buf) == 0) {
                                         log_debug("preserve already existing symlink '%s' to '%s'\n", slink, target);
-                                        udev_selinux_lsetfilecon(udev, slink, S_IFLNK);
+                                        label_fix(slink, true);
                                         utimensat(AT_FDCWD, slink, NULL, AT_SYMLINK_NOFOLLOW);
                                         goto exit;
                                 }
@@ -103,11 +103,11 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
                         err = mkdir_parents(slink, 0755);
                         if (err != 0 && err != -ENOENT)
                                 break;
-                        udev_selinux_setfscreatecon(udev, slink, S_IFLNK);
+                        label_context_set(slink, S_IFLNK);
                         err = symlink(target, slink);
                         if (err != 0)
                                 err = -errno;
-                        udev_selinux_resetfscreatecon(udev);
+                        label_context_clear();
                 } while (err == -ENOENT);
                 if (err == 0)
                         goto exit;
@@ -120,11 +120,11 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink)
                 err = mkdir_parents(slink_tmp, 0755);
                 if (err != 0 && err != -ENOENT)
                         break;
-                udev_selinux_setfscreatecon(udev, slink_tmp, S_IFLNK);
+                label_context_set(slink_tmp, S_IFLNK);
                 err = symlink(target, slink_tmp);
                 if (err != 0)
                         err = -errno;
-                udev_selinux_resetfscreatecon(udev);
+                label_context_clear();
         } while (err == -ENOENT);
         if (err != 0) {
                 log_error("symlink '%s' '%s' failed: %m\n", target, slink_tmp);
@@ -269,7 +269,6 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
 
 static int node_fixup(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid)
 {
-        struct udev *udev = udev_device_get_udev(dev);
         const char *devnode = udev_device_get_devnode(dev);
         dev_t devnum = udev_device_get_devnum(dev);
         struct stat stats;
@@ -308,7 +307,7 @@ static int node_fixup(struct udev_device *dev, mode_t mode, uid_t uid, gid_t gid
          * something else has set a custom context in the meantime.
          */
         if (strcmp(udev_device_get_action(dev), "add") == 0)
-                udev_selinux_lsetfilecon(udev, devnode, mode);
+                label_fix(devnode, true);
 
         /* always update timestamp when we re-use the node, like on media change events */
         utimensat(AT_FDCWD, devnode, NULL, 0);
index e229faa..aaaf632 100644 (file)
@@ -26,6 +26,7 @@
 #include "libudev.h"
 #include "libudev-private.h"
 #include "util.h"
+#include "label.h"
 
 struct udev_event {
         struct udev *udev;
index 2b4a845..5217d7f 100644 (file)
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
         log_open();
         log_parse_environment();
         udev_set_log_fn(udev, udev_main_log);
-        udev_selinux_init(udev);
+        label_init("/dev");
 
         for (;;) {
                 int option;
@@ -143,7 +143,7 @@ int main(int argc, char *argv[])
         adm_help(udev, argc, argv);
         rc = 2;
 out:
-        udev_selinux_exit(udev);
+        label_finish();
         udev_unref(udev);
         log_close();
         return rc;
index 20de5cf..1675114 100644 (file)
@@ -858,11 +858,11 @@ static void static_dev_create_from_modules(struct udev *udev)
 
                 util_strscpyl(filename, sizeof(filename), "/dev/", devname, NULL);
                 mkdir_parents(filename, 0755);
-                udev_selinux_setfscreatecon(udev, filename, mode);
+                label_context_set(filename, mode);
                 log_debug("mknod '%s' %c%u:%u\n", filename, type, maj, min);
                 if (mknod(filename, mode, makedev(maj, min)) < 0 && errno == EEXIST)
                         utimensat(AT_FDCWD, filename, NULL, 0);
-                udev_selinux_resetfscreatecon(udev);
+                label_context_clear();
         }
 
         fclose(f);
@@ -888,10 +888,10 @@ static void static_dev_create_links(struct udev *udev)
                 struct stat sb;
 
                 if (stat(stdlinks[i].target, &sb) == 0) {
-                        udev_selinux_setfscreatecon(udev, stdlinks[i].link, S_IFLNK);
+                        label_context_set(stdlinks[i].link, S_IFLNK);
                         if (symlink(stdlinks[i].target, stdlinks[i].link) < 0 && errno == EEXIST)
                                 utimensat(AT_FDCWD, stdlinks[i].link, NULL, AT_SYMLINK_NOFOLLOW);
-                        udev_selinux_resetfscreatecon(udev);
+                        label_context_clear();
                 }
         }
 }
@@ -1077,7 +1077,7 @@ int main(int argc, char *argv[])
         log_parse_environment();
         udev_set_log_fn(udev, udev_main_log);
         log_debug("version %s\n", VERSION);
-        udev_selinux_init(udev);
+        label_init("/dev");
 
         for (;;) {
                 int option;
@@ -1607,7 +1607,7 @@ exit_daemonize:
         udev_queue_export_unref(udev_queue_export);
         udev_ctrl_connection_unref(ctrl_conn);
         udev_ctrl_unref(udev_ctrl);
-        udev_selinux_exit(udev);
+        label_finish();
         udev_unref(udev);
         log_close();
         return rc;