From 4f4b12c20388ff2cb158b040e3193f86cf7a3b96 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 10 Sep 2008 00:46:17 +0200 Subject: libudev: add selinux --- udev/Makefile.am | 5 -- udev/lib/Makefile.am | 5 -- udev/lib/libudev.c | 83 ++++++++++++++++++++++- udev/lib/libudev.h | 3 + udev/test-udev.c | 3 - udev/udev.h | 2 +- udev/udev_db.c | 6 +- udev/udev_node.c | 21 +++--- udev/udev_rules.c | 1 - udev/udev_rules_parse.c | 5 +- udev/udev_selinux.c | 175 ------------------------------------------------ udev/udev_selinux.h | 35 ---------- udev/udev_utils_file.c | 5 +- udev/udevd.c | 8 +-- 14 files changed, 103 insertions(+), 254 deletions(-) delete mode 100644 udev/udev_selinux.c delete mode 100644 udev/udev_selinux.h (limited to 'udev') diff --git a/udev/Makefile.am b/udev/Makefile.am index de39249af1..7984e5d5f9 100644 --- a/udev/Makefile.am +++ b/udev/Makefile.am @@ -20,7 +20,6 @@ common_files = \ logging.h \ udev.h \ udev_rules.h \ - udev_selinux.h \ udev_sysdeps.h \ udev_db.c \ udev_device.c \ @@ -41,11 +40,7 @@ common_files = \ lib/libudev-utils.c \ lib/libudev-ctrl.c - if USE_SELINUX -common_files += \ - udev_selinux.c - common_ldadd += \ $(SELINUX_LIBS) endif diff --git a/udev/lib/Makefile.am b/udev/lib/Makefile.am index 630888d3d9..95dd46e92f 100644 --- a/udev/lib/Makefile.am +++ b/udev/lib/Makefile.am @@ -38,11 +38,6 @@ libudev_la_SOURCES =\ ../udev_db.c \ ../udev_sysdeps.c -if USE_SELINUX -libudev_la_SOURCES += \ - ../udev_selinux.c -endif - libudev_la_LDFLAGS = \ -version-info $(LIBUDEV_LT_CURRENT):$(LIBUDEV_LT_REVISION):$(LIBUDEV_LT_AGE) \ -export-symbols $(top_srcdir)/udev/lib/exported_symbols diff --git a/udev/lib/libudev.c b/udev/lib/libudev.c index 09e1bec1bf..4e258bd2ce 100644 --- a/udev/lib/libudev.c +++ b/udev/lib/libudev.c @@ -27,6 +27,9 @@ #include #include #include +#ifdef USE_SELINUX +#include +#endif #include "libudev.h" #include "libudev-private.h" @@ -41,6 +44,10 @@ struct udev { char *dev_path; char *rules_path; int log_priority; +#ifdef USE_SELINUX + int selinux_enabled; + security_context_t selinux_prev_scontext; +#endif int run:1; }; @@ -66,6 +73,78 @@ static void log_stderr(struct udev *udev, vfprintf(stderr, format, args); } +static void selinux_init(struct udev *udev) +{ +#ifdef USE_SELINUX + /* + * record the present security context, for file-creation + * restoration creation purposes. + */ + udev->selinux_enabled = (is_selinux_enabled() > 0); + if (udev->selinux_enabled) { + matchpathcon_init_prefix(NULL, udev_get_dev_path(udev)); + if (getfscreatecon(&udev->selinux_prev_scontext) < 0) { + err(udev, "getfscreatecon failed\n"); + udev->selinux_prev_scontext = NULL; + } + } +#endif +} + +static void selinux_exit(struct udev *udev) +{ +#ifdef USE_SELINUX + if (udev->selinux_enabled) { + freecon(udev->selinux_prev_scontext); + udev->selinux_prev_scontext = NULL; + } +#endif +} + +void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode) +{ +#ifdef USE_SELINUX + if (udev->selinux_enabled) { + security_context_t scontext = NULL; + + if (matchpathcon(file, mode, &scontext) < 0) { + err(udev, "matchpathcon(%s) failed\n", file); + return; + } + if (lsetfilecon(file, scontext) < 0) + err(udev, "setfilecon %s failed: %s\n", file, strerror(errno)); + freecon(scontext); + } +#endif +} + +void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode) +{ +#ifdef USE_SELINUX + if (udev->selinux_enabled) { + security_context_t scontext = NULL; + + if (matchpathcon(file, mode, &scontext) < 0) { + err(udev, "matchpathcon(%s) failed\n", file); + return; + } + if (setfscreatecon(scontext) < 0) + err(udev, "setfscreatecon %s failed: %s\n", file, strerror(errno)); + freecon(scontext); + } +#endif +} + +void udev_selinux_resetfscreatecon(struct udev *udev) +{ +#ifdef USE_SELINUX + if (udev->selinux_enabled) { + if (setfscreatecon(udev->selinux_prev_scontext) < 0) + err(udev, "setfscreatecon failed: %s\n", strerror(errno)); + } +#endif +} + /** * udev_new: * @@ -88,9 +167,8 @@ struct udev *udev_new(void) return NULL; memset(udev, 0x00, (sizeof(struct udev))); + selinux_init(udev); sysfs_init(); - - /* defaults */ udev->refcount = 1; udev->log_fn = log_stderr; udev->log_priority = LOG_ERR; @@ -270,6 +348,7 @@ void udev_unref(struct udev *udev) if (udev->refcount > 0) return; sysfs_cleanup(); + selinux_exit(udev); free(udev->dev_path); free(udev->sys_path); free(udev->rules_path); diff --git a/udev/lib/libudev.h b/udev/lib/libudev.h index 2fd990f92e..e1eed568f9 100644 --- a/udev/lib/libudev.h +++ b/udev/lib/libudev.h @@ -40,6 +40,9 @@ extern int udev_get_log_priority(struct udev *udev); extern void udev_set_log_priority(struct udev *udev, int priority); extern const char *udev_get_sys_path(struct udev *udev); extern const char *udev_get_dev_path(struct udev *udev); +extern void udev_selinux_resetfscreatecon(struct udev *udev); +extern void udev_selinux_setfscreatecon(struct udev *udev, const char *file, unsigned int mode); +extern void udev_selinux_lsetfilecon(struct udev *udev, const char *file, unsigned int mode); struct udev_device; extern struct udev_device *udev_device_new_from_devpath(struct udev *udev, const char *devpath); diff --git a/udev/test-udev.c b/udev/test-udev.c index 6c01bdbcd4..58bc28e02a 100644 --- a/udev/test-udev.c +++ b/udev/test-udev.c @@ -33,7 +33,6 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" static void asmlinkage sig_handler(int signum) { @@ -63,7 +62,6 @@ int main(int argc, char *argv[]) if (udev == NULL) exit(1); dbg(udev, "version %s\n", VERSION); - selinux_init(udev); /* set signal handlers */ memset(&act, 0x00, sizeof(act)); @@ -135,7 +133,6 @@ int main(int argc, char *argv[]) fail: udev_rules_cleanup(&rules); sysfs_cleanup(); - selinux_exit(udev); exit: udev_unref(udev); if (retval != 0) diff --git a/udev/udev.h b/udev/udev.h index 122e83d876..700c8c09d8 100644 --- a/udev/udev.h +++ b/udev/udev.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2003 Greg Kroah-Hartman - * Copyright (C) 2003-2006 Kay Sievers + * Copyright (C) 2003-2008 Kay Sievers * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/udev/udev_db.c b/udev/udev_db.c index e89f2c2a15..18e111ba4b 100644 --- a/udev/udev_db.c +++ b/udev/udev_db.c @@ -31,8 +31,6 @@ #include #include "udev.h" -#include "udev_selinux.h" - static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len) { @@ -147,9 +145,9 @@ int udev_db_add_device(struct udevice *udevice) !udevice->partitions && !udevice->ignore_remove) { int ret; dbg(udevice->udev, "nothing interesting to store, create symlink\n"); - selinux_setfscreatecon(udevice->udev, filename, NULL, S_IFLNK); + udev_selinux_setfscreatecon(udevice->udev, filename, S_IFLNK); ret = symlink(udevice->name, filename); - selinux_resetfscreatecon(udevice->udev); + udev_selinux_resetfscreatecon(udevice->udev); if (ret != 0) { err(udevice->udev, "unable to create db link '%s': %s\n", filename, strerror(errno)); return -1; diff --git a/udev/udev_node.c b/udev/udev_node.c index 462f1b633b..079bb4e3b1 100644 --- a/udev/udev_node.c +++ b/udev/udev_node.c @@ -31,7 +31,6 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" #define TMP_FILE_EXT ".udev-tmp" @@ -51,15 +50,15 @@ int udev_node_mknod(struct udevice *udevice, const char *file, dev_t devt, mode_ if (((stats.st_mode & S_IFMT) == (mode & S_IFMT)) && (stats.st_rdev == devt)) { info(udevice->udev, "preserve file '%s', because it has correct dev_t\n", file); preserve = 1; - selinux_setfilecon(udevice->udev, file, udevice->dev->kernel, mode); + udev_selinux_lsetfilecon(udevice->udev, file, mode); } else { info(udevice->udev, "atomically replace existing file '%s'\n", file); strlcpy(file_tmp, file, sizeof(file_tmp)); strlcat(file_tmp, TMP_FILE_EXT, sizeof(file_tmp)); unlink(file_tmp); - selinux_setfscreatecon(udevice->udev, file_tmp, udevice->dev->kernel, mode); + udev_selinux_setfscreatecon(udevice->udev, file_tmp, mode); err = mknod(file_tmp, mode, devt); - selinux_resetfscreatecon(udevice->udev); + udev_selinux_resetfscreatecon(udevice->udev); if (err != 0) { err(udevice->udev, "mknod(%s, %#o, %u, %u) failed: %s\n", file_tmp, mode, major(devt), minor(devt), strerror(errno)); @@ -73,9 +72,9 @@ int udev_node_mknod(struct udevice *udevice, const char *file, dev_t devt, mode_ } } else { info(udevice->udev, "mknod(%s, %#o, (%u,%u))\n", file, mode, major(devt), minor(devt)); - selinux_setfscreatecon(udevice->udev, file, udevice->dev->kernel, mode); + udev_selinux_setfscreatecon(udevice->udev, file, mode); err = mknod(file, mode, devt); - selinux_resetfscreatecon(udevice->udev); + udev_selinux_resetfscreatecon(udevice->udev); if (err != 0) { err(udevice->udev, "mknod(%s, %#o, (%u,%u) failed: %s\n", file, mode, major(devt), minor(devt), strerror(errno)); @@ -151,16 +150,16 @@ static int node_symlink(struct udevice *udevice, const char *node, const char *s buf[len] = '\0'; if (strcmp(target, buf) == 0) { info(udevice->udev, "preserve already existing symlink '%s' to '%s'\n", slink, target); - selinux_setfilecon(udevice->udev, slink, NULL, S_IFLNK); + udev_selinux_lsetfilecon(udevice->udev, slink, S_IFLNK); goto exit; } } } } else { info(udevice->udev, "creating symlink '%s' to '%s'\n", slink, target); - selinux_setfscreatecon(udevice->udev, slink, NULL, S_IFLNK); + udev_selinux_setfscreatecon(udevice->udev, slink, S_IFLNK); retval = symlink(target, slink); - selinux_resetfscreatecon(udevice->udev); + udev_selinux_resetfscreatecon(udevice->udev); if (retval == 0) goto exit; } @@ -169,9 +168,9 @@ static int node_symlink(struct udevice *udevice, const char *node, const char *s strlcpy(slink_tmp, slink, sizeof(slink_tmp)); strlcat(slink_tmp, TMP_FILE_EXT, sizeof(slink_tmp)); unlink(slink_tmp); - selinux_setfscreatecon(udevice->udev, slink, NULL, S_IFLNK); + udev_selinux_setfscreatecon(udevice->udev, slink, S_IFLNK); retval = symlink(target, slink_tmp); - selinux_resetfscreatecon(udevice->udev); + udev_selinux_resetfscreatecon(udevice->udev); if (retval != 0) { err(udevice->udev, "symlink(%s, %s) failed: %s\n", target, slink_tmp, strerror(errno)); goto exit; diff --git a/udev/udev_rules.c b/udev/udev_rules.c index 3b9631b883..6e4a6942f8 100644 --- a/udev/udev_rules.c +++ b/udev/udev_rules.c @@ -35,7 +35,6 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" extern char **environ; diff --git a/udev/udev_rules_parse.c b/udev/udev_rules_parse.c index 81f0edb6f5..9513ac9cf3 100644 --- a/udev/udev_rules_parse.c +++ b/udev/udev_rules_parse.c @@ -30,7 +30,6 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" void udev_rules_iter_init(struct udev_rules_iter *iter, struct udev_rules *rules) @@ -756,9 +755,9 @@ int udev_rules_init(struct udev *udev, struct udev_rules *rules, int resolve_nam strlcat(filename, "/.udev/rules.d", sizeof(filename)); if (stat(filename, &statbuf) != 0) { create_path(udev, filename); - selinux_setfscreatecon(udev, filename, NULL, S_IFDIR|0755); + udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755); mkdir(filename, 0755); - selinux_resetfscreatecon(udev); + udev_selinux_resetfscreatecon(udev); } add_matching_files(udev, &sort_list, filename, ".rules"); diff --git a/udev/udev_selinux.c b/udev/udev_selinux.c deleted file mode 100644 index 2e76a7431f..0000000000 --- a/udev/udev_selinux.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2004 Daniel Walsh - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "udev.h" -#include "udev_selinux.h" - -static security_context_t prev_scontext = NULL; - -static int is_selinux_running(struct udev *udev) -{ - static int selinux_enabled = -1; - - if (selinux_enabled == -1) - selinux_enabled = (is_selinux_enabled() > 0); - - dbg(udev, "selinux=%i\n", selinux_enabled); - return selinux_enabled; -} - -static char *get_media(struct udev *udev, const char *devname, int mode) -{ - FILE *fp; - char procfile[PATH_MAX]; - char mediabuf[256]; - int size; - char *media = NULL; - - if (!(mode & S_IFBLK)) - return NULL; - - snprintf(procfile, PATH_MAX, "/proc/ide/%s/media", devname); - procfile[PATH_MAX-1] = '\0'; - - fp = fopen(procfile, "r"); - if (!fp) - goto out; - - if (fgets(mediabuf, sizeof(mediabuf), fp) == NULL) - goto close_out; - - size = strlen(mediabuf); - while (size-- > 0) { - if (isspace(mediabuf[size])) { - mediabuf[size] = '\0'; - } else { - break; - } - } - - media = strdup(mediabuf); - info(udev, "selinux_get_media(%s)='%s'\n", devname, media); - -close_out: - fclose(fp); -out: - return media; -} - -void selinux_setfilecon(struct udev *udev, const char *file, const char *devname, unsigned int mode) -{ - if (is_selinux_running(udev)) { - security_context_t scontext = NULL; - char *media; - int ret = -1; - - if (devname) { - media = get_media(udev, devname, mode); - if (media) { - ret = matchmediacon(media, &scontext); - free(media); - } - } - - if (ret < 0) - if (matchpathcon(file, mode, &scontext) < 0) { - err(udev, "matchpathcon(%s) failed\n", file); - return; - } - - if (lsetfilecon(file, scontext) < 0) - err(udev, "setfilecon %s failed: %s\n", file, strerror(errno)); - - freecon(scontext); - } -} - -void selinux_setfscreatecon(struct udev *udev, const char *file, const char *devname, unsigned int mode) -{ - if (is_selinux_running(udev)) { - security_context_t scontext = NULL; - char *media; - int ret = -1; - - if (devname) { - media = get_media(udev, devname, mode); - if (media) { - ret = matchmediacon(media, &scontext); - free(media); - } - } - - if (ret < 0) - if (matchpathcon(file, mode, &scontext) < 0) { - err(udev, "matchpathcon(%s) failed\n", file); - return; - } - - if (setfscreatecon(scontext) < 0) - err(udev, "setfscreatecon %s failed: %s\n", file, strerror(errno)); - - freecon(scontext); - } -} - -void selinux_resetfscreatecon(struct udev *udev) -{ - if (is_selinux_running(udev)) { - if (setfscreatecon(prev_scontext) < 0) - err(udev, "setfscreatecon failed: %s\n", strerror(errno)); - } -} - -void selinux_init(struct udev *udev) -{ - /* - * record the present security context, for file-creation - * restoration creation purposes. - */ - if (is_selinux_running(udev)) { - if (!udev_get_dev_path(udev)[0]) - err(udev, "selinux_init: udev_root not set\n"); - matchpathcon_init_prefix(NULL, udev_get_dev_path(udev)); - if (getfscreatecon(&prev_scontext) < 0) { - err(udev, "getfscreatecon failed\n"); - prev_scontext = NULL; - } - } -} - -void selinux_exit(struct udev *udev) -{ - if (is_selinux_running(udev) && prev_scontext) { - freecon(prev_scontext); - prev_scontext = NULL; - } -} diff --git a/udev/udev_selinux.h b/udev/udev_selinux.h deleted file mode 100644 index 55bc91222a..0000000000 --- a/udev/udev_selinux.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2004 Daniel Walsh - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ -#ifndef _UDEV_SELINUX_H -#define _UDEV_SELINUX_H - -#ifdef USE_SELINUX -extern void selinux_setfilecon(struct udev *udev, const char *file, const char *devname, unsigned int mode); -extern void selinux_setfscreatecon(struct udev *udev, const char *file, const char *devname, unsigned int mode); -extern void selinux_resetfscreatecon(struct udev *udev); -extern void selinux_init(struct udev *udev); -extern void selinux_exit(struct udev *udev); -#else -static inline void selinux_setfilecon(struct udev *udev, const char *file, const char *devname, unsigned int mode) {} -static inline void selinux_setfscreatecon(struct udev *udev, const char *file, const char *devname, unsigned int mode) {} -static inline void selinux_resetfscreatecon(struct udev *udev) {} -static inline void selinux_init(struct udev *udev) {} -static inline void selinux_exit(struct udev *udev) {} -#endif - -#endif diff --git a/udev/udev_utils_file.c b/udev/udev_utils_file.c index 7ccb5b4039..b8b4d10d21 100644 --- a/udev/udev_utils_file.c +++ b/udev/udev_utils_file.c @@ -30,7 +30,6 @@ #include #include "udev.h" -#include "udev_selinux.h" int create_path(struct udev *udev, const char *path) { @@ -56,9 +55,9 @@ int create_path(struct udev *udev, const char *path) return -1; dbg(udev, "mkdir '%s'\n", p); - selinux_setfscreatecon(udev, p, NULL, S_IFDIR|0755); + udev_selinux_setfscreatecon(udev, p, S_IFDIR|0755); ret = mkdir(p, 0755); - selinux_resetfscreatecon(udev); + udev_selinux_resetfscreatecon(udev); if (ret == 0) return 0; diff --git a/udev/udevd.c b/udev/udevd.c index a24ca92517..d24d8430ca 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -47,7 +47,6 @@ #include "udev.h" #include "udev_rules.h" -#include "udev_selinux.h" #define UDEVD_PRIORITY -4 #define UDEV_PRIORITY -2 @@ -189,9 +188,9 @@ static void export_event_state(struct udevd_uevent_msg *msg, enum event_state st unlink(filename_failed); delete_path(msg->udev, filename_failed); create_path(msg->udev, filename); - selinux_setfscreatecon(msg->udev, filename, NULL, S_IFLNK); + udev_selinux_setfscreatecon(msg->udev, filename, S_IFLNK); symlink(msg->devpath, filename); - selinux_resetfscreatecon(msg->udev); + udev_selinux_resetfscreatecon(msg->udev); break; case EVENT_FINISHED: if (msg->devpath_old != NULL) { @@ -804,8 +803,6 @@ int main(int argc, char *argv[]) logging_init("udevd"); udev_set_log_fn(udev, log_fn); - - selinux_init(udev); dbg(udev, "version %s\n", VERSION); while (1) { @@ -1107,7 +1104,6 @@ int main(int argc, char *argv[]) exit: udev_rules_cleanup(&rules); sysfs_cleanup(); - selinux_exit(udev); if (signal_pipe[READ_END] >= 0) close(signal_pipe[READ_END]); -- cgit v1.2.3-54-g00ecf