X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_selinux.c;h=446fedc3c35aa67c47e724cb820f357d69d61196;hp=723af9a02fc8753d854149c49dfcc2bfbea4050c;hb=c7a42aea3c1a81f7325104871aad6bb6b0a15834;hpb=b528cd49203c64cf117868b5a5907cb11d934bbb diff --git a/udev_selinux.c b/udev_selinux.c index 723af9a02..446fedc3c 100644 --- a/udev_selinux.c +++ b/udev_selinux.c @@ -1,73 +1,169 @@ +/* + * 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 -#include #include -#include +#include #include -#include +#include +#include #include +#include +#include +#include #include #include "udev.h" -#include "udev_lib.h" -#include "logging.h" +#include "udev_selinux.h" -#ifdef LOG -unsigned char logname[LOGNAME_SIZE]; -void log_message(int level, const char *format, ...) +static security_context_t prev_scontext = NULL; + +static int is_selinux_running(void) { - va_list args; + static int selinux_enabled = -1; - if (!udev_log) - return; + if (selinux_enabled == -1) + selinux_enabled = (is_selinux_enabled() > 0); - va_start(args, format); - vsyslog(level, format, args); - va_end(args); + dbg("selinux=%i", selinux_enabled); + return selinux_enabled; } -#endif -void selinux_add_node(char *filename) +static char *get_media(const char *devname, int mode) { - int retval; + FILE *fp; + char procfile[PATH_MAX]; + char mediabuf[256]; + int size; + char *media = NULL; + + if (!(mode & S_IFBLK)) + return NULL; - if (is_selinux_enabled() > 0) { - security_context_t scontext; - retval = matchpathcon(filename, 0, &scontext); - if (retval < 0) { - dbg("matchpathcon(%s) failed\n", filename); + 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 { - retval=setfilecon(filename,scontext); - if (retval < 0) - dbg("setfiles %s failed with error '%s'", - filename, strerror(errno)); - free(scontext); + 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) { + err("matchpathcon(%s) failed\n", file); + return; + } + + if (setfilecon(file, scontext) < 0) + err("setfilecon %s failed: %s", file, strerror(errno)); + + freecon(scontext); } } -int main(int argc, char *argv[], char *envp[]) +void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode) { - char *action; - char *devpath; - char *devnode; - int retval = 0; + if (is_selinux_running()) { + security_context_t scontext = NULL; + char *media; + int ret = -1; - init_logging("udev_selinux"); + media = get_media(devname, mode); + if (media) { + ret = matchmediacon(media, &scontext); + free(media); + } + + if (ret < 0) + if (matchpathcon(file, mode, &scontext) < 0) { + err("matchpathcon(%s) failed\n", file); + return; + } - action = get_action(); - if (!action) { - dbg("no action?"); - goto exit; + if (setfscreatecon(scontext) < 0) + err("setfscreatecon %s failed: %s", file, strerror(errno)); + + freecon(scontext); } - devnode = get_devnode(); - if (!devnode) { - dbg("no devnode?"); - goto exit; +} + +void selinux_resetfscreatecon(void) +{ + if (is_selinux_running()) { + if (setfscreatecon(prev_scontext) < 0) + err("setfscreatecon failed: %s", strerror(errno)); } +} - if (strcmp(action, "add") == 0) - selinux_add_node(devnode); +void selinux_init(void) +{ + /* + * record the present security context, for file-creation + * restoration creation purposes. + */ + if (is_selinux_running()) { + matchpathcon_init_prefix(NULL, udev_root); + if (getfscreatecon(&prev_scontext) < 0) { + err("getfscreatecon failed\n"); + prev_scontext = NULL; + } + } +} -exit: - return retval; +void selinux_exit(void) +{ + if (is_selinux_running() && prev_scontext) { + freecon(prev_scontext); + prev_scontext = NULL; + } }