static int write_binary_policy(policydb_t * p, char *file, char *progname) { FILE *outfp = NULL; struct policy_file pf; int ret; printf("%s: writing binary representation (version %d) to %s\n", progname, policyvers, file); outfp = fopen(file, "w"); if (!outfp) { perror(file); exit(1); } p->policy_type = policy_type; p->policyvers = policyvers; p->handle_unknown = handle_unknown; policy_file_init(&pf); pf.type = PF_USE_STDIO; pf.fp = outfp; ret = policydb_write(p, &pf); if (ret) { fprintf(stderr, "%s: error writing %s\n", progname, file); return -1; } fclose(outfp); 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); }
int main_seinject(int argc, char **argv) { char *policy = NULL, *source = NULL, *target = NULL, *clazz = NULL, *perm = NULL, *perm_token = NULL, *perm_saveptr = NULL, *outfile = NULL, *permissive = NULL; policydb_t policydb; struct policy_file pf, outpf; sidtab_t sidtab; int ret_add_rule; int load = 0; int quiet = 0; FILE *fp; int i; for (i=1; i<argc; i++) { if (argv[i][0] == '-') { if (argv[i][1] == 's') { i++; source = argv[i]; continue; } if (argv[i][1] == 't') { i++; target = argv[i]; continue; } if (argv[i][1] == 'c') { i++; clazz = argv[i]; continue; } if (argv[i][1] == 'p') { i++; perm = argv[i]; continue; } if (argv[i][1] == 'P') { i++; policy = argv[i]; continue; } if (argv[i][1] == 'o') { i++; outfile = argv[i]; continue; } if (argv[i][1] == 'Z') { i++; permissive = argv[i]; continue; } if (argv[i][1] == 'l') { load = 1; continue; } if (argv[i][1] == 'q') { quiet = 1; continue; } break; } } if (i < argc || argc == 1 || ((!source || !target || !clazz || !perm) && !permissive)) { fprintf(stderr, "%s -s <source type> -t <target type> -c <class> -p <perm>[,<perm2>,<perm3>,...] [-P <policy file>] [-o <output file>] [-l|--load]\n", argv[0]); fprintf(stderr, "%s -Z permissive_type [-P <policy file>] [-o <output file>] [-l|--load]\n", argv[0]); exit(1); } if (!policy) policy = "/sys/fs/selinux/policy"; sepol_set_policydb(&policydb); sepol_set_sidtab(&sidtab); if (load_policy(policy, &policydb, &pf)) { fprintf(stderr, "Could not load policy\n"); return 1; } if (policydb_load_isids(&policydb, &sidtab)) return 1; if (permissive) { type_datum_t *type; type = hashtab_search(policydb.p_types.table, permissive); if (type == NULL) { fprintf(stderr, "type %s does not exist\n", permissive); return 2; } if (ebitmap_set_bit(&policydb.permissive_map, type->s.value, 1)) { fprintf(stderr, "Could not set bit in permissive map\n"); return 1; } } else { perm_token = strtok_r(perm, ",", &perm_saveptr); while (perm_token) { ret_add_rule = add_rule(source, target, clazz, perm_token, &policydb); if (ret_add_rule) { fprintf(stderr, "Could not add rule for perm: %s\n", perm_token); return ret_add_rule; } perm_token = strtok_r(NULL, ",", &perm_saveptr); } } if (outfile) { fp = fopen(outfile, "wb"); if (!fp) { fprintf(stderr, "Could not open outfile\n"); return 1; } policy_file_init(&outpf); outpf.type = PF_USE_STDIO; outpf.fp = fp; if (policydb_write(&policydb, &outpf)) { fprintf(stderr, "Could not write policy\n"); return 1; } fclose(fp); } if (load) { if (load_policy_into_kernel(&policydb)) { fprintf(stderr, "Could not load new policy into kernel\n"); return 1; } } policydb_destroy(&policydb); if (quiet == 0) fprintf(stdout, "Success\n"); 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; }
int sepol_module_package_write(sepol_module_package_t *p, struct sepol_policy_file *spf) { struct policy_file *file = &spf->pf; policy_file_t polfile; uint32_t buf[5], offsets[5], len, nsec = 0; int i; if (p->policy) { /* compute policy length */ polfile.type = PF_LEN; polfile.data = NULL; polfile.len = 0; polfile.handle = file->handle; if (policydb_write(&p->policy->p, &polfile)) return -1; len = polfile.len; if (!polfile.len) return -1; nsec++; } else { /* We don't support writing a package without a module at this point */ return -1; } /* seusers and user_extra only supported in base at the moment */ if ((p->seusers || p->user_extra) && (p->policy->p.policy_type != SEPOL_POLICY_BASE)) { ERR(file->handle, "seuser and user_extra sections only supported in base"); return -1; } if (p->file_contexts) nsec++; if (p->seusers) nsec++; if (p->user_extra) nsec++; buf[0] = cpu_to_le32(SEPOL_MODULE_PACKAGE_MAGIC); buf[1] = cpu_to_le32(p->version); buf[2] = cpu_to_le32(nsec); if (put_entry(buf, sizeof(uint32_t), 3, file) != 3) return -1; /* calculate offsets */ offsets[0] = (nsec + 3) * sizeof(uint32_t); buf[0] = cpu_to_le32(offsets[0]); i = 1; if (p->file_contexts) { offsets[i] = offsets[i-1] + len; buf[i] = cpu_to_le32(offsets[i]); /* add a uint32_t to compensate for the magic number */ len = p->file_contexts_len + sizeof(uint32_t); i++; } if (p->seusers) { offsets[i] = offsets[i-1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->seusers_len + sizeof(uint32_t); i++; } if (p->user_extra) { offsets[i] = offsets[i-1] + len; buf[i] = cpu_to_le32(offsets[i]); len = p->user_extra_len + sizeof(uint32_t); i++; } if (put_entry(buf, sizeof(uint32_t), nsec, file) != nsec) return -1; /* write sections */ if (policydb_write(&p->policy->p, file)) return -1; if (p->file_contexts) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_FC); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->file_contexts, p->file_contexts_len, file)) return -1; } if (p->seusers) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_SEUSER); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->seusers, p->seusers_len, file)) return -1; } if (p->user_extra) { buf[0] = cpu_to_le32(SEPOL_PACKAGE_SECTION_USER_EXTRA); if (put_entry(buf, sizeof(uint32_t), 1, file) != 1) return -1; if (write_helper(p->user_extra, p->user_extra_len, file)) return -1; } return 0; }