1255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdio.h> 2255e72915d4cbddceb435e13d81601755714e9fSE Android#include <stdlib.h> 3255e72915d4cbddceb435e13d81601755714e9fSE Android#include <ctype.h> 4255e72915d4cbddceb435e13d81601755714e9fSE Android#include <errno.h> 5255e72915d4cbddceb435e13d81601755714e9fSE Android 6255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/policydb.h> 7255e72915d4cbddceb435e13d81601755714e9fSE Android#include <sepol/policydb/conditional.h> 8255e72915d4cbddceb435e13d81601755714e9fSE Android 9255e72915d4cbddceb435e13d81601755714e9fSE Android#include "debug.h" 10255e72915d4cbddceb435e13d81601755714e9fSE Android#include "private.h" 11255e72915d4cbddceb435e13d81601755714e9fSE Android#include "dso.h" 12255e72915d4cbddceb435e13d81601755714e9fSE Android 13255e72915d4cbddceb435e13d81601755714e9fSE Android/* -- Deprecated -- */ 14255e72915d4cbddceb435e13d81601755714e9fSE Android 15255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic char *strtrim(char *dest, char *source, int size) 16255e72915d4cbddceb435e13d81601755714e9fSE Android{ 17255e72915d4cbddceb435e13d81601755714e9fSE Android int i = 0; 18255e72915d4cbddceb435e13d81601755714e9fSE Android char *ptr = source; 19255e72915d4cbddceb435e13d81601755714e9fSE Android i = 0; 20255e72915d4cbddceb435e13d81601755714e9fSE Android while (isspace(*ptr) && i < size) { 21255e72915d4cbddceb435e13d81601755714e9fSE Android ptr++; 22255e72915d4cbddceb435e13d81601755714e9fSE Android i++; 23255e72915d4cbddceb435e13d81601755714e9fSE Android } 24255e72915d4cbddceb435e13d81601755714e9fSE Android strncpy(dest, ptr, size); 25255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = strlen(dest) - 1; i > 0; i--) { 26255e72915d4cbddceb435e13d81601755714e9fSE Android if (!isspace(dest[i])) 27255e72915d4cbddceb435e13d81601755714e9fSE Android break; 28255e72915d4cbddceb435e13d81601755714e9fSE Android } 29255e72915d4cbddceb435e13d81601755714e9fSE Android dest[i + 1] = '\0'; 30255e72915d4cbddceb435e13d81601755714e9fSE Android return dest; 31255e72915d4cbddceb435e13d81601755714e9fSE Android} 32255e72915d4cbddceb435e13d81601755714e9fSE Android 33255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int process_boolean(char *buffer, char *name, int namesize, int *val) 34255e72915d4cbddceb435e13d81601755714e9fSE Android{ 35255e72915d4cbddceb435e13d81601755714e9fSE Android char name1[BUFSIZ]; 36dedcd596b31e0e4fc15d75b3a8b5e6b61e6c28b3Stephen Smalley char *ptr = NULL; 37255e72915d4cbddceb435e13d81601755714e9fSE Android char *tok = strtok_r(buffer, "=", &ptr); 38255e72915d4cbddceb435e13d81601755714e9fSE Android if (tok) { 39255e72915d4cbddceb435e13d81601755714e9fSE Android strncpy(name1, tok, BUFSIZ - 1); 40255e72915d4cbddceb435e13d81601755714e9fSE Android strtrim(name, name1, namesize - 1); 41255e72915d4cbddceb435e13d81601755714e9fSE Android if (name[0] == '#') 42255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 43255e72915d4cbddceb435e13d81601755714e9fSE Android tok = strtok_r(NULL, "\0", &ptr); 44255e72915d4cbddceb435e13d81601755714e9fSE Android if (tok) { 45255e72915d4cbddceb435e13d81601755714e9fSE Android while (isspace(*tok)) 46255e72915d4cbddceb435e13d81601755714e9fSE Android tok++; 47255e72915d4cbddceb435e13d81601755714e9fSE Android *val = -1; 48255e72915d4cbddceb435e13d81601755714e9fSE Android if (isdigit(tok[0])) 49255e72915d4cbddceb435e13d81601755714e9fSE Android *val = atoi(tok); 50255e72915d4cbddceb435e13d81601755714e9fSE Android else if (!strncasecmp(tok, "true", sizeof("true") - 1)) 51255e72915d4cbddceb435e13d81601755714e9fSE Android *val = 1; 52255e72915d4cbddceb435e13d81601755714e9fSE Android else if (!strncasecmp 53255e72915d4cbddceb435e13d81601755714e9fSE Android (tok, "false", sizeof("false") - 1)) 54255e72915d4cbddceb435e13d81601755714e9fSE Android *val = 0; 55255e72915d4cbddceb435e13d81601755714e9fSE Android if (*val != 0 && *val != 1) { 56255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "illegal value for boolean " 57255e72915d4cbddceb435e13d81601755714e9fSE Android "%s=%s", name, tok); 58255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 59255e72915d4cbddceb435e13d81601755714e9fSE Android } 60255e72915d4cbddceb435e13d81601755714e9fSE Android 61255e72915d4cbddceb435e13d81601755714e9fSE Android } 62255e72915d4cbddceb435e13d81601755714e9fSE Android } 63255e72915d4cbddceb435e13d81601755714e9fSE Android return 1; 64255e72915d4cbddceb435e13d81601755714e9fSE Android} 65255e72915d4cbddceb435e13d81601755714e9fSE Android 66255e72915d4cbddceb435e13d81601755714e9fSE Androidstatic int load_booleans(struct policydb *policydb, const char *path, 67255e72915d4cbddceb435e13d81601755714e9fSE Android int *changesp) 68255e72915d4cbddceb435e13d81601755714e9fSE Android{ 69255e72915d4cbddceb435e13d81601755714e9fSE Android FILE *boolf; 70255e72915d4cbddceb435e13d81601755714e9fSE Android char *buffer = NULL; 71255e72915d4cbddceb435e13d81601755714e9fSE Android size_t size = 0; 72255e72915d4cbddceb435e13d81601755714e9fSE Android char localbools[BUFSIZ]; 73255e72915d4cbddceb435e13d81601755714e9fSE Android char name[BUFSIZ]; 74255e72915d4cbddceb435e13d81601755714e9fSE Android int val; 75255e72915d4cbddceb435e13d81601755714e9fSE Android int errors = 0, changes = 0; 76255e72915d4cbddceb435e13d81601755714e9fSE Android struct cond_bool_datum *datum; 77255e72915d4cbddceb435e13d81601755714e9fSE Android 78255e72915d4cbddceb435e13d81601755714e9fSE Android boolf = fopen(path, "r"); 79255e72915d4cbddceb435e13d81601755714e9fSE Android if (boolf == NULL) 80255e72915d4cbddceb435e13d81601755714e9fSE Android goto localbool; 81255e72915d4cbddceb435e13d81601755714e9fSE Android 82b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#ifdef DARWIN 83b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { 84b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley ERR(NULL, "out of memory"); 85b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley return -1; 86b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley } 87b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley 88b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley while(fgets(buffer, 255, boolf) != NULL) { 89b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#else 90255e72915d4cbddceb435e13d81601755714e9fSE Android while (getline(&buffer, &size, boolf) > 0) { 91b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#endif 92255e72915d4cbddceb435e13d81601755714e9fSE Android int ret = process_boolean(buffer, name, sizeof(name), &val); 93255e72915d4cbddceb435e13d81601755714e9fSE Android if (ret == -1) 94255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 95255e72915d4cbddceb435e13d81601755714e9fSE Android if (ret == 1) { 96255e72915d4cbddceb435e13d81601755714e9fSE Android datum = hashtab_search(policydb->p_bools.table, name); 97255e72915d4cbddceb435e13d81601755714e9fSE Android if (!datum) { 98255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "unknown boolean %s", name); 99255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 100255e72915d4cbddceb435e13d81601755714e9fSE Android continue; 101255e72915d4cbddceb435e13d81601755714e9fSE Android } 102255e72915d4cbddceb435e13d81601755714e9fSE Android if (datum->state != val) { 103255e72915d4cbddceb435e13d81601755714e9fSE Android datum->state = val; 104255e72915d4cbddceb435e13d81601755714e9fSE Android changes++; 105255e72915d4cbddceb435e13d81601755714e9fSE Android } 106255e72915d4cbddceb435e13d81601755714e9fSE Android } 107255e72915d4cbddceb435e13d81601755714e9fSE Android } 108255e72915d4cbddceb435e13d81601755714e9fSE Android fclose(boolf); 109255e72915d4cbddceb435e13d81601755714e9fSE Android localbool: 110255e72915d4cbddceb435e13d81601755714e9fSE Android snprintf(localbools, sizeof(localbools), "%s.local", path); 111255e72915d4cbddceb435e13d81601755714e9fSE Android boolf = fopen(localbools, "r"); 112255e72915d4cbddceb435e13d81601755714e9fSE Android if (boolf != NULL) { 113b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley 114b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#ifdef DARWIN 115b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley 116b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley while(fgets(buffer, 255, boolf) != NULL) { 117b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#else 118b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley 119b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley while (getline(&buffer, &size, boolf) > 0) { 120b1db49d77789525ac1f4e73e978e35694f21ea1aStephen Smalley#endif 121255e72915d4cbddceb435e13d81601755714e9fSE Android int ret = 122255e72915d4cbddceb435e13d81601755714e9fSE Android process_boolean(buffer, name, sizeof(name), &val); 123255e72915d4cbddceb435e13d81601755714e9fSE Android if (ret == -1) 124255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 125255e72915d4cbddceb435e13d81601755714e9fSE Android if (ret == 1) { 126255e72915d4cbddceb435e13d81601755714e9fSE Android datum = 127255e72915d4cbddceb435e13d81601755714e9fSE Android hashtab_search(policydb->p_bools.table, 128255e72915d4cbddceb435e13d81601755714e9fSE Android name); 129255e72915d4cbddceb435e13d81601755714e9fSE Android if (!datum) { 130255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "unknown boolean %s", name); 131255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 132255e72915d4cbddceb435e13d81601755714e9fSE Android continue; 133255e72915d4cbddceb435e13d81601755714e9fSE Android } 134255e72915d4cbddceb435e13d81601755714e9fSE Android if (datum->state != val) { 135255e72915d4cbddceb435e13d81601755714e9fSE Android datum->state = val; 136255e72915d4cbddceb435e13d81601755714e9fSE Android changes++; 137255e72915d4cbddceb435e13d81601755714e9fSE Android } 138255e72915d4cbddceb435e13d81601755714e9fSE Android } 139255e72915d4cbddceb435e13d81601755714e9fSE Android } 140255e72915d4cbddceb435e13d81601755714e9fSE Android fclose(boolf); 141255e72915d4cbddceb435e13d81601755714e9fSE Android } 142255e72915d4cbddceb435e13d81601755714e9fSE Android free(buffer); 143255e72915d4cbddceb435e13d81601755714e9fSE Android if (errors) 144255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 145255e72915d4cbddceb435e13d81601755714e9fSE Android *changesp = changes; 146255e72915d4cbddceb435e13d81601755714e9fSE Android return errors ? -1 : 0; 147255e72915d4cbddceb435e13d81601755714e9fSE Android} 148255e72915d4cbddceb435e13d81601755714e9fSE Android 149255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_genbools(void *data, size_t len, char *booleans) 150255e72915d4cbddceb435e13d81601755714e9fSE Android{ 151255e72915d4cbddceb435e13d81601755714e9fSE Android struct policydb policydb; 152255e72915d4cbddceb435e13d81601755714e9fSE Android struct policy_file pf; 153255e72915d4cbddceb435e13d81601755714e9fSE Android int rc, changes = 0; 154255e72915d4cbddceb435e13d81601755714e9fSE Android 155255e72915d4cbddceb435e13d81601755714e9fSE Android if (policydb_init(&policydb)) 156255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 157255e72915d4cbddceb435e13d81601755714e9fSE Android if (policydb_from_image(NULL, data, len, &policydb) < 0) 158255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 159255e72915d4cbddceb435e13d81601755714e9fSE Android 160255e72915d4cbddceb435e13d81601755714e9fSE Android if (load_booleans(&policydb, booleans, &changes) < 0) { 161255e72915d4cbddceb435e13d81601755714e9fSE Android WARN(NULL, "error while reading %s", booleans); 162255e72915d4cbddceb435e13d81601755714e9fSE Android } 163255e72915d4cbddceb435e13d81601755714e9fSE Android 164255e72915d4cbddceb435e13d81601755714e9fSE Android if (!changes) 165255e72915d4cbddceb435e13d81601755714e9fSE Android goto out; 166255e72915d4cbddceb435e13d81601755714e9fSE Android 167255e72915d4cbddceb435e13d81601755714e9fSE Android if (evaluate_conds(&policydb) < 0) { 168255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "error while re-evaluating conditionals"); 169255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 170255e72915d4cbddceb435e13d81601755714e9fSE Android goto err_destroy; 171255e72915d4cbddceb435e13d81601755714e9fSE Android } 172255e72915d4cbddceb435e13d81601755714e9fSE Android 173255e72915d4cbddceb435e13d81601755714e9fSE Android policy_file_init(&pf); 174255e72915d4cbddceb435e13d81601755714e9fSE Android pf.type = PF_USE_MEMORY; 175255e72915d4cbddceb435e13d81601755714e9fSE Android pf.data = data; 176255e72915d4cbddceb435e13d81601755714e9fSE Android pf.len = len; 177255e72915d4cbddceb435e13d81601755714e9fSE Android rc = policydb_write(&policydb, &pf); 178255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc) { 179255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "unable to write new binary policy image"); 180255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 181255e72915d4cbddceb435e13d81601755714e9fSE Android goto err_destroy; 182255e72915d4cbddceb435e13d81601755714e9fSE Android } 183255e72915d4cbddceb435e13d81601755714e9fSE Android 184255e72915d4cbddceb435e13d81601755714e9fSE Android out: 185255e72915d4cbddceb435e13d81601755714e9fSE Android policydb_destroy(&policydb); 186255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 187255e72915d4cbddceb435e13d81601755714e9fSE Android 188255e72915d4cbddceb435e13d81601755714e9fSE Android err_destroy: 189255e72915d4cbddceb435e13d81601755714e9fSE Android policydb_destroy(&policydb); 190255e72915d4cbddceb435e13d81601755714e9fSE Android 191255e72915d4cbddceb435e13d81601755714e9fSE Android err: 192255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 193255e72915d4cbddceb435e13d81601755714e9fSE Android} 194255e72915d4cbddceb435e13d81601755714e9fSE Android 195255e72915d4cbddceb435e13d81601755714e9fSE Androidint hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans) 196255e72915d4cbddceb435e13d81601755714e9fSE Android{ 197255e72915d4cbddceb435e13d81601755714e9fSE Android int rc, changes = 0; 198255e72915d4cbddceb435e13d81601755714e9fSE Android 199255e72915d4cbddceb435e13d81601755714e9fSE Android rc = load_booleans(policydb, booleans, &changes); 200255e72915d4cbddceb435e13d81601755714e9fSE Android if (!rc && changes) 201255e72915d4cbddceb435e13d81601755714e9fSE Android rc = evaluate_conds(policydb); 202255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc) 203255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 204255e72915d4cbddceb435e13d81601755714e9fSE Android return rc; 205255e72915d4cbddceb435e13d81601755714e9fSE Android} 206255e72915d4cbddceb435e13d81601755714e9fSE Android 207255e72915d4cbddceb435e13d81601755714e9fSE Android/* -- End Deprecated -- */ 208255e72915d4cbddceb435e13d81601755714e9fSE Android 209255e72915d4cbddceb435e13d81601755714e9fSE Androidint sepol_genbools_array(void *data, size_t len, char **names, int *values, 210255e72915d4cbddceb435e13d81601755714e9fSE Android int nel) 211255e72915d4cbddceb435e13d81601755714e9fSE Android{ 212255e72915d4cbddceb435e13d81601755714e9fSE Android struct policydb policydb; 213255e72915d4cbddceb435e13d81601755714e9fSE Android struct policy_file pf; 214255e72915d4cbddceb435e13d81601755714e9fSE Android int rc, i, errors = 0; 215255e72915d4cbddceb435e13d81601755714e9fSE Android struct cond_bool_datum *datum; 216255e72915d4cbddceb435e13d81601755714e9fSE Android 217255e72915d4cbddceb435e13d81601755714e9fSE Android /* Create policy database from image */ 218255e72915d4cbddceb435e13d81601755714e9fSE Android if (policydb_init(&policydb)) 219255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 220255e72915d4cbddceb435e13d81601755714e9fSE Android if (policydb_from_image(NULL, data, len, &policydb) < 0) 221255e72915d4cbddceb435e13d81601755714e9fSE Android goto err; 222255e72915d4cbddceb435e13d81601755714e9fSE Android 223255e72915d4cbddceb435e13d81601755714e9fSE Android for (i = 0; i < nel; i++) { 224255e72915d4cbddceb435e13d81601755714e9fSE Android datum = hashtab_search(policydb.p_bools.table, names[i]); 225255e72915d4cbddceb435e13d81601755714e9fSE Android if (!datum) { 226255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "boolean %s no longer in policy", names[i]); 227255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 228255e72915d4cbddceb435e13d81601755714e9fSE Android continue; 229255e72915d4cbddceb435e13d81601755714e9fSE Android } 230255e72915d4cbddceb435e13d81601755714e9fSE Android if (values[i] != 0 && values[i] != 1) { 231255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "illegal value %d for boolean %s", 232255e72915d4cbddceb435e13d81601755714e9fSE Android values[i], names[i]); 233255e72915d4cbddceb435e13d81601755714e9fSE Android errors++; 234255e72915d4cbddceb435e13d81601755714e9fSE Android continue; 235255e72915d4cbddceb435e13d81601755714e9fSE Android } 236255e72915d4cbddceb435e13d81601755714e9fSE Android datum->state = values[i]; 237255e72915d4cbddceb435e13d81601755714e9fSE Android } 238255e72915d4cbddceb435e13d81601755714e9fSE Android 239255e72915d4cbddceb435e13d81601755714e9fSE Android if (evaluate_conds(&policydb) < 0) { 240255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "error while re-evaluating conditionals"); 241255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 242255e72915d4cbddceb435e13d81601755714e9fSE Android goto err_destroy; 243255e72915d4cbddceb435e13d81601755714e9fSE Android } 244255e72915d4cbddceb435e13d81601755714e9fSE Android 245255e72915d4cbddceb435e13d81601755714e9fSE Android policy_file_init(&pf); 246255e72915d4cbddceb435e13d81601755714e9fSE Android pf.type = PF_USE_MEMORY; 247255e72915d4cbddceb435e13d81601755714e9fSE Android pf.data = data; 248255e72915d4cbddceb435e13d81601755714e9fSE Android pf.len = len; 249255e72915d4cbddceb435e13d81601755714e9fSE Android rc = policydb_write(&policydb, &pf); 250255e72915d4cbddceb435e13d81601755714e9fSE Android if (rc) { 251255e72915d4cbddceb435e13d81601755714e9fSE Android ERR(NULL, "unable to write binary policy"); 252255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 253255e72915d4cbddceb435e13d81601755714e9fSE Android goto err_destroy; 254255e72915d4cbddceb435e13d81601755714e9fSE Android } 255255e72915d4cbddceb435e13d81601755714e9fSE Android if (errors) { 256255e72915d4cbddceb435e13d81601755714e9fSE Android errno = EINVAL; 257255e72915d4cbddceb435e13d81601755714e9fSE Android goto err_destroy; 258255e72915d4cbddceb435e13d81601755714e9fSE Android } 259255e72915d4cbddceb435e13d81601755714e9fSE Android 260255e72915d4cbddceb435e13d81601755714e9fSE Android policydb_destroy(&policydb); 261255e72915d4cbddceb435e13d81601755714e9fSE Android return 0; 262255e72915d4cbddceb435e13d81601755714e9fSE Android 263255e72915d4cbddceb435e13d81601755714e9fSE Android err_destroy: 264255e72915d4cbddceb435e13d81601755714e9fSE Android policydb_destroy(&policydb); 265255e72915d4cbddceb435e13d81601755714e9fSE Android 266255e72915d4cbddceb435e13d81601755714e9fSE Android err: 267255e72915d4cbddceb435e13d81601755714e9fSE Android return -1; 268255e72915d4cbddceb435e13d81601755714e9fSE Android} 269