diff options
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | selinux.h | 148 | ||||
-rw-r--r-- | udev_add.c | 15 | ||||
-rw-r--r-- | udev_selinux.c | 166 | ||||
-rw-r--r-- | udev_selinux.h | 38 |
5 files changed, 217 insertions, 157 deletions
@@ -203,7 +203,7 @@ HEADERS = \ udev_db.h \ udev_sysfs.h \ logging.h \ - selinux.h \ + udev_selinux.h \ list.h SYSFS_OBJS = \ @@ -245,6 +245,11 @@ ifeq ($(strip $(USE_KLIBC)),true) OBJS += klibc_fixups/klibc_fixups.a endif +ifeq ($(strip $(USE_SELINUX)),true) + UDEV_OBJS += udev_selinux.o + LIB_OBJS += -lselinux +endif + ifeq ($(strip $(V)),false) QUIET=@$(PWD)/ccdv HOST_PROGS=ccdv diff --git a/selinux.h b/selinux.h deleted file mode 100644 index df5bab69d7..0000000000 --- a/selinux.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef SELINUX_H -#define SELINUX_H - -#ifndef USE_SELINUX - -static inline void selinux_setfilecon(char *file, unsigned int mode) {} -static inline void selinux_setfscreatecon(char *file, unsigned int mode) {} -static inline void selinux_init(void) {} -static inline void selinux_restore(void) {} - -#else - -#include <selinux/selinux.h> -#include <stdio.h> -#include <limits.h> -#include <ctype.h> - -static int selinux_enabled=-1; -static security_context_t prev_scontext=NULL; - -static inline int is_selinux_running(void) -{ - if (selinux_enabled == -1) - return selinux_enabled = is_selinux_enabled() > 0; - return selinux_enabled; -} - -static inline int selinux_get_media(char *path, int mode, char **media) -{ - FILE *fp; - char buf[PATH_MAX]; - char mediabuf[PATH_MAX]; - int ret = -1; - - *media = NULL; - if (!(mode && S_IFBLK)) { - return -1; - } - - snprintf(buf, sizeof(buf), "/proc/ide/%s/media", basename(path)); - - fp=fopen(buf,"r"); - if (!fp) - goto out; - - mediabuf[0] = '\0'; - - if (fgets(mediabuf, sizeof(mediabuf), fp) == NULL) - goto close_out; - - int size = strlen(mediabuf); - while (size-- > 0) { - if (isspace(mediabuf[size])) { - mediabuf[size]='\0'; - } else { - break; - } - } - *media = strdup(mediabuf); - info("selinux_get_media(%s)->%s \n", path, *media); - ret = 0; - -close_out: - fclose(fp); -out: - return ret; -} - -static inline void selinux_setfilecon(char *file, unsigned int mode) -{ - if (is_selinux_running()) { - security_context_t scontext=NULL; - char *media; - int ret=selinux_get_media(file, mode, &media); - if (ret == 0) { - ret = matchmediacon(media, &scontext); - free(media); - } - if (ret == -1) - if (matchpathcon(file, mode, &scontext) < 0) { - dbg("matchpathcon(%s) failed\n", file); - return; - } - if (setfilecon(file, scontext) < 0) - dbg("setfiles %s failed with error '%s'", - file, strerror(errno)); - freecon(scontext); - } -} - -static inline void selinux_setfscreatecon(char *file, unsigned int mode) -{ - int retval = 0; - security_context_t scontext=NULL; - - if (is_selinux_running()) { - char *media; - int ret = selinux_get_media(file, mode, &media); - - if (ret == 0) { - ret = matchmediacon(media, &scontext); - free(media); - } - - if (ret == -1) - if (matchpathcon(file, mode, &scontext) < 0) { - dbg("matchpathcon(%s) failed\n", file); - return; - } - - retval = setfscreatecon(scontext); - if (retval < 0) - dbg("setfiles %s failed with error '%s'", - file, strerror(errno)); - freecon(scontext); - } -} - -static inline void selinux_init(void) -{ - /* - * record the present security context, for file-creation - * restoration creation purposes. - */ - if (is_selinux_running()) { - if (getfscreatecon(&prev_scontext) < 0) { - dbg("getfscreatecon failed\n"); - } - prev_scontext = NULL; - } -} - -static inline void selinux_restore(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; - } - } -} - -#endif /* USE_SELINUX */ - -#endif /* SELINUX_H */ diff --git a/udev_add.c b/udev_add.c index d4cccfc085..24a20bba9b 100644 --- a/udev_add.c +++ b/udev_add.c @@ -43,8 +43,7 @@ #include "logging.h" #include "namedev.h" #include "udev_db.h" - -#include "selinux.h" +#include "udev_selinux.h" /* * the major/minor of a device is stored in a file called "dev" @@ -68,7 +67,7 @@ error: return -1; } -static int make_node(char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid) +static int make_node(struct udevice *udev, char *file, int major, int minor, unsigned int mode, uid_t uid, gid_t gid) { struct stat stats; int retval = 0; @@ -80,7 +79,7 @@ static int make_node(char *file, int major, int minor, unsigned int mode, uid_t 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); - selinux_setfilecon(file,stats.st_mode); + selinux_setfilecon(file, udev->kernel_name, stats.st_mode); goto perms; } @@ -90,7 +89,7 @@ static int make_node(char *file, int major, int minor, unsigned int mode, uid_t dbg("already present file '%s' unlinked", file); create: - selinux_setfscreatecon(file, mode); + selinux_setfscreatecon(file, udev->kernel_name, mode); retval = mknod(file, mode, makedev(major, minor)); if (retval != 0) { dbg("mknod(%s, %#o, %u, %u) failed with error '%s'", @@ -184,7 +183,7 @@ static int create_node(struct udevice *udev) if (!udev->test_run) { info("creating device node '%s'", filename); - if (make_node(filename, udev->major, udev->minor, udev->mode, uid, gid) != 0) + if (make_node(udev, filename, udev->major, udev->minor, udev->mode, uid, gid) != 0) goto error; } else { info("creating device node '%s', major = '%d', minor = '%d', " @@ -199,7 +198,7 @@ static int create_node(struct udevice *udev) for (i = 1; i <= udev->partitions; i++) { strfieldcpy(partitionname, filename); strintcat(partitionname, i); - make_node(partitionname, udev->major, udev->minor + i, udev->mode, uid, gid); + make_node(udev, partitionname, udev->major, udev->minor + i, udev->mode, uid, gid); } } } @@ -237,7 +236,7 @@ static int create_node(struct udevice *udev) dbg("symlink(%s, %s)", linktarget, filename); if (!udev->test_run) { - selinux_setfscreatecon(filename, S_IFLNK); + selinux_setfscreatecon(filename, udev->kernel_name, S_IFLNK); unlink(filename); if (symlink(linktarget, filename) != 0) dbg("symlink(%s, %s) failed with error '%s'", diff --git a/udev_selinux.c b/udev_selinux.c new file mode 100644 index 0000000000..72381f0d0d --- /dev/null +++ b/udev_selinux.c @@ -0,0 +1,166 @@ +/* + * udev_selinux.h + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <stdlib.h> +#include <stdio.h> +#include <stddef.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <ctype.h> +#include <limits.h> +#include <libgen.h> +#include <errno.h> +#include <selinux/selinux.h> + +#include "udev_selinux.h" +#include "logging.h" + +static security_context_t prev_scontext = NULL; + +static int is_selinux_running(void) +{ + static int selinux_enabled = -1; + + if (selinux_enabled == -1) + selinux_enabled = (is_selinux_enabled() > 0); + + dbg("selinux=%i", selinux_enabled); + return selinux_enabled; +} + +static char *get_media(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("selinux_get_media(%s)='%s'\n", devname, media); + +close_out: + fclose(fp); +out: + return media; +} + +void selinux_setfilecon(const char *file, const char *devname, unsigned int mode) +{ + if (is_selinux_running()) { + security_context_t scontext = NULL; + char *media; + int ret = -1; + + media = get_media(devname, mode); + if (media) { + ret = matchmediacon(media, &scontext); + free(media); + } + + if (ret < 0) + if (matchpathcon(file, mode, &scontext) < 0) { + dbg("matchpathcon(%s) failed\n", file); + return; + } + + if (setfilecon(file, scontext) < 0) + dbg("setfiles %s failed with error '%s'", file, strerror(errno)); + + freecon(scontext); + } +} + +void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode) +{ + if (is_selinux_running()) { + security_context_t scontext = NULL; + char *media; + int ret = -1; + + media = get_media(devname, mode); + if (media) { + ret = matchmediacon(media, &scontext); + free(media); + } + + if (ret < 0) + if (matchpathcon(file, mode, &scontext) < 0) { + dbg("matchpathcon(%s) failed\n", file); + return; + } + + if (setfscreatecon(scontext) < 0) + dbg("setfiles %s failed with error '%s'", file, strerror(errno)); + + freecon(scontext); + } +} + +void selinux_init(void) +{ + /* + * record the present security context, for file-creation + * restoration creation purposes. + */ + if (is_selinux_running()) { + if (getfscreatecon(&prev_scontext) < 0) + dbg("getfscreatecon failed\n"); + + prev_scontext = NULL; + } +} + +void selinux_restore(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; + } + } +} diff --git a/udev_selinux.h b/udev_selinux.h new file mode 100644 index 0000000000..132a9a6550 --- /dev/null +++ b/udev_selinux.h @@ -0,0 +1,38 @@ +/* + * udev_selinux.h + * + * 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., + * 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ +#ifndef _UDEV_SELINUX_H +#define _UDEV_SELINUX_H + +#ifdef USE_SELINUX + +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_init(void); +extern void selinux_restore(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_init(void) {} +static inline void selinux_restore(void) {} + +#endif /* USE_SELINUX */ +#endif /* _UDEV_USE_SELINUX */ |