1 #include <unistd.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <sys/mman.h> 5 #include <sys/mount.h> 6 #include <sys/utsname.h> 7 #include <fcntl.h> 8 #include <stdlib.h> 9 #include <stdio.h> 10 #include <ctype.h> 11 #include <string.h> 12 #include <errno.h> 13 #include "selinux_internal.h" 14 #ifndef ANDROID 15 #include <sepol/sepol.h> 16 #include <sepol/policydb.h> 17 #endif 18 #include <dlfcn.h> 19 #include "policy.h" 20 #include <limits.h> 21 22 #ifndef MNT_DETACH 23 #define MNT_DETACH 2 24 #endif 25 26 int security_load_policy(void *data, size_t len) 27 { 28 char path[PATH_MAX]; 29 int fd, ret; 30 31 if (!selinux_mnt) { 32 errno = ENOENT; 33 return -1; 34 } 35 36 snprintf(path, sizeof path, "%s/load", selinux_mnt); 37 fd = open(path, O_RDWR | O_CLOEXEC); 38 if (fd < 0) 39 return -1; 40 41 ret = write(fd, data, len); 42 close(fd); 43 if (ret < 0) 44 return -1; 45 return 0; 46 } 47 48 hidden_def(security_load_policy) 49 50 #ifndef ANDROID 51 int load_setlocaldefs hidden = 1; 52 53 #undef max 54 #define max(a, b) (((a) > (b)) ? (a) : (b)) 55 56 int selinux_mkload_policy(int preservebools) 57 { 58 int kernvers = security_policyvers(); 59 int maxvers = kernvers, minvers = DEFAULT_POLICY_VERSION, vers; 60 int setlocaldefs = load_setlocaldefs; 61 char path[PATH_MAX]; 62 struct stat sb; 63 struct utsname uts; 64 size_t size; 65 void *map, *data; 66 int fd, rc = -1, prot; 67 sepol_policydb_t *policydb; 68 sepol_policy_file_t *pf; 69 int usesepol = 0; 70 int (*vers_max)(void) = NULL; 71 int (*vers_min)(void) = NULL; 72 int (*policy_file_create)(sepol_policy_file_t **) = NULL; 73 void (*policy_file_free)(sepol_policy_file_t *) = NULL; 74 void (*policy_file_set_mem)(sepol_policy_file_t *, char*, size_t) = NULL; 75 int (*policydb_create)(sepol_policydb_t **) = NULL; 76 void (*policydb_free)(sepol_policydb_t *) = NULL; 77 int (*policydb_read)(sepol_policydb_t *, sepol_policy_file_t *) = NULL; 78 int (*policydb_set_vers)(sepol_policydb_t *, unsigned int) = NULL; 79 int (*policydb_to_image)(sepol_handle_t *, sepol_policydb_t *, void **, size_t *) = NULL; 80 int (*genbools_array)(void *data, size_t len, char **names, int *values, int nel) = NULL; 81 int (*genusers)(void *data, size_t len, const char *usersdir, void **newdata, size_t * newlen) = NULL; 82 int (*genbools)(void *data, size_t len, const char *boolpath) = NULL; 83 84 #ifdef SHARED 85 char *errormsg = NULL; 86 void *libsepolh = NULL; 87 libsepolh = dlopen("libsepol.so.1", RTLD_NOW); 88 if (libsepolh) { 89 usesepol = 1; 90 dlerror(); 91 #define DLERR() if ((errormsg = dlerror())) goto dlclose; 92 vers_max = dlsym(libsepolh, "sepol_policy_kern_vers_max"); 93 DLERR(); 94 vers_min = dlsym(libsepolh, "sepol_policy_kern_vers_min"); 95 DLERR(); 96 97 policy_file_create = dlsym(libsepolh, "sepol_policy_file_create"); 98 DLERR(); 99 policy_file_free = dlsym(libsepolh, "sepol_policy_file_free"); 100 DLERR(); 101 policy_file_set_mem = dlsym(libsepolh, "sepol_policy_file_set_mem"); 102 DLERR(); 103 policydb_create = dlsym(libsepolh, "sepol_policydb_create"); 104 DLERR(); 105 policydb_free = dlsym(libsepolh, "sepol_policydb_free"); 106 DLERR(); 107 policydb_read = dlsym(libsepolh, "sepol_policydb_read"); 108 DLERR(); 109 policydb_set_vers = dlsym(libsepolh, "sepol_policydb_set_vers"); 110 DLERR(); 111 policydb_to_image = dlsym(libsepolh, "sepol_policydb_to_image"); 112 DLERR(); 113 genbools_array = dlsym(libsepolh, "sepol_genbools_array"); 114 DLERR(); 115 genusers = dlsym(libsepolh, "sepol_genusers"); 116 DLERR(); 117 genbools = dlsym(libsepolh, "sepol_genbools"); 118 DLERR(); 119 120 #undef DLERR 121 } 122 #else 123 usesepol = 1; 124 vers_max = sepol_policy_kern_vers_max; 125 vers_min = sepol_policy_kern_vers_min; 126 policy_file_create = sepol_policy_file_create; 127 policy_file_free = sepol_policy_file_free; 128 policy_file_set_mem = sepol_policy_file_set_mem; 129 policydb_create = sepol_policydb_create; 130 policydb_free = sepol_policydb_free; 131 policydb_read = sepol_policydb_read; 132 policydb_set_vers = sepol_policydb_set_vers; 133 policydb_to_image = sepol_policydb_to_image; 134 genbools_array = sepol_genbools_array; 135 genusers = sepol_genusers; 136 genbools = sepol_genbools; 137 138 #endif 139 140 /* 141 * Check whether we need to support local boolean and user definitions. 142 */ 143 if (setlocaldefs) { 144 if (access(selinux_booleans_path(), F_OK) == 0) 145 goto checkbool; 146 snprintf(path, sizeof path, "%s.local", selinux_booleans_path()); 147 if (access(path, F_OK) == 0) 148 goto checkbool; 149 snprintf(path, sizeof path, "%s/local.users", selinux_users_path()); 150 if (access(path, F_OK) == 0) 151 goto checkbool; 152 /* No local definition files, so disable setlocaldefs. */ 153 setlocaldefs = 0; 154 } 155 156 checkbool: 157 /* 158 * As of Linux 2.6.22, the kernel preserves boolean 159 * values across a reload, so we do not need to 160 * preserve them in userspace. 161 */ 162 if (preservebools && uname(&uts) == 0 && strverscmp(uts.release, "2.6.22") >= 0) 163 preservebools = 0; 164 165 if (usesepol) { 166 maxvers = vers_max(); 167 minvers = vers_min(); 168 if (!setlocaldefs && !preservebools) 169 maxvers = max(kernvers, maxvers); 170 } 171 172 vers = maxvers; 173 search: 174 snprintf(path, sizeof(path), "%s.%d", 175 selinux_binary_policy_path(), vers); 176 fd = open(path, O_RDONLY | O_CLOEXEC); 177 while (fd < 0 && errno == ENOENT 178 && --vers >= minvers) { 179 /* Check prior versions to see if old policy is available */ 180 snprintf(path, sizeof(path), "%s.%d", 181 selinux_binary_policy_path(), vers); 182 fd = open(path, O_RDONLY | O_CLOEXEC); 183 } 184 if (fd < 0) { 185 fprintf(stderr, 186 "SELinux: Could not open policy file <= %s.%d: %s\n", 187 selinux_binary_policy_path(), maxvers, strerror(errno)); 188 goto dlclose; 189 } 190 191 if (fstat(fd, &sb) < 0) { 192 fprintf(stderr, 193 "SELinux: Could not stat policy file %s: %s\n", 194 path, strerror(errno)); 195 goto close; 196 } 197 198 prot = PROT_READ; 199 if (setlocaldefs || preservebools) 200 prot |= PROT_WRITE; 201 202 size = sb.st_size; 203 data = map = mmap(NULL, size, prot, MAP_PRIVATE, fd, 0); 204 if (map == MAP_FAILED) { 205 fprintf(stderr, 206 "SELinux: Could not map policy file %s: %s\n", 207 path, strerror(errno)); 208 goto close; 209 } 210 211 if (vers > kernvers && usesepol) { 212 /* Need to downgrade to kernel-supported version. */ 213 if (policy_file_create(&pf)) 214 goto unmap; 215 if (policydb_create(&policydb)) { 216 policy_file_free(pf); 217 goto unmap; 218 } 219 policy_file_set_mem(pf, data, size); 220 if (policydb_read(policydb, pf)) { 221 policy_file_free(pf); 222 policydb_free(policydb); 223 goto unmap; 224 } 225 if (policydb_set_vers(policydb, kernvers) || 226 policydb_to_image(NULL, policydb, &data, &size)) { 227 /* Downgrade failed, keep searching. */ 228 fprintf(stderr, 229 "SELinux: Could not downgrade policy file %s, searching for an older version.\n", 230 path); 231 policy_file_free(pf); 232 policydb_free(policydb); 233 munmap(map, sb.st_size); 234 close(fd); 235 vers--; 236 goto search; 237 } 238 policy_file_free(pf); 239 policydb_free(policydb); 240 } 241 242 if (usesepol) { 243 if (setlocaldefs) { 244 void *olddata = data; 245 size_t oldsize = size; 246 rc = genusers(olddata, oldsize, selinux_users_path(), 247 &data, &size); 248 if (rc < 0) { 249 /* Fall back to the prior image if genusers failed. */ 250 data = olddata; 251 size = oldsize; 252 rc = 0; 253 } else { 254 if (olddata != map) 255 free(olddata); 256 } 257 } 258 259 if (preservebools) { 260 int *values, len, i; 261 char **names; 262 rc = security_get_boolean_names(&names, &len); 263 if (!rc) { 264 values = malloc(sizeof(int) * len); 265 if (!values) 266 goto unmap; 267 for (i = 0; i < len; i++) 268 values[i] = 269 security_get_boolean_active(names[i]); 270 (void)genbools_array(data, size, names, values, 271 len); 272 free(values); 273 for (i = 0; i < len; i++) 274 free(names[i]); 275 free(names); 276 } 277 } else if (setlocaldefs) { 278 (void)genbools(data, size, selinux_booleans_path()); 279 } 280 } 281 282 283 rc = security_load_policy(data, size); 284 285 if (rc) 286 fprintf(stderr, 287 "SELinux: Could not load policy file %s: %s\n", 288 path, strerror(errno)); 289 290 unmap: 291 if (data != map) 292 free(data); 293 munmap(map, sb.st_size); 294 close: 295 close(fd); 296 dlclose: 297 #ifdef SHARED 298 if (errormsg) 299 fprintf(stderr, "libselinux: %s\n", errormsg); 300 if (libsepolh) 301 dlclose(libsepolh); 302 #endif 303 return rc; 304 } 305 306 hidden_def(selinux_mkload_policy) 307 308 /* 309 * Mount point for selinuxfs. 310 * This definition is private to the function below. 311 * Everything else uses the location determined during 312 * libselinux startup via /proc/mounts (see init_selinuxmnt). 313 * We only need the hardcoded definition for the initial mount 314 * required for the initial policy load. 315 */ 316 int selinux_init_load_policy(int *enforce) 317 { 318 int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1; 319 FILE *cfg; 320 char *buf; 321 322 /* 323 * Reread the selinux configuration in case it has changed. 324 * Example: Caller has chroot'd and is now loading policy from 325 * chroot'd environment. 326 */ 327 selinux_reset_config(); 328 329 /* 330 * Get desired mode (disabled, permissive, enforcing) from 331 * /etc/selinux/config. 332 */ 333 selinux_getenforcemode(&seconfig); 334 335 /* Check for an override of the mode via the kernel command line. */ 336 rc = mount("proc", "/proc", "proc", 0, 0); 337 cfg = fopen("/proc/cmdline", "re"); 338 if (cfg) { 339 char *tmp; 340 buf = malloc(selinux_page_size); 341 if (!buf) { 342 fclose(cfg); 343 return -1; 344 } 345 if (fgets(buf, selinux_page_size, cfg) && 346 (tmp = strstr(buf, "enforcing="))) { 347 if (tmp == buf || isspace(*(tmp - 1))) { 348 secmdline = 349 atoi(tmp + sizeof("enforcing=") - 1); 350 } 351 } 352 fclose(cfg); 353 free(buf); 354 } 355 356 /* 357 * Determine the final desired mode. 358 * Command line argument takes precedence, then config file. 359 */ 360 if (secmdline >= 0) 361 *enforce = secmdline; 362 else if (seconfig >= 0) 363 *enforce = seconfig; 364 else 365 *enforce = 0; /* unspecified or disabled */ 366 367 /* 368 * Check for the existence of SELinux via selinuxfs, and 369 * mount it if present for use in the calls below. 370 */ 371 const char *mntpoint = NULL; 372 /* First make sure /sys is mounted */ 373 if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) { 374 if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 375 mntpoint = SELINUXMNT; 376 } else { 377 /* check old mountpoint */ 378 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 379 mntpoint = OLDSELINUXMNT; 380 } 381 } 382 } else { 383 /* check old mountpoint */ 384 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 385 mntpoint = OLDSELINUXMNT; 386 } 387 } 388 389 if (! mntpoint ) { 390 if (errno == ENODEV || !selinuxfs_exists()) { 391 /* 392 * SELinux was disabled in the kernel, either 393 * omitted entirely or disabled at boot via selinux=0. 394 * This takes precedence over any config or 395 * commandline enforcing setting. 396 */ 397 *enforce = 0; 398 } else { 399 /* Only emit this error if selinux was not disabled */ 400 fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno)); 401 } 402 403 if (rc == 0) 404 umount2("/proc", MNT_DETACH); 405 406 goto noload; 407 } 408 set_selinuxmnt(mntpoint); 409 410 if (rc == 0) 411 umount2("/proc", MNT_DETACH); 412 413 /* 414 * Note: The following code depends on having selinuxfs 415 * already mounted and selinuxmnt set above. 416 */ 417 418 if (seconfig == -1) { 419 /* Runtime disable of SELinux. */ 420 rc = security_disable(); 421 if (rc == 0) { 422 /* Successfully disabled, so umount selinuxfs too. */ 423 umount(selinux_mnt); 424 fini_selinuxmnt(); 425 goto noload; 426 } else { 427 /* 428 * It's possible that this failed because policy has 429 * already been loaded. We can't disable SELinux now, 430 * so the best we can do is force it to be permissive. 431 */ 432 *enforce = 0; 433 } 434 } 435 436 /* 437 * If necessary, change the kernel enforcing status to match 438 * the desired mode. 439 */ 440 orig_enforce = rc = security_getenforce(); 441 if (rc < 0) 442 goto noload; 443 if (orig_enforce != *enforce) { 444 rc = security_setenforce(*enforce); 445 if (rc < 0) { 446 fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno)); 447 if (*enforce) 448 goto noload; 449 } 450 } 451 452 if (seconfig == -1) 453 goto noload; 454 455 /* Load the policy. */ 456 return selinux_mkload_policy(0); 457 458 noload: 459 /* 460 * Only return 0 on a successful completion of policy load. 461 * In any other case, we want to return an error so that init 462 * knows not to proceed with the re-exec for the domain transition. 463 * Depending on the *enforce setting, init will halt (> 0) or proceed 464 * normally (otherwise). 465 */ 466 return -1; 467 } 468 #endif 469