diff options
Diffstat (limited to 'src/genbools.c')
-rw-r--r-- | src/genbools.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/src/genbools.c b/src/genbools.c new file mode 100644 index 0000000..e353ef3 --- /dev/null +++ b/src/genbools.c @@ -0,0 +1,252 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <errno.h> + +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/conditional.h> + +#include "debug.h" +#include "private.h" +#include "dso.h" + +/* -- Deprecated -- */ + +static char *strtrim(char *dest, char *source, int size) +{ + int i = 0; + char *ptr = source; + i = 0; + while (isspace(*ptr) && i < size) { + ptr++; + i++; + } + strncpy(dest, ptr, size); + for (i = strlen(dest) - 1; i > 0; i--) { + if (!isspace(dest[i])) + break; + } + dest[i + 1] = '\0'; + return dest; +} + +static int process_boolean(char *buffer, char *name, int namesize, int *val) +{ + char name1[BUFSIZ]; + char *ptr; + char *tok = strtok_r(buffer, "=", &ptr); + if (tok) { + strncpy(name1, tok, BUFSIZ - 1); + strtrim(name, name1, namesize - 1); + if (name[0] == '#') + return 0; + tok = strtok_r(NULL, "\0", &ptr); + if (tok) { + while (isspace(*tok)) + tok++; + *val = -1; + if (isdigit(tok[0])) + *val = atoi(tok); + else if (!strncasecmp(tok, "true", sizeof("true") - 1)) + *val = 1; + else if (!strncasecmp + (tok, "false", sizeof("false") - 1)) + *val = 0; + if (*val != 0 && *val != 1) { + ERR(NULL, "illegal value for boolean " + "%s=%s", name, tok); + return -1; + } + + } + } + return 1; +} + +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; + + while (getline(&buffer, &size, boolf) > 0) { + 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) { + while (getline(&buffer, &size, boolf) > 0) { + 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; +} |