selinux: unify systemd and udev code
This commit is contained in:
parent
75e37ac5b1
commit
e9a5ef7cdd
|
@ -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 += \
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -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,7 +185,7 @@ fail:
|
|||
return r;
|
||||
}
|
||||
|
||||
int label_fifofile_set(const char *path) {
|
||||
int label_context_set(const char *path, mode_t mode) {
|
||||
int r = 0;
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
|
@ -186,36 +194,7 @@ int label_fifofile_set(const char *path) {
|
|||
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 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_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())
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "libudev.h"
|
||||
#include "libudev-private.h"
|
||||
#include "util.h"
|
||||
#include "label.h"
|
||||
|
||||
struct udev_event {
|
||||
struct udev *udev;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue