From b55e6540260ac3e38d96a0b6c00514a72d5db218 Mon Sep 17 00:00:00 2001 From: "pebenito@gentoo.org" Date: Tue, 8 Mar 2005 06:57:25 -0800 Subject: [PATCH 1/1] [PATCH] udev selinux fix Here is a fix for the SELinux part of udev. Setfscreatecon() overrides the default labeling behavior of SELinux when creating files, so it should only be used for as short of a time as possible, around the mknod or symlink calls. Without this, the files in udev_db get the wrong label because the fscreatecon is reset after the udev_db file creation instead of before. I'm guessing the Redhat people missed this because they modify udev_db to be one big file instead of a directory of small files (at least that's what I'm told). I created selinux_resetfscreatecon() to reset the fscreatecon asap after the file/node is created. Fixed a memory leak in selinux_init. Getfscreatecon() allocates memory for the context, and the udev code was immediately setting the pointer (security_context_t is actually a typedef'ed char*) to NULL after the call regardless of success/failure. If you're wondering about the case where there's effectively a setfscreatecon(NULL), this is ok, as its used to tell SELinux to do the default labeling behavior. Renamed selinux_restore() to selinux_exit() due to the changed behavior. Fixed a couple of dbg() messages. --- udev_add.c | 10 +++++++--- udev_selinux.c | 32 +++++++++++++++++--------------- udev_selinux.h | 6 ++++-- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/udev_add.c b/udev_add.c index eeab1ca17..e5bd042a5 100644 --- a/udev_add.c +++ b/udev_add.c @@ -83,6 +83,7 @@ create: selinux_setfscreatecon(file, udev->kernel_name, mode); retval = mknod(file, mode, devt); + selinux_resetfscreatecon(); if (retval != 0) { dbg("mknod(%s, %#o, %u, %u) failed with error '%s'", file, mode, major(devt), minor(devt), strerror(errno)); @@ -196,6 +197,7 @@ static int create_node(struct udevice *udev, struct sysfs_class_device *class_de /* create symlink(s) if requested */ foreach_strpart(udev->symlink, " ", pos, len) { + int retval; char linkname[NAME_SIZE]; char linktarget[NAME_SIZE]; @@ -227,9 +229,11 @@ static int create_node(struct udevice *udev, struct sysfs_class_device *class_de dbg("symlink(%s, %s)", linktarget, filename); if (!udev->test_run) { - selinux_setfscreatecon(filename, udev->kernel_name, S_IFLNK); unlink(filename); - if (symlink(linktarget, filename) != 0) + selinux_setfscreatecon(filename, udev->kernel_name, S_IFLNK); + retval = symlink(linktarget, filename); + selinux_resetfscreatecon(); + if (retval != 0) dbg("symlink(%s, %s) failed with error '%s'", linktarget, filename, strerror(errno)); } @@ -326,7 +330,7 @@ int udev_add_device(struct udevice *udev, struct sysfs_class_device *class_dev) } exit: - selinux_restore(); + selinux_exit(); return retval; } diff --git a/udev_selinux.c b/udev_selinux.c index 72381f0d0..cc6f4d7d3 100644 --- a/udev_selinux.c +++ b/udev_selinux.c @@ -105,7 +105,7 @@ void selinux_setfilecon(const char *file, const char *devname, unsigned int mode } if (setfilecon(file, scontext) < 0) - dbg("setfiles %s failed with error '%s'", file, strerror(errno)); + dbg("setfilecon %s failed with error '%s'", file, strerror(errno)); freecon(scontext); } @@ -131,12 +131,20 @@ void selinux_setfscreatecon(const char *file, const char *devname, unsigned int } if (setfscreatecon(scontext) < 0) - dbg("setfiles %s failed with error '%s'", file, strerror(errno)); + dbg("setfscreatecon %s failed with error '%s'", file, strerror(errno)); freecon(scontext); } } +void selinux_resetfscreatecon(void) +{ + if (is_selinux_running()) { + if (setfscreatecon(prev_scontext) < 0) + dbg("setfscreatecon %s failed with error '%s'", file, strerror(errno)); + } +} + void selinux_init(void) { /* @@ -144,23 +152,17 @@ void selinux_init(void) * restoration creation purposes. */ if (is_selinux_running()) { - if (getfscreatecon(&prev_scontext) < 0) + if (getfscreatecon(&prev_scontext) < 0) { dbg("getfscreatecon failed\n"); - - prev_scontext = NULL; + prev_scontext = NULL; + } } } -void selinux_restore(void) +void selinux_exit(void) { - if (is_selinux_running()) { - /* reset the file create context to its former glory */ - if (setfscreatecon(prev_scontext) < 0) - dbg("setfscreatecon failed\n"); - - if (prev_scontext) { - freecon(prev_scontext); - prev_scontext = NULL; - } + if (is_selinux_running() && prev_scontext) { + freecon(prev_scontext); + prev_scontext = NULL; } } diff --git a/udev_selinux.h b/udev_selinux.h index 132a9a655..d9dfeffad 100644 --- a/udev_selinux.h +++ b/udev_selinux.h @@ -24,15 +24,17 @@ extern void selinux_setfilecon(const char *file, const char *devname, unsigned int mode); extern void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode); +extern void selinux_resetfscreatecon(void); extern void selinux_init(void); -extern void selinux_restore(void); +extern void selinux_exit(void); #else static inline void selinux_setfilecon(const char *file, const char *devname, unsigned int mode) {} static inline void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode) {} +static inline void selinux_resetfscreatecon(void) {} static inline void selinux_init(void) {} -static inline void selinux_restore(void) {} +static inline void selinux_exit(void) {} #endif /* USE_SELINUX */ #endif /* _UDEV_USE_SELINUX */ -- 2.30.2