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