From mboxrd@z Thu Jan 1 00:00:00 1970 Message-ID: <466DA465.6060909@tycho.nsa.gov> Date: Mon, 11 Jun 2007 15:37:09 -0400 From: Eamon Walsh MIME-Version: 1.0 To: SE Linux CC: Stephen Smalley , Karl MacMillan , Joshua Brindle Subject: [PATCH 2/3] libselinux: labeling support (try 3) References: <466DA23C.9080509@tycho.nsa.gov> In-Reply-To: <466DA23C.9080509@tycho.nsa.gov> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Sender: owner-selinux@tycho.nsa.gov List-Id: selinux@tycho.nsa.gov This patch includes media backend code. Signed-off-by: Eamon Walsh --- label_media.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 219 insertions(+) Index: libselinux/src/label_media.c =================================================================== --- libselinux/src/label_media.c (revision 0) +++ libselinux/src/label_media.c (revision 0) @@ -0,0 +1,219 @@ +/* + * Media contexts backend for labeling system + * + * Author : Eamon Walsh + */ + +#include +#include +#include +#include +#include +#include +#include +#include "callbacks.h" +#include "label_internal.h" + +/* + * Internals + */ + +/* A context specification. */ +typedef struct spec { + struct selabel_lookup_rec lr; /* holds contexts for lookup result */ + char *key; /* key string */ + int matches; /* number of matches made during operation */ +} spec_t; + +struct saved_data { + unsigned int nspec; + spec_t *spec_arr; +}; + +static int process_line(const char *path, char *line_buf, int pass, + unsigned lineno, struct selabel_rec *rec) +{ + struct saved_data *data = (struct saved_data *)rec->data; + int items; + char *buf_p; + char *key, *context; + + buf_p = line_buf; + while (isspace(*buf_p)) + buf_p++; + /* Skip comment lines and empty lines. */ + if (*buf_p == '#' || *buf_p == 0) + return 0; + items = sscanf(line_buf, "%as %as ", &key, &context); + if (items < 2) { + selinux_log(SELINUX_WARNING, + "%s: line %d is missing fields, skipping\n", path, + lineno); + if (items == 1) + free(key); + return 0; + } + + if (pass == 1) { + data->spec_arr[data->nspec].key = key; + data->spec_arr[data->nspec].lr.ctx_raw = context; + } + + data->nspec++; + if (pass == 0) { + free(key); + free(context); + } + return 0; +} + +static int init(struct selabel_rec *rec, struct selabel_opt *opts, + size_t n) +{ + FILE *fp; + struct saved_data *data = (struct saved_data *)rec->data; + const char *path = NULL; + char *line_buf = NULL; + size_t line_len = 0; + int status = -1; + unsigned int lineno, pass, maxnspec; + struct stat sb; + + /* Process arguments */ + while (n--) + switch(opts[n].type) { + case SELABEL_OPT_PATH: + path = opts[n].value; + break; + } + + /* Open the specification file. */ + if (!path) + path = selinux_media_context_path(); + if ((fp = fopen(path, "r")) == NULL) + return -1; + __fsetlocking(fp, FSETLOCKING_BYCALLER); + + if (fstat(fileno(fp), &sb) < 0) + return -1; + if (!S_ISREG(sb.st_mode)) { + errno = EINVAL; + return -1; + } + + /* + * Perform two passes over the specification file. + * The first pass counts the number of specifications and + * performs simple validation of the input. At the end + * of the first pass, the spec array is allocated. + * The second pass performs detailed validation of the input + * and fills in the spec array. + */ + maxnspec = UINT_MAX / sizeof(spec_t); + for (pass = 0; pass < 2; pass++) { + lineno = 0; + data->nspec = 0; + while (getline(&line_buf, &line_len, fp) > 0 && + data->nspec < maxnspec) { + if (process_line(path, line_buf, pass, ++lineno, rec)) + goto finish; + } + lineno = 0; + + if (pass == 0) { + if (data->nspec == 0) { + status = 0; + goto finish; + } + data->spec_arr = malloc(sizeof(spec_t)*data->nspec); + if (data->spec_arr == NULL) + goto finish; + memset(data->spec_arr, 0, sizeof(spec_t)*data->nspec); + maxnspec = data->nspec; + rewind(fp); + } + } + free(line_buf); + + status = 0; +finish: + fclose(fp); + return status; +} + +/* + * Backend interface routines + */ +static void close(struct selabel_rec *rec) +{ + struct saved_data *data = (struct saved_data *)rec->data; + struct spec *spec, *spec_arr = data->spec_arr; + unsigned int i; + + for (i = 0; i < data->nspec; i++) { + spec = &spec_arr[i]; + free(spec->key); + free(spec->lr.ctx_raw); + free(spec->lr.ctx_trans); + } + + if (spec_arr) + free(spec_arr); + + memset(data, 0, sizeof(*data)); +} + +static struct selabel_lookup_rec *lookup(struct selabel_rec *rec, + const char *key, + int type __attribute__((unused))) +{ + struct saved_data *data = (struct saved_data *)rec->data; + spec_t *spec_arr = data->spec_arr; + unsigned int i; + + for (i = 0; i < data->nspec; i++) { + if (!strncmp(spec_arr[i].key, key, strlen(key) + 1)) + break; + if (!strncmp(spec_arr[i].key, "*", 2)) + break; + } + + if (i >= data->nspec) { + /* No matching specification. */ + errno = ENOENT; + return NULL; + } + + spec_arr[i].matches++; + return &spec_arr[i].lr; +} + +static void stats(struct selabel_rec *rec) +{ + struct saved_data *data = (struct saved_data *)rec->data; + unsigned int i, total = 0; + + for (i = 0; i < data->nspec; i++) + total += data->spec_arr[i].matches; + + selinux_log(SELINUX_INFO, "%u entries, %u matches made\n", + data->nspec, total); +} + +int selabel_media_init(struct selabel_rec *rec, struct selabel_opt *opts, + size_t 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 = &close; + rec->func_lookup = &lookup; + rec->func_stats = &stats; + + return init(rec, opts, nopts); +} -- Eamon Walsh National Security Agency -- This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with the words "unsubscribe selinux" without quotes as the message.