/* Takes base, some number of modules, links them, and expands them reads source from myfiles array, which has the base string followed by each module string */ int expander_policy_init(policydb_t * mybase, int num_modules, policydb_t ** mymodules, policydb_t * myexpanded, const char *const *myfiles) { char *filename[num_modules + 1]; int i; for (i = 0; i < num_modules + 1; i++) { filename[i] = calloc(PATH_MAX, sizeof(char)); if (snprintf(filename[i], PATH_MAX, "policies/test-expander/%s%s", myfiles[i], mls ? ".mls" : ".std") < 0) return -1; } if (policydb_init(mybase)) { fprintf(stderr, "out of memory!\n"); return -1; } for (i = 0; i < num_modules; i++) { if (policydb_init(mymodules[i])) { fprintf(stderr, "out of memory!\n"); return -1; } } if (policydb_init(myexpanded)) { fprintf(stderr, "out of memory!\n"); return -1; } mybase->policy_type = POLICY_BASE; mybase->mls = mls; if (read_source_policy(mybase, filename[0], myfiles[0])) { fprintf(stderr, "read source policy failed %s\n", filename[0]); return -1; } for (i = 1; i < num_modules + 1; i++) { mymodules[i - 1]->policy_type = POLICY_MOD; mymodules[i - 1]->mls = mls; if (read_source_policy(mymodules[i - 1], filename[i], myfiles[i])) { fprintf(stderr, "read source policy failed %s\n", filename[i]); return -1; } } if (link_modules(NULL, mybase, mymodules, num_modules, 0)) { fprintf(stderr, "link modules failed\n"); return -1; } if (expand_module(NULL, mybase, myexpanded, 0, 0)) { fprintf(stderr, "expand modules failed\n"); return -1; } for (i = 0; i < num_modules + 1; i++) { free(filename[i]); } return 0; }
int test_load_policy(policydb_t * p, int policy_type, int mls, const char *test_name, const char *policy_name) { char filename[PATH_MAX]; if (mls) { if (snprintf(filename, PATH_MAX, "policies/%s/%s.mls", test_name, policy_name) < 0) { return -1; } } else { if (snprintf(filename, PATH_MAX, "policies/%s/%s.std", test_name, policy_name) < 0) { return -1; } } if (policydb_init(p)) { fprintf(stderr, "Out of memory"); return -1; } p->policy_type = policy_type; p->mls = mls; if (read_source_policy(p, filename, test_name)) { fprintf(stderr, "failed to read policy %s\n", filename); policydb_destroy(p); return -1; } return 0; }
static bool patch_sepolicy() { policydb_t pdb; if (policydb_init(&pdb) < 0) { fprintf(stderr, "Failed to initialize policydb\n"); return false; } if (!util::selinux_read_policy(SELINUX_POLICY_FILE, &pdb)) { fprintf(stderr, "Failed to read SELinux policy file: %s\n", SELINUX_POLICY_FILE); policydb_destroy(&pdb); return false; } printf("SELinux policy version: %d\n", pdb.policyvers); util::selinux_make_all_permissive(&pdb); if (!util::selinux_write_policy(SELINUX_LOAD_FILE, &pdb)) { fprintf(stderr, "Failed to write SELinux policy file: %s\n", SELINUX_LOAD_FILE); policydb_destroy(&pdb); return false; } policydb_destroy(&pdb); return true; }
static int read_binary_policy(policydb_t * p, char *file, char *progname) { int fd; struct stat sb; void *map; struct policy_file f, *fp; fd = open(file, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", file, strerror(errno)); return -1; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", file, strerror(errno)); close(fd); return -1; } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); close(fd); if (map == MAP_FAILED) { fprintf(stderr, "Can't map '%s': %s\n", file, strerror(errno)); return -1; } policy_file_init(&f); f.type = PF_USE_MEMORY; f.data = map; f.len = sb.st_size; fp = &f; if (policydb_init(p)) { fprintf(stderr, "%s: policydb_init: Out of memory!\n", progname); return -1; } if (policydb_read(p, fp, 1)) { fprintf(stderr, "%s: error(s) encountered while parsing configuration\n", progname); return -1; } /* Check Policy Consistency */ if (p->mls) { if (!mlspol) { fprintf(stderr, "%s: MLS policy, but non-MLS" " is specified\n", progname); return -1; } } else { if (mlspol) { fprintf(stderr, "%s: non-MLS policy, but MLS" " is specified\n", progname); return -1; } } return 0; }
static void selinux_permissive(void) { policydb_t policydb; struct policy_file pf; policydb_init(&policydb); sepol_set_policydb(&policydb); policy_file_init(&pf); // Read the current policy pf.fp = fopen("/sepolicy", "r"); pf.type = PF_USE_STDIO; policydb_read(&policydb, &pf, 0); fclose(pf.fp); // Make init, recovery, and ueventd permissive set_permissive("init", &policydb); set_permissive("recovery", &policydb); set_permissive("ueventd", &policydb); // Write the new policy and load it pf.fp = fopen("/dev/sepolicy", "w+"); policydb_write(&policydb, &pf); int size = ftell(pf.fp); fseek(pf.fp, SEEK_SET, 0); void *map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fileno(pf.fp), 0); int load = open("/sys/fs/selinux/load", O_WRONLY); write(load, map, size); close(load); munmap(map, size); fclose(pf.fp); policydb_destroy(&policydb); }
static bool patch_sepolicy_internal(const std::string &source, const std::string &target) { policydb_t pdb; if (policydb_init(&pdb) < 0) { LOGE("Failed to initialize policydb"); return false; } if (!util::selinux_read_policy(source, &pdb)) { LOGE("Failed to read SELinux policy file: {}", source); policydb_destroy(&pdb); return false; } LOGD("Policy version: {}", pdb.policyvers); for (const char **iter = permissive_types; *iter; ++iter) { util::selinux_make_permissive(&pdb, *iter); } if (!util::selinux_write_policy(target, &pdb)) { LOGE("Failed to write SELinux policy file: {}", target); policydb_destroy(&pdb); return false; } policydb_destroy(&pdb); return true; }
static bool patch_sepolicy_daemon() { policydb_t pdb; if (policydb_init(&pdb) < 0) { LOGE("Failed to initialize policydb"); return false; } if (!util::selinux_read_policy(SELINUX_POLICY_FILE, &pdb)) { LOGE("Failed to read SELinux policy file: %s", SELINUX_POLICY_FILE); policydb_destroy(&pdb); return false; } LOGD("Policy version: %u", pdb.policyvers); util::selinux_add_rule(&pdb, "untrusted_app", "init", "unix_stream_socket", "connectto"); if (!util::selinux_write_policy(SELINUX_LOAD_FILE, &pdb)) { LOGE("Failed to write SELinux policy file: %s", SELINUX_LOAD_FILE); policydb_destroy(&pdb); return false; } policydb_destroy(&pdb); return true; }
int cond_test_init(void) { if (policydb_init(&base_expanded)) { fprintf(stderr, "out of memory!\n"); policydb_destroy(&basemod); return -1; } if (test_load_policy(&basemod, POLICY_BASE, 1, "test-cond", "refpolicy-base.conf")) goto cleanup; if (link_modules(NULL, &basemod, NULL, 0, 0)) { fprintf(stderr, "link modules failed\n"); goto cleanup; } if (expand_module(NULL, &basemod, &base_expanded, 0, 1)) { fprintf(stderr, "expand module failed\n"); goto cleanup; } return 0; cleanup: policydb_destroy(&basemod); policydb_destroy(&base_expanded); return -1; }
int load_policy(char *filename, policydb_t *policydb, struct policy_file *pf) { FILE* f; size_t size; void *data; int ret; f = fopen(filename, "rb"); if (f == NULL) { fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); return 1; } fseek(f, 0, SEEK_END); size = ftell(f); fseek(f, 0, SEEK_SET); data = malloc(size); if (data == NULL) { fprintf(stderr, "Can't allocat memory\n"); fclose(f); return 1; } if (fread(data, 1, size, f) != size) { fprintf(stderr, "Can't read policy file '%s': %s\n", filename, strerror(errno)); free(data); fclose(f); return 1; } policy_file_init(pf); pf->type = PF_USE_MEMORY; pf->data = (char*)data; pf->len = size; if (policydb_init(policydb)) { fprintf(stderr, "policydb_init: Out of memory!\n"); free(data); fclose(f); return 1; } ret = policydb_read(policydb, pf, 1); if (ret) { fprintf(stderr, "error(s) encountered while parsing configuration\n"); free(data); fclose(f); return 1; } free(data); fclose(f); return 0; }
bool selinux_mount() { // Try /sys/fs/selinux if (!util::mount(SELINUX_FS_TYPE, SELINUX_MOUNT_POINT, SELINUX_FS_TYPE, 0, nullptr)) { LOGW("Failed to mount %s at %s: %s", SELINUX_FS_TYPE, SELINUX_MOUNT_POINT, strerror(errno)); if (errno == ENODEV || errno == ENOENT) { LOGI("Kernel does not support SELinux"); } return false; } // Load default policy struct stat sb; if (stat(DEFAULT_SEPOLICY_FILE, &sb) == 0) { if (!selinux_set_enforcing(0)) { LOGW("Failed to set SELinux to permissive mode"); } policydb_t pdb; if (policydb_init(&pdb) < 0) { LOGE("Failed to initialize policydb"); return false; } if (!selinux_read_policy(DEFAULT_SEPOLICY_FILE, &pdb)) { LOGE("Failed to read SELinux policy file: %s", DEFAULT_SEPOLICY_FILE); policydb_destroy(&pdb); return false; } if (!util::selinux_write_policy(SELINUX_LOAD_FILE, &pdb)) { LOGE("Failed to write SELinux policy file: %s", SELINUX_LOAD_FILE); policydb_destroy(&pdb); return false; } policydb_destroy(&pdb); return true; } return true; }
int load_policy(char *filename, policydb_t * policydb, struct policy_file *pf) { int fd; struct stat sb; void *map; int ret; fd = open(filename, O_RDONLY); if (fd < 0) { fprintf(stderr, "Can't open '%s': %s\n", filename, strerror(errno)); return 1; } if (fstat(fd, &sb) < 0) { fprintf(stderr, "Can't stat '%s': %s\n", filename, strerror(errno)); close(fd); return 1; } map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { fprintf(stderr, "Can't mmap '%s': %s\n", filename, strerror(errno)); close(fd); return 1; } policy_file_init(pf); pf->type = PF_USE_MEMORY; pf->data = map; pf->len = sb.st_size; if (policydb_init(policydb)) { fprintf(stderr, "Could not initialize policydb!\n"); close(fd); munmap(map, sb.st_size); return 1; } ret = policydb_read(policydb, pf, 0); if (ret) { fprintf(stderr, "error(s) encountered while parsing configuration\n"); close(fd); munmap(map, sb.st_size); return 1; } return 0; }
/* * To work around denials (on Samsung devices): * 1. Mount the system and data partitions * * $ mount /system * $ mount /data * * 2. Start the audit daemon * * $ /system/bin/auditd * * 3. From another window, run mbtool's update-binary wrapper * * $ /tmp/mbtool_recovery updater 3 1 /path/to/file_patched.zip * * 4. Pull /data/misc/audit/audit.log and run it through audit2allow * * $ adb pull /data/misc/audit/audit.log * $ grep denied audit.log | audit2allow * * 5. Allow the rule using util::selinux_add_rule() * * Rules of the form: * allow source target:class perm; * Are allowed by calling: * util::selinux_add_rule(&pdb, source, target, class, perm); * * -- * * To view the allow rules for the currently loaded policy: * * 1. Pull the current policy file * * $ adb pull /sys/fs/selinux/policy * * 2. View the rules (the -s, -t, -c, and -p parameters can be used to filter * the rules by source, target, class, and permission, respectively) * * $ sesearch -A policy */ bool RecoveryInstaller::patch_sepolicy() { policydb_t pdb; if (policydb_init(&pdb) < 0) { LOGE("Failed to initialize policydb"); return false; } if (!util::selinux_read_policy(SELINUX_POLICY_FILE, &pdb)) { LOGE("Failed to read SELinux policy file: %s", SELINUX_POLICY_FILE); policydb_destroy(&pdb); return false; } LOGD("Policy version: %u", pdb.policyvers); // Debugging rules (for CWM and Philz) util::selinux_add_rule(&pdb, "adbd", "block_device", "blk_file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "graphics_device", "chr_file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "graphics_device", "dir", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "input_device", "chr_file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "input_device", "dir", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "rootfs", "dir", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "rootfs", "file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "rootfs", "lnk_file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "system_file", "file", "relabelto"); util::selinux_add_rule(&pdb, "adbd", "tmpfs", "file", "relabelto"); util::selinux_add_rule(&pdb, "rootfs", "tmpfs", "filesystem", "associate"); util::selinux_add_rule(&pdb, "tmpfs", "rootfs", "filesystem", "associate"); if (!util::selinux_write_policy(SELINUX_LOAD_FILE, &pdb)) { LOGE("Failed to write SELinux policy file: %s", SELINUX_LOAD_FILE); policydb_destroy(&pdb); return false; } policydb_destroy(&pdb); return true; }
int main(int argc, char **argv) { char *file = txtfile, *outfile = NULL; unsigned int binary = 0; int ch; int show_version = 0; policydb_t modpolicydb; struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"output", required_argument, NULL, 'o'}, {"binary", no_argument, NULL, 'b'}, {"version", no_argument, NULL, 'V'}, {"handle-unknown", optional_argument, NULL, 'U'}, {"mls", no_argument, NULL, 'M'}, {NULL, 0, NULL, 0} }; while ((ch = getopt_long(argc, argv, "ho:bVU:mM", long_options, NULL)) != -1) { switch (ch) { case 'h': usage(argv[0]); break; case 'o': outfile = optarg; break; case 'b': binary = 1; file = binfile; break; case 'V': show_version = 1; break; case 'U': if (!strcasecmp(optarg, "deny")) { handle_unknown = DENY_UNKNOWN; break; } if (!strcasecmp(optarg, "reject")) { handle_unknown = REJECT_UNKNOWN; break; } if (!strcasecmp(optarg, "allow")) { handle_unknown = ALLOW_UNKNOWN; break; } usage(argv[0]); case 'm': policy_type = POLICY_MOD; policyvers = MOD_POLICYDB_VERSION_MAX; break; case 'M': mlspol = 1; break; default: usage(argv[0]); } } if (show_version) { printf("Module versions %d-%d\n", MOD_POLICYDB_VERSION_MIN, MOD_POLICYDB_VERSION_MAX); exit(0); } if (handle_unknown && (policy_type != POLICY_BASE)) { printf("Handling of unknown classes and permissions is only "); printf("valid in the base module\n"); exit(1); } if (optind != argc) { file = argv[optind++]; if (optind != argc) usage(argv[0]); } printf("%s: loading policy configuration from %s\n", argv[0], file); /* Set policydb and sidtab used by libsepol service functions to my structures, so that I can directly populate and manipulate them. */ sepol_set_policydb(&modpolicydb); sepol_set_sidtab(&sidtab); if (binary) { if (read_binary_policy(&modpolicydb, file, argv[0]) == -1) { exit(1); } } else { if (policydb_init(&modpolicydb)) { fprintf(stderr, "%s: out of memory!\n", argv[0]); return -1; } modpolicydb.policy_type = policy_type; modpolicydb.mls = mlspol; modpolicydb.handle_unknown = handle_unknown; if (read_source_policy(&modpolicydb, file, argv[0]) == -1) { exit(1); } if (hierarchy_check_constraints(NULL, &modpolicydb)) { return -1; } } if (modpolicydb.policy_type == POLICY_BASE) { /* Verify that we can successfully expand the base module. */ policydb_t kernpolicydb; if (policydb_init(&kernpolicydb)) { fprintf(stderr, "%s: policydb_init failed\n", argv[0]); exit(1); } if (link_modules(NULL, &modpolicydb, NULL, 0, 0)) { fprintf(stderr, "%s: link modules failed\n", argv[0]); exit(1); } if (expand_module(NULL, &modpolicydb, &kernpolicydb, 0, 1)) { fprintf(stderr, "%s: expand module failed\n", argv[0]); exit(1); } policydb_destroy(&kernpolicydb); } if (policydb_load_isids(&modpolicydb, &sidtab)) exit(1); sepol_sidtab_destroy(&sidtab); printf("%s: policy configuration loaded\n", argv[0]); if (outfile && write_binary_policy(&modpolicydb, outfile, argv[0]) == -1) { exit(1); } policydb_destroy(&modpolicydb); return 0; }
static int load_booleans(struct policydb *policydb, const char *path, int *changesp) { FILE *boolf; char *buffer = NULL; size_t size = 0; char localbools[BUFSIZ]; char name[BUFSIZ]; int val; int errors = 0, changes = 0; struct cond_bool_datum *datum; boolf = fopen(path, "r"); if (boolf == NULL) goto localbool; #ifdef DARWIN if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { ERR(NULL, "out of memory"); return -1; } while(fgets(buffer, 255, boolf) != NULL) { #else while (getline(&buffer, &size, boolf) > 0) { #endif int ret = process_boolean(buffer, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) { datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(NULL, "unknown boolean %s", name); errors++; continue; } if (datum->state != val) { datum->state = val; changes++; } } } fclose(boolf); localbool: snprintf(localbools, sizeof(localbools), "%s.local", path); boolf = fopen(localbools, "r"); if (boolf != NULL) { #ifdef DARWIN while(fgets(buffer, 255, boolf) != NULL) { #else while (getline(&buffer, &size, boolf) > 0) { #endif int ret = process_boolean(buffer, name, sizeof(name), &val); if (ret == -1) errors++; if (ret == 1) { datum = hashtab_search(policydb->p_bools.table, name); if (!datum) { ERR(NULL, "unknown boolean %s", name); errors++; continue; } if (datum->state != val) { datum->state = val; changes++; } } } fclose(boolf); } free(buffer); if (errors) errno = EINVAL; *changesp = changes; return errors ? -1 : 0; } int sepol_genbools(void *data, size_t len, char *booleans) { struct policydb policydb; struct policy_file pf; int rc, changes = 0; if (policydb_init(&policydb)) goto err; if (policydb_from_image(NULL, data, len, &policydb) < 0) goto err; if (load_booleans(&policydb, booleans, &changes) < 0) { WARN(NULL, "error while reading %s", booleans); } if (!changes) goto out; if (evaluate_conds(&policydb) < 0) { ERR(NULL, "error while re-evaluating conditionals"); errno = EINVAL; goto err_destroy; } policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; rc = policydb_write(&policydb, &pf); if (rc) { ERR(NULL, "unable to write new binary policy image"); errno = EINVAL; goto err_destroy; } out: policydb_destroy(&policydb); return 0; err_destroy: policydb_destroy(&policydb); err: return -1; } int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans) { int rc, changes = 0; rc = load_booleans(policydb, booleans, &changes); if (!rc && changes) rc = evaluate_conds(policydb); if (rc) errno = EINVAL; return rc; } /* -- End Deprecated -- */ int sepol_genbools_array(void *data, size_t len, char **names, int *values, int nel) { struct policydb policydb; struct policy_file pf; int rc, i, errors = 0; struct cond_bool_datum *datum; /* Create policy database from image */ if (policydb_init(&policydb)) goto err; if (policydb_from_image(NULL, data, len, &policydb) < 0) goto err; for (i = 0; i < nel; i++) { datum = hashtab_search(policydb.p_bools.table, names[i]); if (!datum) { ERR(NULL, "boolean %s no longer in policy", names[i]); errors++; continue; } if (values[i] != 0 && values[i] != 1) { ERR(NULL, "illegal value %d for boolean %s", values[i], names[i]); errors++; continue; } datum->state = values[i]; } if (evaluate_conds(&policydb) < 0) { ERR(NULL, "error while re-evaluating conditionals"); errno = EINVAL; goto err_destroy; } policy_file_init(&pf); pf.type = PF_USE_MEMORY; pf.data = data; pf.len = len; rc = policydb_write(&policydb, &pf); if (rc) { ERR(NULL, "unable to write binary policy"); errno = EINVAL; goto err_destroy; } if (errors) { errno = EINVAL; goto err_destroy; } policydb_destroy(&policydb); return 0; err_destroy: policydb_destroy(&policydb); err: return -1; }