summaryrefslogtreecommitdiff
path: root/src/label_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/label_file.c')
-rw-r--r--src/label_file.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/src/label_file.c b/src/label_file.c
index 79239c4..9923e38 100644
--- a/src/label_file.c
+++ b/src/label_file.c
@@ -33,6 +33,7 @@ typedef struct spec {
int matches; /* number of matching pathnames */
int hasMetaChars; /* regular expression has meta-chars */
int stem_id; /* indicates which stem-compression item */
+ size_t prefix_len; /* length of fixed path prefix */
} spec_t;
/* A regular expression stem */
@@ -184,7 +185,7 @@ static int nodups_specs(struct saved_data *data, const char *path)
static void spec_hasMetaChars(struct spec *spec)
{
char *c;
- int len;
+ size_t len;
char *end;
c = spec->regex_str;
@@ -192,6 +193,7 @@ static void spec_hasMetaChars(struct spec *spec)
end = c + len;
spec->hasMetaChars = 0;
+ spec->prefix_len = len;
/* Look at each character in the RE specification string for a
* meta character. Return when any meta character reached. */
@@ -208,6 +210,7 @@ static void spec_hasMetaChars(struct spec *spec)
case '(':
case '{':
spec->hasMetaChars = 1;
+ spec->prefix_len = c - spec->regex_str;
return;
case '\\': /* skip the next character */
c++;
@@ -566,8 +569,9 @@ static void closef(struct selabel_handle *rec)
free(data);
}
-static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
- const char *key, int type)
+static struct selabel_lookup_rec *lookup_common(struct selabel_handle *rec,
+ const char *key, int type,
+ bool partial)
{
struct saved_data *data = (struct saved_data *)rec->data;
spec_t *spec_arr = data->spec_arr;
@@ -578,6 +582,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
char *clean_key = NULL;
const char *prev_slash, *next_slash;
unsigned int sofar = 0;
+ size_t keylen = strlen(key);
if (!data->nspec) {
errno = ENOENT;
@@ -628,6 +633,29 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
spec_arr[i].matches++;
break;
}
+
+ if (partial) {
+ /*
+ * We already checked above to see if the
+ * key has any direct match. Now we just need
+ * to check for partial matches.
+ * Since POSIX regex functions do not support
+ * partial match, we crudely approximate it
+ * via a prefix match.
+ * This is imprecise and could yield
+ * false positives or negatives but
+ * appears to work with our current set of
+ * regex strings.
+ * Convert to using pcre partial match
+ * if/when pcre becomes available in Android.
+ */
+ if (spec_arr[i].prefix_len > 1 &&
+ !strncmp(key, spec_arr[i].regex_str,
+ keylen < spec_arr[i].prefix_len ?
+ keylen : spec_arr[i].prefix_len))
+ break;
+ }
+
if (rc == REG_NOMATCH)
continue;
/* else it's an error */
@@ -648,6 +676,17 @@ finish:
return ret;
}
+static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
+ const char *key, int type)
+{
+ return lookup_common(rec, key, type, false);
+}
+
+static bool partial_match(struct selabel_handle *rec, const char *key)
+{
+ return lookup_common(rec, key, 0, true) ? true : false;
+}
+
static void stats(struct selabel_handle *rec)
{
struct saved_data *data = (struct saved_data *)rec->data;
@@ -686,6 +725,7 @@ int selabel_file_init(struct selabel_handle *rec, const struct selinux_opt *opts
rec->func_close = &closef;
rec->func_stats = &stats;
rec->func_lookup = &lookup;
+ rec->func_partial_match = &partial_match;
return init(rec, opts, nopts);
}