147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Property Service contexts backend for labeling Android 347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * property keys 447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdarg.h> 747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <string.h> 847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <ctype.h> 947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h> 1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <limits.h> 1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/types.h> 1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/stat.h> 1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "callbacks.h" 1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "label_internal.h" 1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* A property security context specification. */ 1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnertypedef struct spec { 1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct selabel_lookup_rec lr; /* holds contexts for lookup result */ 1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *property_key; /* property key string */ 2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} spec_t; 2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* Our stored configuration */ 2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstruct saved_data { 2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * The array of specifications is sorted for longest 2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * prefix match 2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr; 2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int nspec; /* total number of specifications */ 3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}; 3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int cmp(const void *A, const void *B) 3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const struct spec *sp1 = A, *sp2 = B; 3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strncmp(sp1->property_key,"*",1) == 0) 3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 1; 3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strncmp(sp2->property_key,"*",1) == 0) 3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t L1 = strlen(sp1->property_key); 4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t L2 = strlen(sp2->property_key); 4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return (L1 < L2) - (L1 > L2); 4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 4647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 4847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Warn about duplicate specifications. 4947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 5047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int nodups_specs(struct saved_data *data, const char *path) 5147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 5247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int rc = 0; 5347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int ii, jj; 5447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct spec *curr_spec, *spec_arr = data->spec_arr; 5547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 5647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (ii = 0; ii < data->nspec; ii++) { 5747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec = &spec_arr[ii]; 5847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (jj = ii + 1; jj < data->nspec; jj++) { 5947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((!strcmp(spec_arr[jj].property_key, curr_spec->property_key))) { 6047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rc = -1; 6147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = EINVAL; 6247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strcmp 6347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (spec_arr[jj].lr.ctx_raw, 6447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec->lr.ctx_raw)) { 6547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log 6647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (SELINUX_ERROR, 6747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: Multiple different specifications for %s (%s and %s).\n", 6847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, curr_spec->property_key, 6947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[jj].lr.ctx_raw, 7047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec->lr.ctx_raw); 7147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } else { 7247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log 7347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (SELINUX_ERROR, 7447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: Multiple same specifications for %s.\n", 7547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, curr_spec->property_key); 7647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 7747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 7847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 7947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 8047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return rc; 8147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 8247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 8347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int process_line(struct selabel_handle *rec, 8447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *path, char *line_buf, 8547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int pass, unsigned lineno) 8647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 8747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int items, len; 8847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char buf1[BUFSIZ], buf2[BUFSIZ]; 8947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *buf_p, *prop = buf1, *context = buf2; 9047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 9147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr = data->spec_arr; 9247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int nspec = data->nspec; 9347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 9447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = strlen(line_buf); 9547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (line_buf[len - 1] == '\n') 9647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner line_buf[len - 1] = 0; 9747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf_p = line_buf; 9847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (isspace(*buf_p)) 9947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf_p++; 10047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Skip comment lines and empty lines. */ 10147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (*buf_p == '#' || *buf_p == 0) 10247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 10347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner items = sscanf(line_buf, "%255s %255s", prop, context); 10447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (items != 2) { 10547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 10647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d is missing fields, skipping\n", path, 10747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner lineno); 10847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 10947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 11047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 11147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 1) { 11247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* On the second pass, process and store the specification in spec. */ 11347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].property_key = strdup(prop); 11447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!spec_arr[nspec].property_key) { 11547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 11647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: out of memory at line %d on prop %s\n", 11747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, prop); 11847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 11947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 12047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 12147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 12247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].lr.ctx_raw = strdup(context); 12347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!spec_arr[nspec].lr.ctx_raw) { 12447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 12547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: out of memory at line %d on context %s\n", 12647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, context); 12747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 12847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 12947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 13047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (rec->validating) { 13147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { 13247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 13347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d has invalid context %s\n", 13447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, spec_arr[nspec].lr.ctx_raw); 13547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 13647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 13747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 13847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 13947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->nspec = ++nspec; 14047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 14147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 14247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 14347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int init(struct selabel_handle *rec, const struct selinux_opt *opts, 14447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned n) 14547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 14647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 14747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *path = NULL; 14847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner FILE *fp; 14947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char line_buf[BUFSIZ]; 15047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int lineno = 0, maxnspec, pass; 15147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int status = -1; 15247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct stat sb; 15347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 15447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Process arguments */ 15547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (n--) 15647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner switch (opts[n].type) { 15747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case SELABEL_OPT_PATH: 15847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path = opts[n].value; 15947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 16047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 16147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 16247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Open the specification file. */ 16347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((fp = fopen(path, "r")) == NULL) 16447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 16547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 16647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (fstat(fileno(fp), &sb) < 0) 16747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 16847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!S_ISREG(sb.st_mode)) { 16947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = EINVAL; 17047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 17147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 17247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 17347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 17447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Two passes of the specification file. First is to get the size. 17547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * After the first pass, the spec array is malloced to the appropriate 17647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * size. Second pass is to populate the spec array and check for 17747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * dups. 17847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 17947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner maxnspec = UINT_MAX / sizeof(spec_t); 18047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 18147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->nspec = 0; 18247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 18347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (fgets(line_buf, sizeof line_buf - 1, fp) 18447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && data->nspec < maxnspec) { 18547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (process_line(rec, path, line_buf, pass, ++lineno) != 0) { 18647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 18747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 18847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 18947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 1) { 19147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = nodups_specs(data, path); 19247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (status) 19447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 19547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 19647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 0) { 19847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->nspec == 0) { 20047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = 0; 20147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 20247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 20347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 20447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (NULL == (data->spec_arr = 20547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner malloc(sizeof(spec_t) * data->nspec))) 20647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 20747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 20847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); 20947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner maxnspec = data->nspec; 21047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rewind(fp); 21147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 21247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 21347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 21447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp); 21547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 21647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = 0; 21747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerfinish: 21847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner fclose(fp); 21947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return status; 22047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 22147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 22247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 22347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Backend interface routines 22447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 22547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void closef(struct selabel_handle *rec) 22647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 22747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 22847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct spec *spec; 22947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int i; 23047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 23147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->nspec; i++) { 23247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec = &data->spec_arr[i]; 23347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->property_key); 23447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->lr.ctx_raw); 23547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->lr.ctx_trans); 23647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 23747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 23847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->spec_arr) 23947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data->spec_arr); 24047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 24147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data); 24247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 24347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 24447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic struct selabel_lookup_rec *lookup(struct selabel_handle *rec, 24547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *key, 24647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int __attribute__((unused)) type) 24747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 24847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 24947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr = data->spec_arr; 25047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int i; 25147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct selabel_lookup_rec *ret = NULL; 25247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 25347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data->nspec) { 25447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = ENOENT; 25547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 25647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 25747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 25847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->nspec; i++) { 25947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strncmp(spec_arr[i].property_key, key, 26047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner strlen(spec_arr[i].property_key)) == 0) { 26147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 26247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 26347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strncmp(spec_arr[i].property_key, "*", 1) == 0) 26447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 26547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 26647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 26747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (i >= data->nspec) { 26847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* No matching specification. */ 26947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = ENOENT; 27047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 27147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 27247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner ret = &spec_arr[i].lr; 27447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerfinish: 27647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return ret; 27747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 27847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void stats(struct selabel_handle __attribute__((unused)) *rec) 28047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 28147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n"); 28247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 28347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 28447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint selabel_property_init(struct selabel_handle *rec, 28547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const struct selinux_opt *opts, 28647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned nopts) 28747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 28847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data; 28947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 29047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data = (struct saved_data *)malloc(sizeof(*data)); 29147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data) 29247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 29347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memset(data, 0, sizeof(*data)); 29447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 29547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->data = data; 29647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_close = &closef; 29747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_stats = &stats; 29847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_lookup = &lookup; 29947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 30047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return init(rec, opts, nopts); 30147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 302