1/* 2 * Copyright (C) 2004 Daniel Walsh 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by the 6 * Free Software Foundation version 2 of the License. 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License for more details. 12 * 13 * You should have received a copy of the GNU General Public License along 14 * with this program; if not, write to the Free Software Foundation, Inc., 15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 * 17 */ 18 19#include <stdlib.h> 20#include <stdio.h> 21#include <stddef.h> 22#include <unistd.h> 23#include <string.h> 24#include <fcntl.h> 25#include <ctype.h> 26#include <limits.h> 27#include <libgen.h> 28#include <errno.h> 29#include <selinux/selinux.h> 30 31#include "udev.h" 32#include "udev_selinux.h" 33 34static security_context_t prev_scontext = NULL; 35 36static int is_selinux_running(void) 37{ 38 static int selinux_enabled = -1; 39 40 if (selinux_enabled == -1) 41 selinux_enabled = (is_selinux_enabled() > 0); 42 43 dbg("selinux=%i", selinux_enabled); 44 return selinux_enabled; 45} 46 47static char *get_media(const char *devname, int mode) 48{ 49 FILE *fp; 50 char procfile[PATH_MAX]; 51 char mediabuf[256]; 52 int size; 53 char *media = NULL; 54 55 if (!(mode & S_IFBLK)) 56 return NULL; 57 58 snprintf(procfile, PATH_MAX, "/proc/ide/%s/media", devname); 59 procfile[PATH_MAX-1] = '\0'; 60 61 fp = fopen(procfile, "r"); 62 if (!fp) 63 goto out; 64 65 if (fgets(mediabuf, sizeof(mediabuf), fp) == NULL) 66 goto close_out; 67 68 size = strlen(mediabuf); 69 while (size-- > 0) { 70 if (isspace(mediabuf[size])) { 71 mediabuf[size] = '\0'; 72 } else { 73 break; 74 } 75 } 76 77 media = strdup(mediabuf); 78 info("selinux_get_media(%s)='%s'", devname, media); 79 80close_out: 81 fclose(fp); 82out: 83 return media; 84} 85 86void selinux_setfilecon(const char *file, const char *devname, unsigned int mode) 87{ 88 if (is_selinux_running()) { 89 security_context_t scontext = NULL; 90 char *media; 91 int ret = -1; 92 93 if (devname) { 94 media = get_media(devname, mode); 95 if (media) { 96 ret = matchmediacon(media, &scontext); 97 free(media); 98 } 99 } 100 101 if (ret < 0) 102 if (matchpathcon(file, mode, &scontext) < 0) { 103 err("matchpathcon(%s) failed", file); 104 return; 105 } 106 107 if (lsetfilecon(file, scontext) < 0) 108 err("setfilecon %s failed: %s", file, strerror(errno)); 109 110 freecon(scontext); 111 } 112} 113 114void selinux_setfscreatecon(const char *file, const char *devname, unsigned int mode) 115{ 116 if (is_selinux_running()) { 117 security_context_t scontext = NULL; 118 char *media; 119 int ret = -1; 120 121 if (devname) { 122 media = get_media(devname, mode); 123 if (media) { 124 ret = matchmediacon(media, &scontext); 125 free(media); 126 } 127 } 128 129 if (ret < 0) 130 if (matchpathcon(file, mode, &scontext) < 0) { 131 err("matchpathcon(%s) failed", file); 132 return; 133 } 134 135 if (setfscreatecon(scontext) < 0) 136 err("setfscreatecon %s failed: %s", file, strerror(errno)); 137 138 freecon(scontext); 139 } 140} 141 142void selinux_resetfscreatecon(void) 143{ 144 if (is_selinux_running()) { 145 if (setfscreatecon(prev_scontext) < 0) 146 err("setfscreatecon failed: %s", strerror(errno)); 147 } 148} 149 150void selinux_init(void) 151{ 152 /* 153 * record the present security context, for file-creation 154 * restoration creation purposes. 155 */ 156 if (is_selinux_running()) { 157 if (!udev_root[0]) 158 err("selinux_init: udev_root not set"); 159 matchpathcon_init_prefix(NULL, udev_root); 160 if (getfscreatecon(&prev_scontext) < 0) { 161 err("getfscreatecon failed"); 162 prev_scontext = NULL; 163 } 164 } 165} 166 167void selinux_exit(void) 168{ 169 if (is_selinux_running() && prev_scontext) { 170 freecon(prev_scontext); 171 prev_scontext = NULL; 172 } 173} 174