X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_selinux.c;h=cc6f4d7d3fad6716d468315993199afe67399887;hp=3728fd0b5094478ae5c5e5ccc34a3f751aa72062;hb=c07669bd663d780e4957691e488798aa0178e76b;hpb=8481f8ce2bd2b19ebcf3cb96ac6825093f626b0f diff --git a/udev_selinux.c b/udev_selinux.c index 3728fd0b5..cc6f4d7d3 100644 --- a/udev_selinux.c +++ b/udev_selinux.c @@ -1,34 +1,168 @@ +/* + * 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_version.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; +} -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 (is_selinux_enabled() > 0) { - security_context_t scontext; - retval = matchpathcon(filename, 0, &scontext); - if (retval < 0) { - dbg("matchpathcon(%s) failed\n", filename); + 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 { - 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) { + dbg("matchpathcon(%s) failed\n", file); + return; + } + + if (setfilecon(file, scontext) < 0) + dbg("setfilecon %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("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) +{ + /* + * 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_exit(void) +{ + if (is_selinux_running() && prev_scontext) { + freecon(prev_scontext); + prev_scontext = NULL; + } +}