1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * File contexts backend for labeling system 3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Author : Eamon Walsh <ewalsh@tycho.nsa.gov> 5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <fcntl.h> 8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdarg.h> 9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <string.h> 10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h> 11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <ctype.h> 12f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h> 13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <limits.h> 14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/types.h> 15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <sys/stat.h> 16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <unistd.h> 17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "callbacks.h" 18f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "label_internal.h" 19d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich#include <pcre.h> 20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 22f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Internals, mostly moved over from matchpathcon.c 23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* A file security context specification. */ 26f074036424618c130dacb3464465a8b40bffef5Stephen Smalleytypedef struct spec { 27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct selabel_lookup_rec lr; /* holds contexts for lookup result */ 28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *regex_str; /* regular expession string for diagnostics */ 29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *type_str; /* type string for diagnostic messages */ 30d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich pcre *regex; /* compiled regular expression */ 31d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich pcre_extra *sd; /* pcre study result */ 32f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char regcomp; /* regex_str has been compiled to regex */ 33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley mode_t mode; /* mode format value */ 34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int matches; /* number of matching pathnames */ 35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int hasMetaChars; /* regular expression has meta-chars */ 36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int stem_id; /* indicates which stem-compression item */ 370e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley size_t prefix_len; /* length of fixed path prefix */ 38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} spec_t; 39f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* A regular expression stem */ 41f074036424618c130dacb3464465a8b40bffef5Stephen Smalleytypedef struct stem { 42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *buf; 43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int len; 44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} stem_t; 45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* Our stored configuration */ 47f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystruct saved_data { 48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* 49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * The array of specifications, initially in the same order as in 50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * the specification file. Sorting occurs based on hasMetaChars. 51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_t *spec_arr; 53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int nspec; 54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int ncomp; 55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* 57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * The array of regular expression stems. 58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley stem_t *stem_arr; 60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int num_stems; 61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int alloc_stems; 62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}; 63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* Return the length of the text that can be considered the stem, returns 0 65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * if there is no identifiable stem */ 66f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int get_stem_from_spec(const char *const buf) 67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *tmp = strchr(buf + 1, '/'); 69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *ind; 70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!tmp) 72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (ind = buf; ind < tmp; ind++) { 75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (strchr(".^$?*+|[({", (int)*ind)) 76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return tmp - buf; 79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* return the length of the text that is the stem of a file name */ 82f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int get_stem_from_file_name(const char *const buf) 83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *tmp = strchr(buf + 1, '/'); 85f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!tmp) 87f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return tmp - buf; 89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* find the stem of a file spec, returns the index into stem_arr for a new 92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * or existing stem, (or -1 if there is no possible stem - IE for a file in 93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * the root directory or a regex that is too complex for us). */ 94f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int find_stem_from_spec(struct saved_data *data, const char *buf) 95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i, num = data->num_stems; 97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int stem_len = get_stem_from_spec(buf); 98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 99f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!stem_len) 100f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < num; i++) { 102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (stem_len == data->stem_arr[i].len 103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && !strncmp(buf, data->stem_arr[i].buf, stem_len)) 104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return i; 105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->alloc_stems == num) { 107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley stem_t *tmp_arr; 108f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->alloc_stems = data->alloc_stems * 2 + 16; 1095b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich tmp_arr = (stem_t *) realloc(data->stem_arr, 110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley sizeof(stem_t) * data->alloc_stems); 111f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!tmp_arr) 112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->stem_arr = tmp_arr; 114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->stem_arr[num].len = stem_len; 1165b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich data->stem_arr[num].buf = (char *) malloc(stem_len + 1); 117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!data->stem_arr[num].buf) 118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(data->stem_arr[num].buf, buf, stem_len); 120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->stem_arr[num].buf[stem_len] = '\0'; 121f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->num_stems++; 122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley buf += stem_len; 123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return num; 124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* find the stem of a file name, returns the index into stem_arr (or -1 if 127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * there is no match - IE for a file in the root directory or a regex that is 128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * too complex for us). Makes buf point to the text AFTER the stem. */ 129f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int find_stem_from_file(struct saved_data *data, const char **buf) 130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int i; 132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int stem_len = get_stem_from_file_name(*buf); 133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!stem_len) 135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < data->num_stems; i++) { 137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (stem_len == data->stem_arr[i].len 138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && !strncmp(*buf, data->stem_arr[i].buf, stem_len)) { 139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *buf += stem_len; 140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return i; 141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Warn about duplicate specifications. 148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 149f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int nodups_specs(struct saved_data *data, const char *path) 150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int rc = 0; 152f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int ii, jj; 153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct spec *curr_spec, *spec_arr = data->spec_arr; 154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (ii = 0; ii < data->nspec; ii++) { 156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley curr_spec = &spec_arr[ii]; 157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (jj = ii + 1; jj < data->nspec; jj++) { 158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if ((!strcmp 159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (spec_arr[jj].regex_str, curr_spec->regex_str)) 160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && (!spec_arr[jj].mode || !curr_spec->mode 161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley || spec_arr[jj].mode == curr_spec->mode)) { 162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rc = -1; 163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EINVAL; 164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (strcmp 165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (spec_arr[jj].lr.ctx_raw, 166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley curr_spec->lr.ctx_raw)) { 167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log 168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (SELINUX_ERROR, 169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: Multiple different specifications for %s (%s and %s).\n", 170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, curr_spec->regex_str, 171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[jj].lr.ctx_raw, 172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley curr_spec->lr.ctx_raw); 173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log 175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (SELINUX_ERROR, 176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: Multiple same specifications for %s.\n", 177f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, curr_spec->regex_str); 178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 182f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return rc; 183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 184f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* Determine if the regular expression specification has any meta characters. */ 186f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void spec_hasMetaChars(struct spec *spec) 187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *c; 1890e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley size_t len; 190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *end; 191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c = spec->regex_str; 193f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = strlen(spec->regex_str); 194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley end = c + len; 195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec->hasMetaChars = 0; 1970e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley spec->prefix_len = len; 198f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 199f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Look at each character in the RE specification string for a 200f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * meta character. Return when any meta character reached. */ 201f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (c != end) { 202f074036424618c130dacb3464465a8b40bffef5Stephen Smalley switch (*c) { 203f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '.': 204f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '^': 205f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '$': 206f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '?': 207f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '*': 208f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '+': 209f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '|': 210f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '[': 211f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '(': 212f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '{': 213f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec->hasMetaChars = 1; 2140e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley spec->prefix_len = c - spec->regex_str; 215f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return; 216f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '\\': /* skip the next character */ 217f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c++; 218f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 219f074036424618c130dacb3464465a8b40bffef5Stephen Smalley default: 220f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 221f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 222f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 223f074036424618c130dacb3464465a8b40bffef5Stephen Smalley c++; 224f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 225f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return; 226f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 227f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 228d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevichstatic int compile_regex(struct saved_data *data, spec_t *spec, const char **errbuf) 229f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 230d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich const char *tmperrbuf; 231f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *reg_buf, *anchored_regex, *cp; 232f074036424618c130dacb3464465a8b40bffef5Stephen Smalley stem_t *stem_arr = data->stem_arr; 233f074036424618c130dacb3464465a8b40bffef5Stephen Smalley size_t len; 234d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich int erroff; 235f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 236f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (spec->regcomp) 237f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; /* already done */ 238f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 239f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->ncomp++; /* how many compiled regexes required */ 240f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 241f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Skip the fixed stem. */ 242f074036424618c130dacb3464465a8b40bffef5Stephen Smalley reg_buf = spec->regex_str; 243f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (spec->stem_id >= 0) 244f074036424618c130dacb3464465a8b40bffef5Stephen Smalley reg_buf += stem_arr[spec->stem_id].len; 245f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 246f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Anchor the regular expression. */ 247f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = strlen(reg_buf); 2485b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich cp = anchored_regex = (char *) malloc(len + 3); 249f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!anchored_regex) 250f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 251f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Create ^...$ regexp. */ 252f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *cp++ = '^'; 253f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(cp, reg_buf, len); 254f074036424618c130dacb3464465a8b40bffef5Stephen Smalley cp += len; 255f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *cp++ = '$'; 256f074036424618c130dacb3464465a8b40bffef5Stephen Smalley *cp = '\0'; 257f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 258f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Compile the regular expression. */ 25951fc85bc845bf6c7de1962efe6458ec701051162Nick Kralevich spec->regex = pcre_compile(anchored_regex, PCRE_DOTALL, &tmperrbuf, &erroff, NULL); 260d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich free(anchored_regex); 261d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (!spec->regex) { 262d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (errbuf) 263d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich *errbuf=tmperrbuf; 264d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich return -1; 265d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich } 266d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich 267d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich spec->sd = pcre_study(spec->regex, 0, &tmperrbuf); 268f74bc4e9ae72f60e9d1173802fcc275a9339c261Stephen Smalley if (!spec->sd && tmperrbuf) { 269d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (errbuf) 270d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich *errbuf=tmperrbuf; 271f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 272f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 273f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 274f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Done. */ 275f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec->regcomp = 1; 276f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 277f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 278f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 279f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 280f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 281f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int process_line(struct selabel_handle *rec, 282f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *path, const char *prefix, 283f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *line_buf, int pass, unsigned lineno) 284f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 285f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int items, len; 286f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char buf1[BUFSIZ], buf2[BUFSIZ], buf3[BUFSIZ]; 287f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *buf_p, *regex = buf1, *type = buf2, *context = buf3; 288f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data = (struct saved_data *)rec->data; 289f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_t *spec_arr = data->spec_arr; 290f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int nspec = data->nspec; 291f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 292f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = strlen(line_buf); 293f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (line_buf[len - 1] == '\n') 294f074036424618c130dacb3464465a8b40bffef5Stephen Smalley line_buf[len - 1] = 0; 295f074036424618c130dacb3464465a8b40bffef5Stephen Smalley buf_p = line_buf; 296f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (isspace(*buf_p)) 297f074036424618c130dacb3464465a8b40bffef5Stephen Smalley buf_p++; 298f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Skip comment lines and empty lines. */ 299f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (*buf_p == '#' || *buf_p == 0) 300f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 301f074036424618c130dacb3464465a8b40bffef5Stephen Smalley items = sscanf(line_buf, "%255s %255s %255s", regex, type, context); 302f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (items < 2) { 303f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 304f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: line %d is missing fields, skipping\n", path, 305f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno); 306f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 307f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else if (items == 2) { 308f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* The type field is optional. */ 309f074036424618c130dacb3464465a8b40bffef5Stephen Smalley context = type; 310f074036424618c130dacb3464465a8b40bffef5Stephen Smalley type = NULL; 311f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 312f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 313f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = get_stem_from_spec(regex); 314f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (len && prefix && strncmp(prefix, regex, len)) { 315f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Stem of regex does not match requested prefix, discard. */ 316f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 317f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 318f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 319f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (pass == 1) { 320f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* On the second pass, process and store the specification in spec. */ 321d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich const char *errbuf = NULL; 322f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].stem_id = find_stem_from_spec(data, regex); 323f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].regex_str = strdup(regex); 324f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!spec_arr[nspec].regex_str) { 325f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 326f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: out of memory at line %d on regex %s\n", 327f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, lineno, regex); 328f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 329f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 330f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 331f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) { 332f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 333f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: line %d has invalid regex %s: %s\n", 334f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, lineno, regex, 335f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (errbuf ? errbuf : "out of memory")); 336f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 337f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 338f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Convert the type string to a mode format */ 339f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = 0; 340f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!type) 341f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto skip_type; 342f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].type_str = strdup(type); 343f074036424618c130dacb3464465a8b40bffef5Stephen Smalley len = strlen(type); 344f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (type[0] != '-' || len != 2) { 345f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 346f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: line %d has invalid file type %s\n", 347f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, lineno, type); 348f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 349f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 350f074036424618c130dacb3464465a8b40bffef5Stephen Smalley switch (type[1]) { 351f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 'b': 352f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFBLK; 353f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 354f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 'c': 355f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFCHR; 356f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 357f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 'd': 358f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFDIR; 359f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 360f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 'p': 361f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFIFO; 362f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 363f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 'l': 364f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFLNK; 365f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 366f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case 's': 367f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFSOCK; 368f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 369f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case '-': 370f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].mode = S_IFREG; 371f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 372f074036424618c130dacb3464465a8b40bffef5Stephen Smalley default: 373f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 374f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "%s: line %d has invalid file type %s\n", 375f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path, lineno, type); 376f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 377f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 378f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 379f074036424618c130dacb3464465a8b40bffef5Stephen Smalley skip_type: 380f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[nspec].lr.ctx_raw = strdup(context); 381f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 38261e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley if (strcmp(context, "<<none>>") && rec->validating) { 38361e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) { 38461e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley selinux_log(SELINUX_WARNING, 38561e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley "%s: line %d has invalid context %s\n", 38661e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley path, lineno, spec_arr[nspec].lr.ctx_raw); 38761e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley } 38861e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley } 38961e917ad2f1fbf39b3205d7568fcd3684b0ccda6Stephen Smalley 390f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Determine if specification has 391f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * any meta characters in the RE */ 392f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_hasMetaChars(&spec_arr[nspec]); 393f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 394f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 395f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->nspec = ++nspec; 396f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return 0; 397f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 398f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 399a2e47cd90d84d48cde19575d044577a3fc7a4000Stephen Smalleystatic int init(struct selabel_handle *rec, const struct selinux_opt *opts, 400f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned n) 401f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 402f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data = (struct saved_data *)rec->data; 403f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *path = NULL; 404f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *prefix = NULL; 405f074036424618c130dacb3464465a8b40bffef5Stephen Smalley FILE *fp; 406f074036424618c130dacb3464465a8b40bffef5Stephen Smalley FILE *localfp = NULL; 407f074036424618c130dacb3464465a8b40bffef5Stephen Smalley FILE *homedirfp = NULL; 408f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char local_path[PATH_MAX + 1]; 409f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char homedir_path[PATH_MAX + 1]; 410f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char line_buf[BUFSIZ]; 411f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int lineno, pass, i, j, maxnspec; 412f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_t *spec_copy = NULL; 413f074036424618c130dacb3464465a8b40bffef5Stephen Smalley int status = -1, baseonly = 0; 414f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct stat sb; 415f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 416f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Process arguments */ 417f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (n--) 418f074036424618c130dacb3464465a8b40bffef5Stephen Smalley switch(opts[n].type) { 419f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case SELABEL_OPT_PATH: 420f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path = opts[n].value; 421f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 422f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case SELABEL_OPT_SUBSET: 423f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prefix = opts[n].value; 424f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 425f074036424618c130dacb3464465a8b40bffef5Stephen Smalley case SELABEL_OPT_BASEONLY: 426f074036424618c130dacb3464465a8b40bffef5Stephen Smalley baseonly = !!opts[n].value; 427f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 428f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 429f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 430f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Open the specification file. */ 431f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if ((fp = fopen(path, "r")) == NULL) 432f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 433f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 434f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (fstat(fileno(fp), &sb) < 0) 435f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 436f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!S_ISREG(sb.st_mode)) { 437f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = EINVAL; 438f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 439f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 440f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 441f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!baseonly) { 442f074036424618c130dacb3464465a8b40bffef5Stephen Smalley snprintf(homedir_path, sizeof(homedir_path), "%s.homedirs", 443f074036424618c130dacb3464465a8b40bffef5Stephen Smalley path); 444f074036424618c130dacb3464465a8b40bffef5Stephen Smalley homedirfp = fopen(homedir_path, "r"); 445f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 446f074036424618c130dacb3464465a8b40bffef5Stephen Smalley snprintf(local_path, sizeof(local_path), "%s.local", path); 447f074036424618c130dacb3464465a8b40bffef5Stephen Smalley localfp = fopen(local_path, "r"); 448f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 449f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 450f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* 451f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Perform two passes over the specification file. 452f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * The first pass counts the number of specifications and 453f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * performs simple validation of the input. At the end 454f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * of the first pass, the spec array is allocated. 455f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * The second pass performs detailed validation of the input 456f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * and fills in the spec array. 457f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 458f074036424618c130dacb3464465a8b40bffef5Stephen Smalley maxnspec = UINT_MAX / sizeof(spec_t); 459f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (pass = 0; pass < 2; pass++) { 460f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno = 0; 461f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->nspec = 0; 462f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->ncomp = 0; 463f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (fgets(line_buf, sizeof line_buf - 1, fp) 464f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && data->nspec < maxnspec) { 465f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (process_line(rec, path, prefix, line_buf, 466f074036424618c130dacb3464465a8b40bffef5Stephen Smalley pass, ++lineno) != 0) 467f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 468f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 469f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (pass == 1) { 470f074036424618c130dacb3464465a8b40bffef5Stephen Smalley status = nodups_specs(data, path); 471f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (status) 472f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 473f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 474f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno = 0; 475f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (homedirfp) 476f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (fgets(line_buf, sizeof line_buf - 1, homedirfp) 477f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && data->nspec < maxnspec) { 478f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (process_line 479f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (rec, homedir_path, prefix, 480f074036424618c130dacb3464465a8b40bffef5Stephen Smalley line_buf, pass, ++lineno) != 0) 481f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 482f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 483f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 484f074036424618c130dacb3464465a8b40bffef5Stephen Smalley lineno = 0; 485f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (localfp) 486f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (fgets(line_buf, sizeof line_buf - 1, localfp) 487f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && data->nspec < maxnspec) { 488f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (process_line 489f074036424618c130dacb3464465a8b40bffef5Stephen Smalley (rec, local_path, prefix, line_buf, 490f074036424618c130dacb3464465a8b40bffef5Stephen Smalley pass, ++lineno) != 0) 491f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 492f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 493f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 494f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (pass == 0) { 495f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->nspec == 0) { 496f074036424618c130dacb3464465a8b40bffef5Stephen Smalley status = 0; 497f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 498f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 499f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (NULL == (data->spec_arr = 5005b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich (spec_t *) malloc(sizeof(spec_t) * data->nspec))) 501f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 502f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); 503f074036424618c130dacb3464465a8b40bffef5Stephen Smalley maxnspec = data->nspec; 504f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rewind(fp); 505f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (homedirfp) 506f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rewind(homedirfp); 507f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (localfp) 508f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rewind(localfp); 509f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 510f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 511f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 512f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Move exact pathname specifications to the end. */ 5135b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich spec_copy = (spec_t *) malloc(sizeof(spec_t) * data->nspec); 514f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!spec_copy) 515f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 516f074036424618c130dacb3464465a8b40bffef5Stephen Smalley j = 0; 517f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < data->nspec; i++) 518f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->spec_arr[i].hasMetaChars) 519f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(&spec_copy[j++], 520f074036424618c130dacb3464465a8b40bffef5Stephen Smalley &data->spec_arr[i], sizeof(spec_t)); 521f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < data->nspec; i++) 522f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!data->spec_arr[i].hasMetaChars) 523f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(&spec_copy[j++], 524f074036424618c130dacb3464465a8b40bffef5Stephen Smalley &data->spec_arr[i], sizeof(spec_t)); 525f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(data->spec_arr); 526f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data->spec_arr = spec_copy; 527f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 528f074036424618c130dacb3464465a8b40bffef5Stephen Smalley status = 0; 529f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyfinish: 530f074036424618c130dacb3464465a8b40bffef5Stephen Smalley fclose(fp); 531f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->spec_arr != spec_copy) 532f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(data->spec_arr); 533f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (homedirfp) 534f074036424618c130dacb3464465a8b40bffef5Stephen Smalley fclose(homedirfp); 535f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (localfp) 536f074036424618c130dacb3464465a8b40bffef5Stephen Smalley fclose(localfp); 537f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return status; 538f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 539f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 540f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* 541f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Backend interface routines 542f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 543f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void closef(struct selabel_handle *rec) 544f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 545f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data = (struct saved_data *)rec->data; 546f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct spec *spec; 547f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct stem *stem; 548f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int i; 549f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 550f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < data->nspec; i++) { 551f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec = &data->spec_arr[i]; 552f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(spec->regex_str); 553f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(spec->type_str); 554f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(spec->lr.ctx_raw); 555f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(spec->lr.ctx_trans); 556d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (spec->regcomp) { 557d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich pcre_free(spec->regex); 558d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich pcre_free_study(spec->sd); 559d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich } 560f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 561f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 562f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < (unsigned int)data->num_stems; i++) { 563f074036424618c130dacb3464465a8b40bffef5Stephen Smalley stem = &data->stem_arr[i]; 564f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(stem->buf); 565f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 566f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 567f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->spec_arr) 568f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(data->spec_arr); 569f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (data->stem_arr) 570f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(data->stem_arr); 571f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 572f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(data); 573f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 574f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 575be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalleystatic spec_t *lookup_common(struct selabel_handle *rec, 576be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley const char *key, 577be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley int type, 578be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley bool partial) 579f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 580f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data = (struct saved_data *)rec->data; 581f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_t *spec_arr = data->spec_arr; 582d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich int i, rc, file_stem, pcre_options = 0; 583f074036424618c130dacb3464465a8b40bffef5Stephen Smalley mode_t mode = (mode_t)type; 584f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *buf; 585be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley spec_t *ret = NULL; 586f074036424618c130dacb3464465a8b40bffef5Stephen Smalley char *clean_key = NULL; 587f074036424618c130dacb3464465a8b40bffef5Stephen Smalley const char *prev_slash, *next_slash; 588f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int sofar = 0; 589f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 590f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!data->nspec) { 591f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = ENOENT; 592f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 593f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 594f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 595f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* Remove duplicate slashes */ 596f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if ((next_slash = strstr(key, "//"))) { 5975b91e6297719ee29fc4d3795a4bc9d7343b30fb0Nick Kralevich clean_key = (char *) malloc(strlen(key) + 1); 598f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!clean_key) 599f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 600f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prev_slash = key; 601f074036424618c130dacb3464465a8b40bffef5Stephen Smalley while (next_slash) { 602f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memcpy(clean_key + sofar, prev_slash, next_slash - prev_slash); 603f074036424618c130dacb3464465a8b40bffef5Stephen Smalley sofar += next_slash - prev_slash; 604f074036424618c130dacb3464465a8b40bffef5Stephen Smalley prev_slash = next_slash + 1; 605f074036424618c130dacb3464465a8b40bffef5Stephen Smalley next_slash = strstr(prev_slash, "//"); 606f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 607f074036424618c130dacb3464465a8b40bffef5Stephen Smalley strcpy(clean_key + sofar, prev_slash); 608f074036424618c130dacb3464465a8b40bffef5Stephen Smalley key = clean_key; 609f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 610f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 611f074036424618c130dacb3464465a8b40bffef5Stephen Smalley buf = key; 612f074036424618c130dacb3464465a8b40bffef5Stephen Smalley file_stem = find_stem_from_file(data, &buf); 613f074036424618c130dacb3464465a8b40bffef5Stephen Smalley mode &= S_IFMT; 614f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 615d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (partial) 616d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich pcre_options |= PCRE_PARTIAL_SOFT; 617d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich 618f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* 619f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Check for matching specifications in reverse order, so that 620f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * the last matching specification is used. 621f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */ 622f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = data->nspec - 1; i >= 0; i--) { 623f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* if the spec in question matches no stem or has the same 624f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * stem as the file AND if the spec in question has no mode 625f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * specified or if the mode matches the file mode then we do 626f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * a regex check */ 627f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if ((spec_arr[i].stem_id == -1 628f074036424618c130dacb3464465a8b40bffef5Stephen Smalley || spec_arr[i].stem_id == file_stem) 629f074036424618c130dacb3464465a8b40bffef5Stephen Smalley && (!mode || !spec_arr[i].mode 630f074036424618c130dacb3464465a8b40bffef5Stephen Smalley || mode == spec_arr[i].mode)) { 631f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (compile_regex(data, &spec_arr[i], NULL) < 0) 632f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 633f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (spec_arr[i].stem_id == -1) 634d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich rc = pcre_exec(spec_arr[i].regex, spec_arr[i].sd, key, strlen(key), 0, pcre_options, NULL, 0); 635f074036424618c130dacb3464465a8b40bffef5Stephen Smalley else 636d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich rc = pcre_exec(spec_arr[i].regex, spec_arr[i].sd, buf, strlen(buf), 0, pcre_options, NULL, 0); 637f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 638f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (rc == 0) { 639f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].matches++; 640f074036424618c130dacb3464465a8b40bffef5Stephen Smalley break; 641d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich } else if (partial && rc == PCRE_ERROR_PARTIAL) 642d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich break; 6430e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley 644d0b768abcd2b4adb1853ac38e59aa80f09872ac3Nick Kralevich if (rc == PCRE_ERROR_NOMATCH) 645f074036424618c130dacb3464465a8b40bffef5Stephen Smalley continue; 646f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* else it's an error */ 647f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 648f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 649f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 650f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 651f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (i < 0 || strcmp(spec_arr[i].lr.ctx_raw, "<<none>>") == 0) { 652f074036424618c130dacb3464465a8b40bffef5Stephen Smalley /* No matching specification. */ 653f074036424618c130dacb3464465a8b40bffef5Stephen Smalley errno = ENOENT; 654f074036424618c130dacb3464465a8b40bffef5Stephen Smalley goto finish; 655f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 656f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 657be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley ret = &spec_arr[i]; 658f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 659f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyfinish: 660f074036424618c130dacb3464465a8b40bffef5Stephen Smalley free(clean_key); 661f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return ret; 662f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 663f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 6640e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalleystatic struct selabel_lookup_rec *lookup(struct selabel_handle *rec, 6650e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley const char *key, int type) 6660e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley{ 667be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley spec_t *spec; 668be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley spec = lookup_common(rec, key, type, false); 669be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (spec) 670be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley return &spec->lr; 671be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley return NULL; 6720e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley} 6730e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley 6740e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalleystatic bool partial_match(struct selabel_handle *rec, const char *key) 6750e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley{ 6760e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley return lookup_common(rec, key, 0, true) ? true : false; 6770e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley} 6780e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley 679be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalleystatic struct selabel_lookup_rec *lookup_best_match(struct selabel_handle *rec, 680be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley const char *key, 681be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley const char **aliases, 682be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley int type) 683be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley{ 684be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley size_t n, i; 685be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley int best = -1; 686be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley spec_t **specs; 687be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley size_t prefix_len = 0; 688be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley struct selabel_lookup_rec *lr = NULL; 689be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 690be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (!aliases || !aliases[0]) 691be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley return lookup(rec, key, type); 692be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 693be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley for (n = 0; aliases[n]; n++) 694be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley ; 695be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 696be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley specs = calloc(n+1, sizeof(spec_t *)); 697be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (!specs) 698be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley return NULL; 699be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley specs[0] = lookup_common(rec, key, type, false); 700be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (specs[0]) { 701be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (!specs[0]->hasMetaChars) { 702be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley /* exact match on key */ 703be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley lr = &specs[0]->lr; 704be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley goto out; 705be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 706be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley best = 0; 707be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley prefix_len = specs[0]->prefix_len; 708be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 709be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley for (i = 1; i <= n; i++) { 710be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley specs[i] = lookup_common(rec, aliases[i-1], type, false); 711be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (specs[i]) { 712be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (!specs[i]->hasMetaChars) { 713be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley /* exact match on alias */ 714be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley lr = &specs[i]->lr; 715be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley goto out; 716be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 717be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (specs[i]->prefix_len > prefix_len) { 718be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley best = i; 719be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley prefix_len = specs[i]->prefix_len; 720be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 721be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 722be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 723be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 724be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley if (best >= 0) { 725be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley /* longest fixed prefix match on key or alias */ 726be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley lr = &specs[best]->lr; 727be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley } 728be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 729be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalleyout: 730be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley free(specs); 731be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley return lr; 732be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley} 733be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley 734f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void stats(struct selabel_handle *rec) 735f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 736f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data = (struct saved_data *)rec->data; 737f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned int i, nspec = data->nspec; 738f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_t *spec_arr = data->spec_arr; 739f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 740f074036424618c130dacb3464465a8b40bffef5Stephen Smalley for (i = 0; i < nspec; i++) { 741f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (spec_arr[i].matches == 0) { 742f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (spec_arr[i].type_str) { 743f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 744f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "Warning! No matches for (%s, %s, %s)\n", 745f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].regex_str, 746f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].type_str, 747f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].lr.ctx_raw); 748f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } else { 749f074036424618c130dacb3464465a8b40bffef5Stephen Smalley selinux_log(SELINUX_WARNING, 750f074036424618c130dacb3464465a8b40bffef5Stephen Smalley "Warning! No matches for (%s, %s)\n", 751f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].regex_str, 752f074036424618c130dacb3464465a8b40bffef5Stephen Smalley spec_arr[i].lr.ctx_raw); 753f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 754f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 755f074036424618c130dacb3464465a8b40bffef5Stephen Smalley } 756f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 757f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 758a2e47cd90d84d48cde19575d044577a3fc7a4000Stephen Smalleyint selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts, 759f074036424618c130dacb3464465a8b40bffef5Stephen Smalley unsigned nopts) 760f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ 761f074036424618c130dacb3464465a8b40bffef5Stephen Smalley struct saved_data *data; 762f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 763f074036424618c130dacb3464465a8b40bffef5Stephen Smalley data = (struct saved_data *)malloc(sizeof(*data)); 764f074036424618c130dacb3464465a8b40bffef5Stephen Smalley if (!data) 765f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return -1; 766f074036424618c130dacb3464465a8b40bffef5Stephen Smalley memset(data, 0, sizeof(*data)); 767f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 768f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rec->data = data; 769f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rec->func_close = &closef; 770f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rec->func_stats = &stats; 771f074036424618c130dacb3464465a8b40bffef5Stephen Smalley rec->func_lookup = &lookup; 7720e7340fb99b931540e2baf4778abeb53d40084e7Stephen Smalley rec->func_partial_match = &partial_match; 773be7f5e8814c4954aca51d3f95455c5d9d527658cStephen Smalley rec->func_lookup_best_match = &lookup_best_match; 774f074036424618c130dacb3464465a8b40bffef5Stephen Smalley 775f074036424618c130dacb3464465a8b40bffef5Stephen Smalley return init(rec, opts, nopts); 776f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} 777