--- udev-add.c.orig 2004-07-09 18:59:09.000000000 +0100 +++ udev-add.c 2004-08-03 16:21:59.000000000 +0100 @@ -50,6 +50,10 @@ #define LOCAL_USER "$local" +#ifdef WITH_SELINUX +#include +#endif + /* * Right now the major/minor of a device is stored in a file called * "dev" in sysfs. @@ -92,7 +96,31 @@ break; *pos = 0x00; if (stat(p, &stats)) { +#ifdef WITH_SELINUX + int seretval = 0; + security_context_t scontext; + if (is_selinux_enabled() > 0) + { + seretval = matchpathcon(p, S_IFDIR, &scontext); + if (seretval < 0) { + dbg("matchpathcon(%s) failed\n", p); + } else { + seretval=setfscreatecon(scontext); + if (seretval < 0) + dbg("setfiles %s failed with error '%s'", + p, strerror(errno)); + } + } +#endif retval = mkdir(p, 0755); +#ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) + { + /* after mkdir, free the context */ + freecon(scontext); + } +#endif + if (retval != 0) { dbg("mkdir(%s) failed with error '%s'", p, strerror(errno)); @@ -109,6 +137,10 @@ { struct stat stats; int retval = 0; + int seretval = 0; +#ifdef WITH_SELINUX + security_context_t scontext; +#endif if (stat(file, &stats) != 0) goto create; @@ -117,6 +149,24 @@ if (((stats.st_mode & S_IFMT) == S_IFBLK || (stats.st_mode & S_IFMT) == S_IFCHR) && (stats.st_rdev == makedev(major, minor))) { dbg("preserve file '%s', cause it has correct dev_t", file); +#ifdef WITH_SELINUX + /* lkcl: maybe someone would like to do the same thing with se/linux + * security contexts (check they are the same) but hey, not me! + */ + if (is_selinux_enabled() > 0) + { + retval = matchpathcon(file, mode, &scontext); + if (retval < 0) { + dbg("matchpathcon(%s) failed\n", file); + } else { + retval=setfilecon(scontext, file); + if (retval < 0) + dbg("setfiles %s failed with error '%s'", + file, strerror(errno)); + freecon(scontext); + } + } +#endif goto perms; } @@ -126,6 +176,21 @@ dbg("already present file '%s' unlinked", file); create: +#ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) + { + seretval = matchpathcon(file, mode, &scontext); + if (seretval < 0) { + dbg("matchpathcon(%s) failed\n", file); + } else { + retval=setfscreatecon(scontext); + if (retval < 0) + dbg("setfiles %s failed with error '%s'", + file, strerror(errno)); + } + } +#endif + retval = mknod(file, mode, makedev(major, minor)); if (retval != 0) { dbg("mknod(%s, %#o, %u, %u) failed with error '%s'", @@ -133,6 +198,15 @@ goto exit; } +#ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) + { + /* after mknod, free the context */ + if (seretval == 0) + freecon(scontext); + } +#endif + perms: dbg("chmod(%s, %#o)", file, mode); if (chmod(file, mode) != 0) { @@ -150,7 +224,11 @@ } exit: +#ifdef WITH_SELINUX + return retval < 0 ? retval : seretval; +#else return retval; +#endif } /* get the local logged in user */ @@ -304,10 +382,36 @@ dbg("symlink(%s, %s)", linktarget, filename); if (!fake) { +#ifdef WITH_SELINUX + int seretval = 0; + security_context_t scontext; + if (is_selinux_enabled() > 0) + { + seretval = matchpathcon(filename, S_IFLNK, &scontext); + if (seretval < 0) { + dbg("matchpathcon(%s) failed\n", filename); + } else { + seretval=setfscreatecon(scontext); + if (seretval < 0) + dbg("setfiles %s failed with error '%s'", + filename, strerror(errno)); + } + } +#endif + + unlink(filename); if (symlink(linktarget, filename) != 0) dbg("symlink(%s, %s) failed with error '%s'", linktarget, filename, strerror(errno)); +#ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) + { + /* after symlink, free the context */ + freecon(scontext); + } +#endif + } } @@ -403,6 +507,11 @@ char *pos; int retval; +#ifdef WITH_SELINUX + int seretval; + security_context_t prev_scontext; +#endif + memset(&dev, 0x00, sizeof(dev)); dev.type = get_device_type(path, subsystem); @@ -438,6 +547,23 @@ dbg("name='%s'", dev.name); +#ifdef WITH_SELINUX + /* record the present security context, for file-creation + * restoration creation purposes. + * + * we're going to assume that between now and the time that + * this context is restored that the only filecreation of any + * kind to occur will be mknod, symlink and mkdirs. + */ + + if (is_selinux_enabled() > 0) + { + seretval = getfscreatecon(&prev_scontext); + if (seretval < 0) { + dbg("getfscreatecon failed\n"); + } + } +#endif switch (dev.type) { case 'b': case 'c': @@ -474,6 +600,16 @@ break; } +#ifdef WITH_SELINUX + if (is_selinux_enabled() > 0) + { + /* reset the file create context to its former glory */ + if (seretval == 0) + seretval=setfscreatecon(prev_scontext); + freecon(prev_scontext); + } +#endif + exit: sysfs_close_class_device(class_dev); --- Makefile.orig 2004-08-02 22:23:58.000000000 +0100 +++ Makefile 2004-08-02 22:24:01.000000000 +0100 @@ -25,6 +25,8 @@ # Leave this set to `false' for production use. DEBUG = true +# Set this to compile with Security-Enhanced Linux support. +WITH_SELINUX = true ROOT = udev DAEMON = udevd @@ -39,6 +41,7 @@ LOCAL_CFG_DIR = etc/udev HOTPLUG_EXEC = $(ROOT) + DESTDIR = KERNEL_DIR = /lib/modules/${shell uname -r}/build @@ -172,6 +175,13 @@ CFLAGS += -I$(PWD)/libsysfs +ifeq ($(strip $(WITH_SELINUX)),true) + LIB_OBJS += \ + -lselinux + CFLAGS += \ + -DWITH_SELINUX +endif + all: $(ROOT) $(SENDER) $(DAEMON) $(INFO) $(TESTER) $(STARTER) @extras="$(EXTRAS)" ; for target in $$extras ; do \ echo $$target ; \