summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-04-17 16:05:03 +0200
committerKay Sievers <kay@vrfy.org>2012-04-17 16:05:28 +0200
commite9a5ef7cddcfcdb29b5aef3896931132b6fd5165 (patch)
treeed40d27a53fcbee52aedad4531860aec6edb5c55
parent75e37ac5b125713c5ab6e1c4a9d62cfb62948c27 (diff)
selinux: unify systemd and udev code
-rw-r--r--Makefile.am9
-rw-r--r--src/core/main.c2
-rw-r--r--src/core/mount-setup.c5
-rw-r--r--src/core/socket.c7
-rw-r--r--src/libudev/libudev-private.h16
-rw-r--r--src/libudev/libudev-selinux-private.c84
-rw-r--r--src/shared/label.c47
-rw-r--r--src/shared/label.h7
-rw-r--r--src/test/test-udev.c4
-rw-r--r--src/tmpfiles/tmpfiles.c17
-rw-r--r--src/udev/udev-node.c13
-rw-r--r--src/udev/udev.h1
-rw-r--r--src/udev/udevadm.c4
-rw-r--r--src/udev/udevd.c12
14 files changed, 57 insertions, 171 deletions
diff --git a/Makefile.am b/Makefile.am
index 1371a7753..13c4ed169 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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 += \
diff --git a/src/core/main.c b/src/core/main.c
index 9bcedbe71..e3ea868da 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 52fe52367..30046a51b 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 a43971765..31aff5bce 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/libudev/libudev-private.h b/src/libudev/libudev-private.h
index 4bdbb0aa2..eb2657a74 100644
--- a/src/libudev/libudev-private.h
+++ b/src/libudev/libudev-private.h
@@ -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
index 03ca168b0..000000000
--- a/src/libudev/libudev-selinux-private.c
+++ /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");
-}
diff --git a/src/shared/label.c b/src/shared/label.c
index dce6f45c8..bd38f0ba6 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 ccf405bbe..3f880e363 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/test/test-udev.c b/src/test/test-udev.c
index a39ba7211..64bb5cbc3 100644
--- a/src/test/test-udev.c
+++ b/src/test/test-udev.c
@@ -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;
diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c
index 15913089b..5db827eca 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);
diff --git a/src/udev/udev-node.c b/src/udev/udev-node.c
index 20aa7c865..3c9846f15 100644
--- a/src/udev/udev-node.c
+++ b/src/udev/udev-node.c
@@ -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);
diff --git a/src/udev/udev.h b/src/udev/udev.h
index e229faaa4..aaaf63220 100644
--- a/src/udev/udev.h
+++ b/src/udev/udev.h
@@ -26,6 +26,7 @@
#include "libudev.h"
#include "libudev-private.h"
#include "util.h"
+#include "label.h"
struct udev_event {
struct udev *udev;
diff --git a/src/udev/udevadm.c b/src/udev/udevadm.c
index 2b4a845d7..5217d7f9d 100644
--- a/src/udev/udevadm.c
+++ b/src/udev/udevadm.c
@@ -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;
diff --git a/src/udev/udevd.c b/src/udev/udevd.c
index 20de5cfc2..16751144b 100644
--- a/src/udev/udevd.c
+++ b/src/udev/udevd.c
@@ -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;