1cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig/* 2cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * Property Service contexts backend for labeling Android 3cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * property keys 4cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig */ 5cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 6cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <stdarg.h> 7cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <string.h> 8cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <ctype.h> 9cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <errno.h> 10cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <limits.h> 11cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <sys/types.h> 12cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include <sys/stat.h> 13cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include "callbacks.h" 14cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig#include "label_internal.h" 15cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 16cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig/* A property security context specification. */ 17cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigtypedef struct spec { 1830900902b16c70fabe78a22aafb120443acdd53cEric Paris struct selabel_lookup_rec lr; /* holds contexts for lookup result */ 1930900902b16c70fabe78a22aafb120443acdd53cEric Paris char *property_key; /* property key string */ 20cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} spec_t; 21cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 22cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig/* Our stored configuration */ 23cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstruct saved_data { 24cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* 25cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * The array of specifications is sorted for longest 26cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * prefix match 27cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig */ 28cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec_t *spec_arr; 2930900902b16c70fabe78a22aafb120443acdd53cEric Paris unsigned int nspec; /* total number of specifications */ 30cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig}; 31cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 32cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstatic int cmp(const void *A, const void *B) 33cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 34cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig const struct spec *sp1 = A, *sp2 = B; 35cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 3630900902b16c70fabe78a22aafb120443acdd53cEric Paris if (strncmp(sp1->property_key, "*", 1) == 0) 37cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return 1; 3830900902b16c70fabe78a22aafb120443acdd53cEric Paris if (strncmp(sp2->property_key, "*", 1) == 0) 39cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return -1; 40cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 41cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig size_t L1 = strlen(sp1->property_key); 42cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig size_t L2 = strlen(sp2->property_key); 43cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 44cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return (L1 < L2) - (L1 > L2); 45cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 46cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 47cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig/* 48cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * Warn about duplicate specifications. 49cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig */ 50cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstatic int nodups_specs(struct saved_data *data, const char *path) 51cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 52cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig int rc = 0; 53cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned int ii, jj; 54cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct spec *curr_spec, *spec_arr = data->spec_arr; 55cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 56cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig for (ii = 0; ii < data->nspec; ii++) { 57cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig curr_spec = &spec_arr[ii]; 58cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig for (jj = ii + 1; jj < data->nspec; jj++) { 5930900902b16c70fabe78a22aafb120443acdd53cEric Paris if (!strcmp(spec_arr[jj].property_key, curr_spec->property_key)) { 60cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rc = -1; 61cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig errno = EINVAL; 6230900902b16c70fabe78a22aafb120443acdd53cEric Paris if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) { 6330900902b16c70fabe78a22aafb120443acdd53cEric Paris selinux_log(SELINUX_ERROR, 6430900902b16c70fabe78a22aafb120443acdd53cEric Paris "%s: Multiple different specifications for %s (%s and %s).\n", 6530900902b16c70fabe78a22aafb120443acdd53cEric Paris path, 6630900902b16c70fabe78a22aafb120443acdd53cEric Paris curr_spec->property_key, 6730900902b16c70fabe78a22aafb120443acdd53cEric Paris spec_arr[jj].lr.ctx_raw, 6830900902b16c70fabe78a22aafb120443acdd53cEric Paris curr_spec->lr.ctx_raw); 69cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } else { 7030900902b16c70fabe78a22aafb120443acdd53cEric Paris selinux_log(SELINUX_ERROR, 7130900902b16c70fabe78a22aafb120443acdd53cEric Paris "%s: Multiple same specifications for %s.\n", 7230900902b16c70fabe78a22aafb120443acdd53cEric Paris path, 7330900902b16c70fabe78a22aafb120443acdd53cEric Paris curr_spec->property_key); 74cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 75cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 76cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 77cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 78cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return rc; 79cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 80cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 81cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstatic int process_line(struct selabel_handle *rec, 8230900902b16c70fabe78a22aafb120443acdd53cEric Paris const char *path, char *line_buf, 83cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig int pass, unsigned lineno) 84cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 85cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig int items, len; 86cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig char buf1[BUFSIZ], buf2[BUFSIZ]; 87cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig char *buf_p, *prop = buf1, *context = buf2; 88cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct saved_data *data = (struct saved_data *)rec->data; 89cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec_t *spec_arr = data->spec_arr; 90cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned int nspec = data->nspec; 91cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 92cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig len = strlen(line_buf); 93cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (line_buf[len - 1] == '\n') 94cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig line_buf[len - 1] = 0; 95cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig buf_p = line_buf; 96cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig while (isspace(*buf_p)) 97cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig buf_p++; 98cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* Skip comment lines and empty lines. */ 99cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (*buf_p == '#' || *buf_p == 0) 100cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return 0; 101cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig items = sscanf(line_buf, "%255s %255s", prop, context); 102cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (items != 2) { 103cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig selinux_log(SELINUX_WARNING, 104417cb8d076a31c57710429b255aebc595613eb6bPetr Lautrbach "%s: line %u is missing fields, skipping\n", path, 105cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig lineno); 106cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return 0; 107cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 108cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 109cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (pass == 1) { 110cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* On the second pass, process and store the specification in spec. */ 111cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec_arr[nspec].property_key = strdup(prop); 112cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (!spec_arr[nspec].property_key) { 113cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig selinux_log(SELINUX_WARNING, 114417cb8d076a31c57710429b255aebc595613eb6bPetr Lautrbach "%s: out of memory at line %u on prop %s\n", 115cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig path, lineno, prop); 11630900902b16c70fabe78a22aafb120443acdd53cEric Paris return -1; 11730900902b16c70fabe78a22aafb120443acdd53cEric Paris 118cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 119cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 120cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec_arr[nspec].lr.ctx_raw = strdup(context); 121cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (!spec_arr[nspec].lr.ctx_raw) { 122cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig selinux_log(SELINUX_WARNING, 123417cb8d076a31c57710429b255aebc595613eb6bPetr Lautrbach "%s: out of memory at line %u on context %s\n", 124cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig path, lineno, context); 12530900902b16c70fabe78a22aafb120443acdd53cEric Paris return -1; 126cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 127eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig 128eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig if (rec->validating) { 129eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { 130eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig selinux_log(SELINUX_WARNING, 131417cb8d076a31c57710429b255aebc595613eb6bPetr Lautrbach "%s: line %u has invalid context %s\n", 132eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig path, lineno, spec_arr[nspec].lr.ctx_raw); 133eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig } 134eb0ba200b513d05d176e10a85061fdf01d0426f7Robert Craig } 13530900902b16c70fabe78a22aafb120443acdd53cEric Paris } 136cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 137cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig data->nspec = ++nspec; 138cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return 0; 139cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 140cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 141cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstatic int init(struct selabel_handle *rec, struct selinux_opt *opts, 142cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned n) 143cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 144cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct saved_data *data = (struct saved_data *)rec->data; 145cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig const char *path = NULL; 146cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig FILE *fp; 147cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig char line_buf[BUFSIZ]; 148cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned int lineno = 0, maxnspec, pass; 149cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig int status = -1; 150cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct stat sb; 151cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 152cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* Process arguments */ 153cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig while (n--) 154cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig switch (opts[n].type) { 155cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig case SELABEL_OPT_PATH: 156cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig path = opts[n].value; 157cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig break; 158cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 159cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 160aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris if (!path) 161aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris return -1; 162aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris 163cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* Open the specification file. */ 164cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if ((fp = fopen(path, "r")) == NULL) 165cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return -1; 166cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 167cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (fstat(fileno(fp), &sb) < 0) 1681e8f102e8cec4ae84f09cc595013234398270366Eric Paris goto finish; 1691e8f102e8cec4ae84f09cc595013234398270366Eric Paris errno = EINVAL; 1701e8f102e8cec4ae84f09cc595013234398270366Eric Paris if (!S_ISREG(sb.st_mode)) 1711e8f102e8cec4ae84f09cc595013234398270366Eric Paris goto finish; 172cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 173cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* 174cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * Two passes of the specification file. First is to get the size. 175cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * After the first pass, the spec array is malloced to the appropriate 176cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * size. Second pass is to populate the spec array and check for 177cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * dups. 178cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig */ 179cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig maxnspec = UINT_MAX / sizeof(spec_t); 180cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig for (pass = 0; pass < 2; pass++) { 181cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig data->nspec = 0; 182cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 183cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig while (fgets(line_buf, sizeof line_buf - 1, fp) 184cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig && data->nspec < maxnspec) { 18530900902b16c70fabe78a22aafb120443acdd53cEric Paris if (process_line(rec, path, line_buf, pass, ++lineno) != 0) 186cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 187cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 188cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 189cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (pass == 1) { 190cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig status = nodups_specs(data, path); 19130900902b16c70fabe78a22aafb120443acdd53cEric Paris 192cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (status) 193cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 194cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 195cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 196cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (pass == 0) { 197cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 198cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (data->nspec == 0) { 199cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig status = 0; 200cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 201cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 202cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 203cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (NULL == (data->spec_arr = 204cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig malloc(sizeof(spec_t) * data->nspec))) 205cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 206cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 20730900902b16c70fabe78a22aafb120443acdd53cEric Paris memset(data->spec_arr, 0, sizeof(spec_t) * data->nspec); 208cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig maxnspec = data->nspec; 209cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rewind(fp); 210cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 211cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 212cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 213cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp); 214cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 215cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig status = 0; 216cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigfinish: 217cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig fclose(fp); 218cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return status; 219cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 220cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 221cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig/* 222cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig * Backend interface routines 223cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig */ 224cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigstatic void closef(struct selabel_handle *rec) 225cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 226cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct saved_data *data = (struct saved_data *)rec->data; 227cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct spec *spec; 228cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned int i; 229cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 230cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig for (i = 0; i < data->nspec; i++) { 231cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec = &data->spec_arr[i]; 232cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig free(spec->property_key); 233cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig free(spec->lr.ctx_raw); 234cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig free(spec->lr.ctx_trans); 235cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 236cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 237cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (data->spec_arr) 238cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig free(data->spec_arr); 23930900902b16c70fabe78a22aafb120443acdd53cEric Paris 240cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig free(data); 241cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 242cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 24330900902b16c70fabe78a22aafb120443acdd53cEric Parisstatic struct selabel_lookup_rec *lookup(struct selabel_handle *rec, 24430900902b16c70fabe78a22aafb120443acdd53cEric Paris const char *key, 24530900902b16c70fabe78a22aafb120443acdd53cEric Paris int __attribute__ ((unused)) type) 246cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 247cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct saved_data *data = (struct saved_data *)rec->data; 248cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig spec_t *spec_arr = data->spec_arr; 249cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig unsigned int i; 250cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct selabel_lookup_rec *ret = NULL; 251cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 252cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (!data->nspec) { 253cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig errno = ENOENT; 254cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 255cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 256cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 257cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig for (i = 0; i < data->nspec; i++) { 25830900902b16c70fabe78a22aafb120443acdd53cEric Paris if (strncmp(spec_arr[i].property_key, key, 25930900902b16c70fabe78a22aafb120443acdd53cEric Paris strlen(spec_arr[i].property_key)) == 0) { 260cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig break; 261cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 262cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (strncmp(spec_arr[i].property_key, "*", 1) == 0) 263cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig break; 264cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 265cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 266cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (i >= data->nspec) { 267cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig /* No matching specification. */ 268cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig errno = ENOENT; 269cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig goto finish; 270cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig } 271cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 272cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig ret = &spec_arr[i].lr; 273cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 274cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigfinish: 275cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return ret; 276cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 277cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 27830900902b16c70fabe78a22aafb120443acdd53cEric Parisstatic void stats(struct selabel_handle __attribute__ ((unused)) * rec) 279cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 280cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n"); 281cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 282cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 283cfc492cf11e1b641e2a0478907d56a17b771a067rpcraigint selabel_property_init(struct selabel_handle *rec, struct selinux_opt *opts, 28430900902b16c70fabe78a22aafb120443acdd53cEric Paris unsigned nopts) 285cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig{ 286cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig struct saved_data *data; 287cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 288cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig data = (struct saved_data *)malloc(sizeof(*data)); 289cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig if (!data) 290cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return -1; 291cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig memset(data, 0, sizeof(*data)); 292cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 293cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rec->data = data; 294cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rec->func_close = &closef; 295cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rec->func_stats = &stats; 296cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig rec->func_lookup = &lookup; 297cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig 298cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig return init(rec, opts, nopts); 299cfc492cf11e1b641e2a0478907d56a17b771a067rpcraig} 300