1. seandroid
  2. Untitled project
  3. external/libselinux

Commits

Stephen Smalley  committed d490b7f Merge

Merge branch 'master' into seandroid

  • Participants
  • Parent commits 8e50a55, be7f5e8
  • Branches seandroid

Comments (0)

Files changed (4)

File include/selinux/label.h

View file
 
 bool selabel_partial_match(struct selabel_handle *handle, const char *key);
 
+int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
+			      const char *key, const char **aliases, int type);
+
 /**
  * selabel_stats - log labeling operation statistics.
  * @handle: specifies backend instance to query

File src/label.c

View file
 	return rec->func_partial_match(rec, key);
 }
 
+int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
+			      const char *key, const char **aliases, int type)
+{
+	struct selabel_lookup_rec *lr;
+
+	if (!rec->func_lookup_best_match) {
+		errno = ENOTSUP;
+		return -1;
+	}
+
+	lr = rec->func_lookup_best_match(rec, key, aliases, type);
+	if (!lr)
+		return -1;
+
+	*con = strdup(lr->ctx_raw);
+	return *con ? 0 : -1;
+}
+
 void selabel_close(struct selabel_handle *rec)
 {
 	rec->func_close(rec);

File src/label_file.c

View file
 	free(data);
 }
 
-static struct selabel_lookup_rec *lookup_common(struct selabel_handle *rec,
-						const char *key, int type,
-						bool partial)
+static spec_t *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;
 	int i, rc, file_stem;
 	mode_t mode = (mode_t)type;
 	const char *buf;
-	struct selabel_lookup_rec *ret = NULL;
+	spec_t *ret = NULL;
 	char *clean_key = NULL;
 	const char *prev_slash, *next_slash;
 	unsigned int sofar = 0;
 		goto finish;
 	}
 
-	ret = &spec_arr[i].lr;
+	ret = &spec_arr[i];
 
 finish:
 	free(clean_key);
 static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
 					 const char *key, int type)
 {
-	return lookup_common(rec, key, type, false);
+	spec_t *spec;
+	spec = lookup_common(rec, key, type, false);
+	if (spec)
+		return &spec->lr;
+	return NULL;
 }
 
 static bool partial_match(struct selabel_handle *rec, const char *key)
 	return lookup_common(rec, key, 0, true) ? true : false;
 }
 
+static struct selabel_lookup_rec *lookup_best_match(struct selabel_handle *rec,
+						    const char *key,
+						    const char **aliases,
+						    int type)
+{
+	size_t n, i;
+	int best = -1;
+	spec_t **specs;
+	size_t prefix_len = 0;
+	struct selabel_lookup_rec *lr = NULL;
+
+	if (!aliases || !aliases[0])
+		return lookup(rec, key, type);
+
+	for (n = 0; aliases[n]; n++)
+		;
+
+	specs = calloc(n+1, sizeof(spec_t *));
+	if (!specs)
+		return NULL;
+	specs[0] = lookup_common(rec, key, type, false);
+	if (specs[0]) {
+		if (!specs[0]->hasMetaChars) {
+			/* exact match on key */
+			lr = &specs[0]->lr;
+			goto out;
+		}
+		best = 0;
+		prefix_len = specs[0]->prefix_len;
+	}
+	for (i = 1; i <= n; i++) {
+		specs[i] = lookup_common(rec, aliases[i-1], type, false);
+		if (specs[i]) {
+			if (!specs[i]->hasMetaChars) {
+				/* exact match on alias */
+				lr = &specs[i]->lr;
+				goto out;
+			}
+			if (specs[i]->prefix_len > prefix_len) {
+				best = i;
+				prefix_len = specs[i]->prefix_len;
+			}
+		}
+	}
+
+	if (best >= 0) {
+		/* longest fixed prefix match on key or alias */
+		lr = &specs[best]->lr;
+	}
+
+out:
+	free(specs);
+	return lr;
+}
+
 static void stats(struct selabel_handle *rec)
 {
 	struct saved_data *data = (struct saved_data *)rec->data;
 	rec->func_stats = &stats;
 	rec->func_lookup = &lookup;
 	rec->func_partial_match = &partial_match;
+	rec->func_lookup_best_match = &lookup_best_match;
 
 	return init(rec, opts, nopts);
 }

File src/label_internal.h

View file
 	void (*func_close) (struct selabel_handle *h);
 	void (*func_stats) (struct selabel_handle *h);
 	bool (*func_partial_match) (struct selabel_handle *h, const char *key);
+	struct selabel_lookup_rec *(*func_lookup_best_match) (struct selabel_handle *h,
+							 const char *key,
+							 const char **aliases,
+							 int type);
 
 	/* supports backend-specific state information */
 	void *data;