summaryrefslogtreecommitdiff
path: root/src/label_android_property.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/label_android_property.c')
-rw-r--r--src/label_android_property.c350
1 files changed, 0 insertions, 350 deletions
diff --git a/src/label_android_property.c b/src/label_android_property.c
deleted file mode 100644
index b0a807c..0000000
--- a/src/label_android_property.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Property Service contexts backend for labeling Android
- * property keys
- */
-
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include "callbacks.h"
-#include "label_internal.h"
-
-/* A property security context specification. */
-typedef struct spec {
- struct selabel_lookup_rec lr; /* holds contexts for lookup result */
- char *property_key; /* property key string */
-} spec_t;
-
-/* Our stored configuration */
-struct saved_data {
- /*
- * The array of specifications is sorted for longest
- * prefix match
- */
- spec_t *spec_arr;
- unsigned int nspec; /* total number of specifications */
-};
-
-static int cmp(const void *A, const void *B)
-{
- const struct spec *sp1 = A, *sp2 = B;
-
- if (strncmp(sp1->property_key, "*", 1) == 0)
- return 1;
- if (strncmp(sp2->property_key, "*", 1) == 0)
- return -1;
-
- size_t L1 = strlen(sp1->property_key);
- size_t L2 = strlen(sp2->property_key);
-
- return (L1 < L2) - (L1 > L2);
-}
-
-/*
- * Warn about duplicate specifications.
- */
-static int nodups_specs(struct saved_data *data, const char *path)
-{
- int rc = 0;
- unsigned int ii, jj;
- struct spec *curr_spec, *spec_arr = data->spec_arr;
-
- for (ii = 0; ii < data->nspec; ii++) {
- curr_spec = &spec_arr[ii];
- for (jj = ii + 1; jj < data->nspec; jj++) {
- if (!strcmp(spec_arr[jj].property_key,
- curr_spec->property_key)) {
- rc = -1;
- errno = EINVAL;
- if (strcmp(spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw)) {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple different specifications for %s (%s and %s).\n",
- path, curr_spec->property_key,
- spec_arr[jj].lr.ctx_raw,
- curr_spec->lr.ctx_raw);
- } else {
- selinux_log
- (SELINUX_ERROR,
- "%s: Multiple same specifications for %s.\n",
- path, curr_spec->property_key);
- }
- }
- }
- }
- return rc;
-}
-
-static int process_line(struct selabel_handle *rec,
- const char *path, char *line_buf,
- int pass, unsigned lineno)
-{
- int items;
- char *prop = NULL, *context = NULL;
- struct saved_data *data = (struct saved_data *)rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int nspec = data->nspec;
- const char *errbuf = NULL;
-
- items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
- if (items < 0) {
- items = errno;
- selinux_log(SELINUX_ERROR,
- "%s: line %u error due to: %s\n", path,
- lineno, errbuf ?: strerror(errno));
- errno = items;
- return -1;
- }
-
- if (items == 0)
- return items;
-
- if (items != 2) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u is missing fields\n", path,
- lineno);
- free(prop);
- errno = EINVAL;
- return -1;
- }
-
- if (pass == 0) {
- free(prop);
- free(context);
- } else if (pass == 1) {
- /* On the second pass, process and store the specification in spec. */
- spec_arr[nspec].property_key = prop;
- spec_arr[nspec].lr.ctx_raw = context;
-
- if (rec->validating) {
- if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) {
- selinux_log(SELINUX_ERROR,
- "%s: line %u has invalid context %s\n",
- path, lineno, spec_arr[nspec].lr.ctx_raw);
- errno = EINVAL;
- return -1;
- }
- }
- }
-
- data->nspec = ++nspec;
- return 0;
-}
-
-static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
- unsigned n)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- const char *path = NULL;
- FILE *fp;
- char line_buf[BUFSIZ];
- unsigned int lineno, maxnspec, pass;
- int status = -1;
- struct stat sb;
-
- /* Process arguments */
- while (n--)
- switch (opts[n].type) {
- case SELABEL_OPT_PATH:
- path = opts[n].value;
- break;
- }
-
- if (!path)
- return -1;
-
- /* Open the specification file. */
- if ((fp = fopen(path, "r")) == NULL)
- return -1;
-
- if (fstat(fileno(fp), &sb) < 0)
- goto finish;
- errno = EINVAL;
- if (!S_ISREG(sb.st_mode))
- goto finish;
-
- /*
- * Two passes of the specification file. First is to get the size.
- * After the first pass, the spec array is malloced to the appropriate
- * size. Second pass is to populate the spec array and check for
- * dups.
- */
- maxnspec = UINT_MAX / sizeof(spec_t);
- for (pass = 0; pass < 2; pass++) {
- data->nspec = 0;
- lineno = 0;
-
- while (fgets(line_buf, sizeof(line_buf) - 1, fp)
- && data->nspec < maxnspec) {
- if (process_line(rec, path, line_buf, pass, ++lineno)
- != 0)
- goto finish;
- }
-
- if (pass == 1) {
- status = nodups_specs(data, path);
-
- if (status)
- goto finish;
- }
-
- if (pass == 0) {
- if (data->nspec == 0) {
- status = 0;
- goto finish;
- }
-
- if (NULL == (data->spec_arr =
- malloc(sizeof(spec_t) * data->nspec)))
- goto finish;
-
- memset(data->spec_arr, 0, sizeof(spec_t) * data->nspec);
- maxnspec = data->nspec;
- rewind(fp);
- }
- }
-
- qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp);
-
- status = 0;
-finish:
- fclose(fp);
- return status;
-}
-
-/*
- * Backend interface routines
- */
-static void closef(struct selabel_handle *rec)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- struct spec *spec;
- unsigned int i;
-
- for (i = 0; i < data->nspec; i++) {
- spec = &data->spec_arr[i];
- free(spec->property_key);
- free(spec->lr.ctx_raw);
- free(spec->lr.ctx_trans);
- }
-
- if (data->spec_arr)
- free(data->spec_arr);
-
- free(data);
-}
-
-static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
- const char *key,
- int __attribute__((unused)) type)
-{
- struct saved_data *data = (struct saved_data *)rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int i;
- struct selabel_lookup_rec *ret = NULL;
-
- if (!data->nspec) {
- errno = ENOENT;
- goto finish;
- }
-
- for (i = 0; i < data->nspec; i++) {
- if (strncmp(spec_arr[i].property_key, key,
- strlen(spec_arr[i].property_key)) == 0) {
- break;
- }
- if (strncmp(spec_arr[i].property_key, "*", 1) == 0)
- break;
- }
-
- if (i >= data->nspec) {
- /* No matching specification. */
- errno = ENOENT;
- goto finish;
- }
-
- ret = &spec_arr[i].lr;
-
-finish:
- return ret;
-}
-
-static struct selabel_lookup_rec *service_lookup(struct selabel_handle *rec,
- const char *key,
- int __attribute__((unused)) type)
-{
- struct saved_data *data = (struct saved_data *) rec->data;
- spec_t *spec_arr = data->spec_arr;
- unsigned int i;
- struct selabel_lookup_rec *ret = NULL;
-
- if (!data->nspec) {
- errno = ENOENT;
- goto finish;
- }
-
- for (i = 0; i < data->nspec; i++) {
- if (strcmp(spec_arr[i].property_key, key) == 0) {
- break;
- }
- if (strcmp(spec_arr[i].property_key, "*") == 0) break;
- }
-
- if (i >= data->nspec) {
- /* No matching specification. */
- errno = ENOENT;
- goto finish;
- }
-
- ret = &spec_arr[i].lr;
-
-finish:
- return ret;
-}
-
-static void stats(struct selabel_handle __attribute__((unused)) *rec)
-{
- selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n");
-}
-
-int selabel_property_init(struct selabel_handle *rec,
- const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct saved_data *data;
-
- data = (struct saved_data *)malloc(sizeof(*data));
- if (!data)
- return -1;
- memset(data, 0, sizeof(*data));
-
- rec->data = data;
- rec->func_close = &closef;
- rec->func_stats = &stats;
- rec->func_lookup = &lookup;
-
- return init(rec, opts, nopts);
-}
-
-int selabel_service_init(struct selabel_handle *rec,
- const struct selinux_opt *opts,
- unsigned nopts)
-{
- struct saved_data *data;
-
- data = (struct saved_data *)calloc(1, sizeof(*data));
- if (!data)
- return -1;
-
- rec->data = data;
- rec->func_close = &closef;
- rec->func_stats = &stats;
- rec->func_lookup = &service_lookup;
-
- return init(rec, opts, nopts);
-}