1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <ctype.h> 4 #include <errno.h> 5 6 #include <sepol/policydb/policydb.h> 7 #include <sepol/policydb/conditional.h> 8 9 #include "debug.h" 10 #include "private.h" 11 #include "dso.h" 12 13 /* -- Deprecated -- */ 14 15 static char *strtrim(char *dest, char *source, int size) 16 { 17 int i = 0; 18 char *ptr = source; 19 i = 0; 20 while (isspace(*ptr) && i < size) { 21 ptr++; 22 i++; 23 } 24 strncpy(dest, ptr, size); 25 for (i = strlen(dest) - 1; i > 0; i--) { 26 if (!isspace(dest[i])) 27 break; 28 } 29 dest[i + 1] = '\0'; 30 return dest; 31 } 32 33 static int process_boolean(char *buffer, char *name, int namesize, int *val) 34 { 35 char name1[BUFSIZ]; 36 char *ptr; 37 char *tok = strtok_r(buffer, "=", &ptr); 38 if (tok) { 39 strncpy(name1, tok, BUFSIZ - 1); 40 strtrim(name, name1, namesize - 1); 41 if (name[0] == '#') 42 return 0; 43 tok = strtok_r(NULL, "\0", &ptr); 44 if (tok) { 45 while (isspace(*tok)) 46 tok++; 47 *val = -1; 48 if (isdigit(tok[0])) 49 *val = atoi(tok); 50 else if (!strncasecmp(tok, "true", sizeof("true") - 1)) 51 *val = 1; 52 else if (!strncasecmp 53 (tok, "false", sizeof("false") - 1)) 54 *val = 0; 55 if (*val != 0 && *val != 1) { 56 ERR(NULL, "illegal value for boolean " 57 "%s=%s", name, tok); 58 return -1; 59 } 60 61 } 62 } 63 return 1; 64 } 65 66 static int load_booleans(struct policydb *policydb, const char *path, 67 int *changesp) 68 { 69 FILE *boolf; 70 char *buffer = NULL; 71 size_t size = 0; 72 char localbools[BUFSIZ]; 73 char name[BUFSIZ]; 74 int val; 75 int errors = 0, changes = 0; 76 struct cond_bool_datum *datum; 77 78 boolf = fopen(path, "r"); 79 if (boolf == NULL) 80 goto localbool; 81 82 #ifdef DARWIN 83 if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) { 84 ERR(NULL, "out of memory"); 85 return -1; 86 } 87 88 while(fgets(buffer, 255, boolf) != NULL) { 89 #else 90 while (getline(&buffer, &size, boolf) > 0) { 91 #endif 92 int ret = process_boolean(buffer, name, sizeof(name), &val); 93 if (ret == -1) 94 errors++; 95 if (ret == 1) { 96 datum = hashtab_search(policydb->p_bools.table, name); 97 if (!datum) { 98 ERR(NULL, "unknown boolean %s", name); 99 errors++; 100 continue; 101 } 102 if (datum->state != val) { 103 datum->state = val; 104 changes++; 105 } 106 } 107 } 108 fclose(boolf); 109 localbool: 110 snprintf(localbools, sizeof(localbools), "%s.local", path); 111 boolf = fopen(localbools, "r"); 112 if (boolf != NULL) { 113 114 #ifdef DARWIN 115 116 while(fgets(buffer, 255, boolf) != NULL) { 117 #else 118 119 while (getline(&buffer, &size, boolf) > 0) { 120 #endif 121 int ret = 122 process_boolean(buffer, name, sizeof(name), &val); 123 if (ret == -1) 124 errors++; 125 if (ret == 1) { 126 datum = 127 hashtab_search(policydb->p_bools.table, 128 name); 129 if (!datum) { 130 ERR(NULL, "unknown boolean %s", name); 131 errors++; 132 continue; 133 } 134 if (datum->state != val) { 135 datum->state = val; 136 changes++; 137 } 138 } 139 } 140 fclose(boolf); 141 } 142 free(buffer); 143 if (errors) 144 errno = EINVAL; 145 *changesp = changes; 146 return errors ? -1 : 0; 147 } 148 149 int sepol_genbools(void *data, size_t len, char *booleans) 150 { 151 struct policydb policydb; 152 struct policy_file pf; 153 int rc, changes = 0; 154 155 if (policydb_init(&policydb)) 156 goto err; 157 if (policydb_from_image(NULL, data, len, &policydb) < 0) 158 goto err; 159 160 if (load_booleans(&policydb, booleans, &changes) < 0) { 161 WARN(NULL, "error while reading %s", booleans); 162 } 163 164 if (!changes) 165 goto out; 166 167 if (evaluate_conds(&policydb) < 0) { 168 ERR(NULL, "error while re-evaluating conditionals"); 169 errno = EINVAL; 170 goto err_destroy; 171 } 172 173 policy_file_init(&pf); 174 pf.type = PF_USE_MEMORY; 175 pf.data = data; 176 pf.len = len; 177 rc = policydb_write(&policydb, &pf); 178 if (rc) { 179 ERR(NULL, "unable to write new binary policy image"); 180 errno = EINVAL; 181 goto err_destroy; 182 } 183 184 out: 185 policydb_destroy(&policydb); 186 return 0; 187 188 err_destroy: 189 policydb_destroy(&policydb); 190 191 err: 192 return -1; 193 } 194 195 int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans) 196 { 197 int rc, changes = 0; 198 199 rc = load_booleans(policydb, booleans, &changes); 200 if (!rc && changes) 201 rc = evaluate_conds(policydb); 202 if (rc) 203 errno = EINVAL; 204 return rc; 205 } 206 207 /* -- End Deprecated -- */ 208 209 int sepol_genbools_array(void *data, size_t len, char **names, int *values, 210 int nel) 211 { 212 struct policydb policydb; 213 struct policy_file pf; 214 int rc, i, errors = 0; 215 struct cond_bool_datum *datum; 216 217 /* Create policy database from image */ 218 if (policydb_init(&policydb)) 219 goto err; 220 if (policydb_from_image(NULL, data, len, &policydb) < 0) 221 goto err; 222 223 for (i = 0; i < nel; i++) { 224 datum = hashtab_search(policydb.p_bools.table, names[i]); 225 if (!datum) { 226 ERR(NULL, "boolean %s no longer in policy", names[i]); 227 errors++; 228 continue; 229 } 230 if (values[i] != 0 && values[i] != 1) { 231 ERR(NULL, "illegal value %d for boolean %s", 232 values[i], names[i]); 233 errors++; 234 continue; 235 } 236 datum->state = values[i]; 237 } 238 239 if (evaluate_conds(&policydb) < 0) { 240 ERR(NULL, "error while re-evaluating conditionals"); 241 errno = EINVAL; 242 goto err_destroy; 243 } 244 245 policy_file_init(&pf); 246 pf.type = PF_USE_MEMORY; 247 pf.data = data; 248 pf.len = len; 249 rc = policydb_write(&policydb, &pf); 250 if (rc) { 251 ERR(NULL, "unable to write binary policy"); 252 errno = EINVAL; 253 goto err_destroy; 254 } 255 if (errors) { 256 errno = EINVAL; 257 goto err_destroy; 258 } 259 260 policydb_destroy(&policydb); 261 return 0; 262 263 err_destroy: 264 policydb_destroy(&policydb); 265 266 err: 267 return -1; 268 } 269