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 free(names); 267 goto unmap; 268 } 269 for (i = 0; i < len; i++) 270 values[i] = 271 security_get_boolean_active(names[i]); 272 (void)genbools_array(data, size, names, values, 273 len); 274 free(values); 275 for (i = 0; i < len; i++) 276 free(names[i]); 277 free(names); 278 } 279 } else if (setlocaldefs) { 280 (void)genbools(data, size, selinux_booleans_path()); 281 } 282 } 283 284 285 rc = security_load_policy(data, size); 286 287 if (rc) 288 fprintf(stderr, 289 "SELinux: Could not load policy file %s: %s\n", 290 path, strerror(errno)); 291 292 unmap: 293 if (data != map) 294 free(data); 295 munmap(map, sb.st_size); 296 close: 297 close(fd); 298 dlclose: 299 #ifdef SHARED 300 if (errormsg) 301 fprintf(stderr, "libselinux: %s\n", errormsg); 302 if (libsepolh) 303 dlclose(libsepolh); 304 #endif 305 return rc; 306 } 307 308 hidden_def(selinux_mkload_policy) 309 310 /* 311 * Mount point for selinuxfs. 312 * This definition is private to the function below. 313 * Everything else uses the location determined during 314 * libselinux startup via /proc/mounts (see init_selinuxmnt). 315 * We only need the hardcoded definition for the initial mount 316 * required for the initial policy load. 317 */ 318 int selinux_init_load_policy(int *enforce) 319 { 320 int rc = 0, orig_enforce = 0, seconfig = -2, secmdline = -1; 321 FILE *cfg; 322 char *buf; 323 324 /* 325 * Reread the selinux configuration in case it has changed. 326 * Example: Caller has chroot'd and is now loading policy from 327 * chroot'd environment. 328 */ 329 selinux_reset_config(); 330 331 /* 332 * Get desired mode (disabled, permissive, enforcing) from 333 * /etc/selinux/config. 334 */ 335 selinux_getenforcemode(&seconfig); 336 337 /* Check for an override of the mode via the kernel command line. */ 338 rc = mount("proc", "/proc", "proc", 0, 0); 339 cfg = fopen("/proc/cmdline", "re"); 340 if (cfg) { 341 char *tmp; 342 buf = malloc(selinux_page_size); 343 if (!buf) { 344 fclose(cfg); 345 return -1; 346 } 347 if (fgets(buf, selinux_page_size, cfg) && 348 (tmp = strstr(buf, "enforcing="))) { 349 if (tmp == buf || isspace(*(tmp - 1))) { 350 secmdline = 351 atoi(tmp + sizeof("enforcing=") - 1); 352 } 353 } 354 fclose(cfg); 355 free(buf); 356 } 357 358 /* 359 * Determine the final desired mode. 360 * Command line argument takes precedence, then config file. 361 */ 362 if (secmdline >= 0) 363 *enforce = secmdline; 364 else if (seconfig >= 0) 365 *enforce = seconfig; 366 else 367 *enforce = 0; /* unspecified or disabled */ 368 369 /* 370 * Check for the existence of SELinux via selinuxfs, and 371 * mount it if present for use in the calls below. 372 */ 373 const char *mntpoint = NULL; 374 /* First make sure /sys is mounted */ 375 if (mount("sysfs", "/sys", "sysfs", 0, 0) == 0 || errno == EBUSY) { 376 if (mount(SELINUXFS, SELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 377 mntpoint = SELINUXMNT; 378 } else { 379 /* check old mountpoint */ 380 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 381 mntpoint = OLDSELINUXMNT; 382 } 383 } 384 } else { 385 /* check old mountpoint */ 386 if (mount(SELINUXFS, OLDSELINUXMNT, SELINUXFS, 0, 0) == 0 || errno == EBUSY) { 387 mntpoint = OLDSELINUXMNT; 388 } 389 } 390 391 if (! mntpoint ) { 392 if (errno == ENODEV || !selinuxfs_exists()) { 393 /* 394 * SELinux was disabled in the kernel, either 395 * omitted entirely or disabled at boot via selinux=0. 396 * This takes precedence over any config or 397 * commandline enforcing setting. 398 */ 399 *enforce = 0; 400 } else { 401 /* Only emit this error if selinux was not disabled */ 402 fprintf(stderr, "Mount failed for selinuxfs on %s: %s\n", SELINUXMNT, strerror(errno)); 403 } 404 405 if (rc == 0) 406 umount2("/proc", MNT_DETACH); 407 408 goto noload; 409 } 410 set_selinuxmnt(mntpoint); 411 412 if (rc == 0) 413 umount2("/proc", MNT_DETACH); 414 415 /* 416 * Note: The following code depends on having selinuxfs 417 * already mounted and selinuxmnt set above. 418 */ 419 420 if (seconfig == -1) { 421 /* Runtime disable of SELinux. */ 422 rc = security_disable(); 423 if (rc == 0) { 424 /* Successfully disabled, so umount selinuxfs too. */ 425 umount(selinux_mnt); 426 fini_selinuxmnt(); 427 goto noload; 428 } else { 429 /* 430 * It's possible that this failed because policy has 431 * already been loaded. We can't disable SELinux now, 432 * so the best we can do is force it to be permissive. 433 */ 434 *enforce = 0; 435 } 436 } 437 438 /* 439 * If necessary, change the kernel enforcing status to match 440 * the desired mode. 441 */ 442 orig_enforce = rc = security_getenforce(); 443 if (rc < 0) 444 goto noload; 445 if (orig_enforce != *enforce) { 446 rc = security_setenforce(*enforce); 447 if (rc < 0) { 448 fprintf(stderr, "SELinux: Unable to switch to %s mode: %s\n", (*enforce ? "enforcing" : "permissive"), strerror(errno)); 449 if (*enforce) 450 goto noload; 451 } 452 } 453 454 if (seconfig == -1) { 455 umount(selinux_mnt); 456 fini_selinuxmnt(); 457 goto noload; 458 } 459 460 /* Load the policy. */ 461 return selinux_mkload_policy(0); 462 463 noload: 464 /* 465 * Only return 0 on a successful completion of policy load. 466 * In any other case, we want to return an error so that init 467 * knows not to proceed with the re-exec for the domain transition. 468 * Depending on the *enforce setting, init will halt (> 0) or proceed 469 * normally (otherwise). 470 */ 471 return -1; 472 } 473 #endif 474