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 += \
log_open();
- if (label_init() < 0)
+ if (label_init(NULL) < 0)
goto finish;
if (!is_reexec)
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;
}
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 */
goto fail;
}
- label_file_clear();
+ label_context_clear();
if (fstat(fd, &st) < 0) {
r = -errno;
return 0;
fail:
- label_file_clear();
+ label_context_clear();
if (fd >= 0)
close_nointr_nofail(fd);
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
+++ /dev/null
-/*
- * 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");
-}
#endif
-int label_init(void) {
+int label_init(const char *prefix) {
int r = 0;
#ifdef HAVE_SELINUX
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");
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
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) {
return 0;
}
-void label_file_clear(void) {
+void label_context_clear(void) {
#ifdef HAVE_SELINUX
if (!use_selinux())
#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);
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);
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);
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;
}
static int create_item(Item *i) {
- int r;
+ int r, e;
mode_t u;
struct stat st;
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)
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;
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);
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);
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;
}
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;
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);
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;
* 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);
#include "libudev.h"
#include "libudev-private.h"
#include "util.h"
+#include "label.h"
struct udev_event {
struct udev *udev;
log_open();
log_parse_environment();
udev_set_log_fn(udev, udev_main_log);
- udev_selinux_init(udev);
+ label_init("/dev");
for (;;) {
int option;
adm_help(udev, argc, argv);
rc = 2;
out:
- udev_selinux_exit(udev);
+ label_finish();
udev_unref(udev);
log_close();
return rc;
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);
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();
}
}
}
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;
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;