1 /* 2 * Author: Karl MacMillan <kmacmillan (at) tresys.com> 3 * 4 * Modified: 5 * Dan Walsh <dwalsh (at) redhat.com> - Added security_load_booleans(). 6 */ 7 8 #include <sys/types.h> 9 #include <sys/stat.h> 10 #include <fcntl.h> 11 #include <assert.h> 12 #include <stdlib.h> 13 #include <dirent.h> 14 #include <string.h> 15 #include <stdio.h> 16 #include <unistd.h> 17 #include <fnmatch.h> 18 #include <limits.h> 19 #include <ctype.h> 20 #include <errno.h> 21 22 #include "selinux_internal.h" 23 #include "policy.h" 24 25 #define SELINUX_BOOL_DIR "/booleans/" 26 27 static int filename_select(const struct dirent *d) 28 { 29 if (d->d_name[0] == '.' 30 && (d->d_name[1] == '\0' 31 || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) 32 return 0; 33 return 1; 34 } 35 36 int security_get_boolean_names(char ***names, int *len) 37 { 38 char path[PATH_MAX]; 39 int i, rc; 40 struct dirent **namelist; 41 char **n; 42 43 assert(len); 44 if (!selinux_mnt) { 45 errno = ENOENT; 46 return -1; 47 } 48 49 snprintf(path, sizeof path, "%s%s", selinux_mnt, SELINUX_BOOL_DIR); 50 *len = scandir(path, &namelist, &filename_select, alphasort); 51 if (*len <= 0) { 52 return -1; 53 } 54 55 n = (char **)malloc(sizeof(char *) * *len); 56 if (!n) { 57 rc = -1; 58 goto bad; 59 } 60 61 for (i = 0; i < *len; i++) { 62 n[i] = strdup(namelist[i]->d_name); 63 if (!n[i]) { 64 rc = -1; 65 goto bad_freen; 66 } 67 } 68 rc = 0; 69 *names = n; 70 out: 71 for (i = 0; i < *len; i++) { 72 free(namelist[i]); 73 } 74 free(namelist); 75 return rc; 76 bad_freen: 77 for (--i; i >= 0; --i) 78 free(n[i]); 79 free(n); 80 bad: 81 goto out; 82 } 83 84 hidden_def(security_get_boolean_names) 85 #define STRBUF_SIZE 3 86 static int get_bool_value(const char *name, char **buf) 87 { 88 int fd, len; 89 char *fname = NULL; 90 91 if (!selinux_mnt) { 92 errno = ENOENT; 93 return -1; 94 } 95 96 *buf = (char *)malloc(sizeof(char) * (STRBUF_SIZE + 1)); 97 if (!*buf) 98 goto out; 99 (*buf)[STRBUF_SIZE] = 0; 100 101 len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); 102 fname = (char *)malloc(sizeof(char) * len); 103 if (!fname) 104 goto out; 105 snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); 106 107 fd = open(fname, O_RDONLY); 108 if (fd < 0) 109 goto out; 110 111 len = read(fd, *buf, STRBUF_SIZE); 112 close(fd); 113 if (len != STRBUF_SIZE) 114 goto out; 115 116 free(fname); 117 return 0; 118 out: 119 if (*buf) 120 free(*buf); 121 if (fname) 122 free(fname); 123 return -1; 124 } 125 126 int security_get_boolean_pending(const char *name) 127 { 128 char *buf; 129 int val; 130 131 if (get_bool_value(name, &buf)) 132 return -1; 133 134 if (atoi(&buf[1])) 135 val = 1; 136 else 137 val = 0; 138 free(buf); 139 return val; 140 } 141 142 int security_get_boolean_active(const char *name) 143 { 144 char *buf; 145 int val; 146 147 if (get_bool_value(name, &buf)) 148 return -1; 149 150 buf[1] = '\0'; 151 if (atoi(buf)) 152 val = 1; 153 else 154 val = 0; 155 free(buf); 156 return val; 157 } 158 159 hidden_def(security_get_boolean_active) 160 161 int security_set_boolean(const char *name, int value) 162 { 163 int fd, ret, len; 164 char buf[2], *fname; 165 166 if (!selinux_mnt) { 167 errno = ENOENT; 168 return -1; 169 } 170 if (value < 0 || value > 1) { 171 errno = EINVAL; 172 return -1; 173 } 174 175 len = strlen(name) + strlen(selinux_mnt) + sizeof(SELINUX_BOOL_DIR); 176 fname = (char *)malloc(sizeof(char) * len); 177 if (!fname) 178 return -1; 179 snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); 180 181 fd = open(fname, O_WRONLY); 182 if (fd < 0) { 183 ret = -1; 184 goto out; 185 } 186 187 if (value) 188 buf[0] = '1'; 189 else 190 buf[0] = '0'; 191 buf[1] = '\0'; 192 193 ret = write(fd, buf, 2); 194 close(fd); 195 out: 196 free(fname); 197 if (ret > 0) 198 return 0; 199 else 200 return -1; 201 } 202 203 hidden_def(security_set_boolean) 204 205 int security_commit_booleans(void) 206 { 207 int fd, ret; 208 char buf[2]; 209 char path[PATH_MAX]; 210 211 if (!selinux_mnt) { 212 errno = ENOENT; 213 return -1; 214 } 215 216 snprintf(path, sizeof path, "%s/commit_pending_bools", selinux_mnt); 217 fd = open(path, O_WRONLY); 218 if (fd < 0) 219 return -1; 220 221 buf[0] = '1'; 222 buf[1] = '\0'; 223 224 ret = write(fd, buf, 2); 225 close(fd); 226 227 if (ret > 0) 228 return 0; 229 else 230 return -1; 231 } 232 233 hidden_def(security_commit_booleans) 234 235 static void rollback(SELboolean * boollist, int end) 236 { 237 int i; 238 239 for (i = 0; i < end; i++) 240 security_set_boolean(boollist[i].name, 241 security_get_boolean_active(boollist[i]. 242 name)); 243 } 244 245 int security_set_boolean_list(size_t boolcnt, SELboolean * boollist, 246 int permanent __attribute__((unused))) 247 { 248 249 size_t i; 250 for (i = 0; i < boolcnt; i++) { 251 if (security_set_boolean(boollist[i].name, boollist[i].value)) { 252 rollback(boollist, i); 253 return -1; 254 } 255 } 256 257 /* OK, let's do the commit */ 258 if (security_commit_booleans()) { 259 return -1; 260 } 261 262 return 0; 263 } 264