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