label_file.c revision 47173c7d6704f1258b2d85537caa09185f6920c8
147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * File contexts backend for labeling system 347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * 447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Author : Eamon Walsh <ewalsh@tycho.nsa.gov> 547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <fcntl.h> 847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdarg.h> 947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <string.h> 1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdio.h> 1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <ctype.h> 1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h> 1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <limits.h> 1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <regex.h> 1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/types.h> 1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <sys/stat.h> 1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <unistd.h> 1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "callbacks.h" 1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "label_internal.h" 2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Internals, mostly moved over from matchpathcon.c 2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* A file security context specification. */ 2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnertypedef struct spec { 2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct selabel_lookup_rec lr; /* holds contexts for lookup result */ 2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *regex_str; /* regular expession string for diagnostics */ 2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *type_str; /* type string for diagnostic messages */ 3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner regex_t regex; /* compiled regular expression */ 3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char regcomp; /* regex_str has been compiled to regex */ 3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner mode_t mode; /* mode format value */ 3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int matches; /* number of matching pathnames */ 3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int hasMetaChars; /* regular expression has meta-chars */ 3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int stem_id; /* indicates which stem-compression item */ 3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t prefix_len; /* length of fixed path prefix */ 3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} spec_t; 3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* A regular expression stem */ 4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnertypedef struct stem { 4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *buf; 4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int len; 4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} stem_t; 4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* Our stored configuration */ 4647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstruct saved_data { 4747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 4847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * The array of specifications, initially in the same order as in 4947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * the specification file. Sorting occurs based on hasMetaChars. 5047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 5147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr; 5247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int nspec; 5347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int ncomp; 5447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 5547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 5647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * The array of regular expression stems. 5747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 5847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner stem_t *stem_arr; 5947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int num_stems; 6047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int alloc_stems; 6147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}; 6247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 6347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* Return the length of the text that can be considered the stem, returns 0 6447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * if there is no identifiable stem */ 6547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int get_stem_from_spec(const char *const buf) 6647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 6747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *tmp = strchr(buf + 1, '/'); 6847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *ind; 6947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 7047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!tmp) 7147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 7247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 7347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (ind = buf; ind < tmp; ind++) { 7447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strchr(".^$?*+|[({", (int)*ind)) 7547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 7647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 7747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return tmp - buf; 7847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 7947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 8047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* return the length of the text that is the stem of a file name */ 8147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int get_stem_from_file_name(const char *const buf) 8247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 8347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *tmp = strchr(buf + 1, '/'); 8447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 8547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!tmp) 8647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 8747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return tmp - buf; 8847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 8947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 9047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* find the stem of a file spec, returns the index into stem_arr for a new 9147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * or existing stem, (or -1 if there is no possible stem - IE for a file in 9247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * the root directory or a regex that is too complex for us). */ 9347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int find_stem_from_spec(struct saved_data *data, const char *buf) 9447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 9547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int i, num = data->num_stems; 9647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int stem_len = get_stem_from_spec(buf); 9747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 9847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!stem_len) 9947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 10047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < num; i++) { 10147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (stem_len == data->stem_arr[i].len 10247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && !strncmp(buf, data->stem_arr[i].buf, stem_len)) 10347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return i; 10447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 10547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->alloc_stems == num) { 10647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner stem_t *tmp_arr; 10747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->alloc_stems = data->alloc_stems * 2 + 16; 10847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner tmp_arr = (stem_t *) realloc(data->stem_arr, 10947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner sizeof(stem_t) * data->alloc_stems); 11047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!tmp_arr) 11147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 11247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->stem_arr = tmp_arr; 11347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 11447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->stem_arr[num].len = stem_len; 11547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->stem_arr[num].buf = (char *) malloc(stem_len + 1); 11647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data->stem_arr[num].buf) 11747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 11847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memcpy(data->stem_arr[num].buf, buf, stem_len); 11947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->stem_arr[num].buf[stem_len] = '\0'; 12047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->num_stems++; 12147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf += stem_len; 12247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return num; 12347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 12447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 12547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* find the stem of a file name, returns the index into stem_arr (or -1 if 12647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * there is no match - IE for a file in the root directory or a regex that is 12747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * too complex for us). Makes buf point to the text AFTER the stem. */ 12847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int find_stem_from_file(struct saved_data *data, const char **buf) 12947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 13047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int i; 13147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int stem_len = get_stem_from_file_name(*buf); 13247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 13347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!stem_len) 13447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 13547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->num_stems; i++) { 13647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (stem_len == data->stem_arr[i].len 13747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && !strncmp(*buf, data->stem_arr[i].buf, stem_len)) { 13847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *buf += stem_len; 13947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return i; 14047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 14147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 14247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 14347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 14447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 14547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 14647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Warn about duplicate specifications. 14747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 14847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int nodups_specs(struct saved_data *data, const char *path) 14947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 15047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int rc = 0; 15147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int ii, jj; 15247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct spec *curr_spec, *spec_arr = data->spec_arr; 15347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 15447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (ii = 0; ii < data->nspec; ii++) { 15547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec = &spec_arr[ii]; 15647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (jj = ii + 1; jj < data->nspec; jj++) { 15747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((!strcmp 15847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (spec_arr[jj].regex_str, curr_spec->regex_str)) 15947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && (!spec_arr[jj].mode || !curr_spec->mode 16047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner || spec_arr[jj].mode == curr_spec->mode)) { 16147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rc = -1; 16247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = EINVAL; 16347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strcmp 16447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (spec_arr[jj].lr.ctx_raw, 16547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec->lr.ctx_raw)) { 16647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log 16747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (SELINUX_ERROR, 16847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: Multiple different specifications for %s (%s and %s).\n", 16947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, curr_spec->regex_str, 17047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[jj].lr.ctx_raw, 17147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner curr_spec->lr.ctx_raw); 17247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } else { 17347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log 17447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (SELINUX_ERROR, 17547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: Multiple same specifications for %s.\n", 17647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, curr_spec->regex_str); 17747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 17847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 17947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 18047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 18147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return rc; 18247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 18347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 18447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* Determine if the regular expression specification has any meta characters. */ 18547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void spec_hasMetaChars(struct spec *spec) 18647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 18747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *c; 18847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t len; 18947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *end; 19047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner c = spec->regex_str; 19247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = strlen(spec->regex_str); 19347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner end = c + len; 19447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec->hasMetaChars = 0; 19647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec->prefix_len = len; 19747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 19847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Look at each character in the RE specification string for a 19947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * meta character. Return when any meta character reached. */ 20047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (c != end) { 20147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner switch (*c) { 20247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '.': 20347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '^': 20447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '$': 20547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '?': 20647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '*': 20747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '+': 20847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '|': 20947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '[': 21047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '(': 21147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '{': 21247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec->hasMetaChars = 1; 21347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec->prefix_len = c - spec->regex_str; 21447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return; 21547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '\\': /* skip the next character */ 21647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner c++; 21747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 21847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner default: 21947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 22047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 22147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 22247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner c++; 22347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 22447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return; 22547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 22647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 22747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int compile_regex(struct saved_data *data, spec_t *spec, char **errbuf) 22847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 22947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *reg_buf, *anchored_regex, *cp; 23047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner stem_t *stem_arr = data->stem_arr; 23147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t len; 23247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int regerr; 23347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 23447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec->regcomp) 23547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; /* already done */ 23647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 23747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->ncomp++; /* how many compiled regexes required */ 23847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 23947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Skip the fixed stem. */ 24047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner reg_buf = spec->regex_str; 24147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec->stem_id >= 0) 24247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner reg_buf += stem_arr[spec->stem_id].len; 24347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 24447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Anchor the regular expression. */ 24547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = strlen(reg_buf); 24647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner cp = anchored_regex = (char *) malloc(len + 3); 24747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!anchored_regex) 24847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 24947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Create ^...$ regexp. */ 25047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *cp++ = '^'; 25147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memcpy(cp, reg_buf, len); 25247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner cp += len; 25347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *cp++ = '$'; 25447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *cp = '\0'; 25547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 25647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Compile the regular expression. */ 25747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner regerr = regcomp(&spec->regex, anchored_regex, 25847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner REG_EXTENDED | REG_NOSUB); 25947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (regerr != 0) { 26047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t errsz = 0; 26147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errsz = regerror(regerr, &spec->regex, NULL, 0); 26247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (errsz && errbuf) 26347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *errbuf = (char *) malloc(errsz); 26447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (errbuf && *errbuf) 26547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (void)regerror(regerr, &spec->regex, 26647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner *errbuf, errsz); 26747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 26847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(anchored_regex); 26947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 27047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 27147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(anchored_regex); 27247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Done. */ 27447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec->regcomp = 1; 27547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 27747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 27847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 27947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 28047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int process_line(struct selabel_handle *rec, 28147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *path, const char *prefix, 28247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *line_buf, int pass, unsigned lineno) 28347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 28447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int items, len; 28547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char buf1[BUFSIZ], buf2[BUFSIZ], buf3[BUFSIZ]; 28647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *buf_p, *regex = buf1, *type = buf2, *context = buf3; 28747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 28847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr = data->spec_arr; 28947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int nspec = data->nspec; 29047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 29147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = strlen(line_buf); 29247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (line_buf[len - 1] == '\n') 29347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner line_buf[len - 1] = 0; 29447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf_p = line_buf; 29547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (isspace(*buf_p)) 29647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf_p++; 29747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Skip comment lines and empty lines. */ 29847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (*buf_p == '#' || *buf_p == 0) 29947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 30047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner items = sscanf(line_buf, "%255s %255s %255s", regex, type, context); 30147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (items < 2) { 30247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 30347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d is missing fields, skipping\n", path, 30447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner lineno); 30547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 30647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } else if (items == 2) { 30747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* The type field is optional. */ 30847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner context = type; 30947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner type = NULL; 31047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 31147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 31247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = get_stem_from_spec(regex); 31347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (len && prefix && strncmp(prefix, regex, len)) { 31447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Stem of regex does not match requested prefix, discard. */ 31547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 31647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 31747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 31847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 1) { 31947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* On the second pass, process and store the specification in spec. */ 32047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *errbuf = NULL; 32147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); 32247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].regex_str = strdup(regex); 32347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!spec_arr[nspec].regex_str) { 32447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 32547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: out of memory at line %d on regex %s\n", 32647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, regex); 32747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 32847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 32947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 33047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) { 33147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 33247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d has invalid regex %s: %s\n", 33347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, regex, 33447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (errbuf ? errbuf : "out of memory")); 33547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 33647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 33747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Convert the type string to a mode format */ 33847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = 0; 33947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!type) 34047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto skip_type; 34147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].type_str = strdup(type); 34247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner len = strlen(type); 34347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (type[0] != '-' || len != 2) { 34447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 34547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d has invalid file type %s\n", 34647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, type); 34747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 34847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 34947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner switch (type[1]) { 35047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 'b': 35147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFBLK; 35247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 35347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 'c': 35447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFCHR; 35547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 35647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 'd': 35747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFDIR; 35847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 35947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 'p': 36047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFIFO; 36147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 36247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 'l': 36347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFLNK; 36447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 36547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case 's': 36647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFSOCK; 36747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 36847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case '-': 36947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].mode = S_IFREG; 37047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 37147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner default: 37247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 37347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d has invalid file type %s\n", 37447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, type); 37547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 37647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 37747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 37847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner skip_type: 37947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[nspec].lr.ctx_raw = strdup(context); 38047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 38147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (strcmp(context, "<<none>>") && rec->validating) { 38247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { 38347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 38447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "%s: line %d has invalid context %s\n", 38547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path, lineno, spec_arr[nspec].lr.ctx_raw); 38647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 38747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 38847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 38947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Determine if specification has 39047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * any meta characters in the RE */ 39147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_hasMetaChars(&spec_arr[nspec]); 39247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 39347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 39447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->nspec = ++nspec; 39547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return 0; 39647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 39747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 39847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int init(struct selabel_handle *rec, const struct selinux_opt *opts, 39947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned n) 40047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 40147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 40247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *path = NULL; 40347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *prefix = NULL; 40447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner FILE *fp; 40547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner FILE *localfp = NULL; 40647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner FILE *homedirfp = NULL; 40747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char local_path[PATH_MAX + 1]; 40847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char homedir_path[PATH_MAX + 1]; 40947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char line_buf[BUFSIZ]; 41047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int lineno, pass, i, j, maxnspec; 41147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_copy = NULL; 41247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int status = -1, baseonly = 0; 41347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct stat sb; 41447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 41547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Process arguments */ 41647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (n--) 41747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner switch(opts[n].type) { 41847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case SELABEL_OPT_PATH: 41947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path = opts[n].value; 42047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 42147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case SELABEL_OPT_SUBSET: 42247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner prefix = opts[n].value; 42347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 42447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner case SELABEL_OPT_BASEONLY: 42547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner baseonly = !!opts[n].value; 42647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 42747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 42847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 42947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Open the specification file. */ 43047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((fp = fopen(path, "r")) == NULL) 43147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 43247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 43347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (fstat(fileno(fp), &sb) < 0) 43447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 43547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!S_ISREG(sb.st_mode)) { 43647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = EINVAL; 43747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 43847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 43947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 44047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!baseonly) { 44147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner snprintf(homedir_path, sizeof(homedir_path), "%s.homedirs", 44247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner path); 44347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner homedirfp = fopen(homedir_path, "r"); 44447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 44547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner snprintf(local_path, sizeof(local_path), "%s.local", path); 44647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner localfp = fopen(local_path, "r"); 44747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 44847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 44947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 45047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Perform two passes over the specification file. 45147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * The first pass counts the number of specifications and 45247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * performs simple validation of the input. At the end 45347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * of the first pass, the spec array is allocated. 45447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * The second pass performs detailed validation of the input 45547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * and fills in the spec array. 45647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 45747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner maxnspec = UINT_MAX / sizeof(spec_t); 45847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (pass = 0; pass < 2; pass++) { 45947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner lineno = 0; 46047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->nspec = 0; 46147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->ncomp = 0; 46247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (fgets(line_buf, sizeof line_buf - 1, fp) 46347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && data->nspec < maxnspec) { 46447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (process_line(rec, path, prefix, line_buf, 46547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner pass, ++lineno) != 0) 46647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 46747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 46847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 1) { 46947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = nodups_specs(data, path); 47047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (status) 47147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 47247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 47347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner lineno = 0; 47447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (homedirfp) 47547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (fgets(line_buf, sizeof line_buf - 1, homedirfp) 47647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && data->nspec < maxnspec) { 47747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (process_line 47847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (rec, homedir_path, prefix, 47947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner line_buf, pass, ++lineno) != 0) 48047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 48147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 48247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 48347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner lineno = 0; 48447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (localfp) 48547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (fgets(line_buf, sizeof line_buf - 1, localfp) 48647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && data->nspec < maxnspec) { 48747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (process_line 48847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (rec, local_path, prefix, line_buf, 48947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner pass, ++lineno) != 0) 49047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 49147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 49247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 49347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (pass == 0) { 49447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->nspec == 0) { 49547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = 0; 49647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 49747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 49847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (NULL == (data->spec_arr = 49947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner (spec_t *) malloc(sizeof(spec_t) * data->nspec))) 50047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 50147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); 50247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner maxnspec = data->nspec; 50347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rewind(fp); 50447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (homedirfp) 50547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rewind(homedirfp); 50647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (localfp) 50747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rewind(localfp); 50847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 50947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 51047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 51147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Move exact pathname specifications to the end. */ 51247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_copy = (spec_t *) malloc(sizeof(spec_t) * data->nspec); 51347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!spec_copy) 51447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 51547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner j = 0; 51647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->nspec; i++) 51747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->spec_arr[i].hasMetaChars) 51847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memcpy(&spec_copy[j++], 51947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner &data->spec_arr[i], sizeof(spec_t)); 52047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->nspec; i++) 52147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data->spec_arr[i].hasMetaChars) 52247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memcpy(&spec_copy[j++], 52347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner &data->spec_arr[i], sizeof(spec_t)); 52447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data->spec_arr); 52547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data->spec_arr = spec_copy; 52647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 52747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner status = 0; 52847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerfinish: 52947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner fclose(fp); 53047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->spec_arr != spec_copy) 53147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data->spec_arr); 53247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (homedirfp) 53347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner fclose(homedirfp); 53447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (localfp) 53547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner fclose(localfp); 53647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return status; 53747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 53847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 53947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* 54047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Backend interface routines 54147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 54247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void closef(struct selabel_handle *rec) 54347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 54447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 54547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct spec *spec; 54647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct stem *stem; 54747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int i; 54847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 54947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < data->nspec; i++) { 55047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec = &data->spec_arr[i]; 55147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->regex_str); 55247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->type_str); 55347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->lr.ctx_raw); 55447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(spec->lr.ctx_trans); 55547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec->regcomp) 55647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner regfree(&spec->regex); 55747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 55847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 55947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < (unsigned int)data->num_stems; i++) { 56047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner stem = &data->stem_arr[i]; 56147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(stem->buf); 56247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 56347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 56447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->spec_arr) 56547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data->spec_arr); 56647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (data->stem_arr) 56747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data->stem_arr); 56847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 56947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(data); 57047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 57147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 57247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic struct selabel_lookup_rec *lookup_common(struct selabel_handle *rec, 57347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *key, int type, 57447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner bool partial) 57547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 57647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 57747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr = data->spec_arr; 57847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner int i, rc, file_stem; 57947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner mode_t mode = (mode_t)type; 58047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *buf; 58147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct selabel_lookup_rec *ret = NULL; 58247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner char *clean_key = NULL; 58347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *prev_slash, *next_slash; 58447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int sofar = 0; 58547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner size_t keylen = strlen(key); 58647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 58747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data->nspec) { 58847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = ENOENT; 58947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 59047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 59147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 59247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* Remove duplicate slashes */ 59347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((next_slash = strstr(key, "//"))) { 59447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner clean_key = (char *) malloc(strlen(key) + 1); 59547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!clean_key) 59647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 59747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner prev_slash = key; 59847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner while (next_slash) { 59947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memcpy(clean_key + sofar, prev_slash, next_slash - prev_slash); 60047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner sofar += next_slash - prev_slash; 60147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner prev_slash = next_slash + 1; 60247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner next_slash = strstr(prev_slash, "//"); 60347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 60447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner strcpy(clean_key + sofar, prev_slash); 60547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner key = clean_key; 60647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 60747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 60847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner buf = key; 60947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner file_stem = find_stem_from_file(data, &buf); 61047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner mode &= S_IFMT; 61147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 61247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 61347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Check for matching specifications in reverse order, so that 61447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * the last matching specification is used. 61547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 61647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = data->nspec - 1; i >= 0; i--) { 61747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* if the spec in question matches no stem or has the same 61847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * stem as the file AND if the spec in question has no mode 61947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * specified or if the mode matches the file mode then we do 62047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * a regex check */ 62147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if ((spec_arr[i].stem_id == -1 62247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner || spec_arr[i].stem_id == file_stem) 62347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner && (!mode || !spec_arr[i].mode 62447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner || mode == spec_arr[i].mode)) { 62547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (compile_regex(data, &spec_arr[i], NULL) < 0) 62647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 62747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec_arr[i].stem_id == -1) 62847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rc = regexec(&spec_arr[i].regex, key, 0, 0, 0); 62947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner else 63047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rc = regexec(&spec_arr[i].regex, buf, 0, 0, 0); 63147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 63247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (rc == 0) { 63347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].matches++; 63447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 63547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 63647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 63747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (partial) { 63847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* 63947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * We already checked above to see if the 64047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * key has any direct match. Now we just need 64147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * to check for partial matches. 64247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Since POSIX regex functions do not support 64347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * partial match, we crudely approximate it 64447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * via a prefix match. 64547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * This is imprecise and could yield 64647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * false positives or negatives but 64747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * appears to work with our current set of 64847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * regex strings. 64947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Convert to using pcre partial match 65047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * if/when pcre becomes available in Android. 65147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */ 65247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec_arr[i].prefix_len > 1 && 65347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner !strncmp(key, spec_arr[i].regex_str, 65447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner keylen < spec_arr[i].prefix_len ? 65547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner keylen : spec_arr[i].prefix_len)) 65647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner break; 65747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 65847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 65947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (rc == REG_NOMATCH) 66047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner continue; 66147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* else it's an error */ 66247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 66347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 66447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 66547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 66647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (i < 0 || strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) { 66747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner /* No matching specification. */ 66847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner errno = ENOENT; 66947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner goto finish; 67047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 67147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 67247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner ret = &spec_arr[i].lr; 67347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 67447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerfinish: 67547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner free(clean_key); 67647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return ret; 67747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 67847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 67947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic struct selabel_lookup_rec *lookup(struct selabel_handle *rec, 68047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner const char *key, int type) 68147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 68247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return lookup_common(rec, key, type, false); 68347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 68447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 68547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic bool partial_match(struct selabel_handle *rec, const char *key) 68647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 68747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return lookup_common(rec, key, 0, true) ? true : false; 68847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 68947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 69047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void stats(struct selabel_handle *rec) 69147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 69247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data = (struct saved_data *)rec->data; 69347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned int i, nspec = data->nspec; 69447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_t *spec_arr = data->spec_arr; 69547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 69647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner for (i = 0; i < nspec; i++) { 69747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec_arr[i].matches == 0) { 69847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (spec_arr[i].type_str) { 69947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 70047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "Warning! No matches for (%s, %s, %s)\n", 70147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].regex_str, 70247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].type_str, 70347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].lr.ctx_raw); 70447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } else { 70547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner selinux_log(SELINUX_WARNING, 70647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner "Warning! No matches for (%s, %s)\n", 70747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].regex_str, 70847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner spec_arr[i].lr.ctx_raw); 70947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 71047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 71147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner } 71247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 71347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 71447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts, 71547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner unsigned nopts) 71647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ 71747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner struct saved_data *data; 71847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 71947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner data = (struct saved_data *)malloc(sizeof(*data)); 72047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner if (!data) 72147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return -1; 72247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner memset(data, 0, sizeof(*data)); 72347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 72447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->data = data; 72547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_close = &closef; 72647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_stats = &stats; 72747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_lookup = &lookup; 72847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner rec->func_partial_match = &partial_match; 72947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner 73047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner return init(rec, opts, nopts); 73147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} 732