Currently sscanf is used with %ms parameters that are not supported on all platforms. The new read_spec_entries function may be used to replace these where required. This patch updates sefcontext_compile, label_file and label_android_property services to use the new function. The file and property services have been tested on Android emulator and the file service on Fedora 21. Signed-off-by: Richard Haines <richard_c_haines@xxxxxxxxxxxxxx> --- libselinux/src/label_android_property.c | 18 ++----- libselinux/src/label_file.c | 16 ++---- libselinux/src/label_internal.h | 6 +++ libselinux/src/label_support.c | 89 +++++++++++++++++++++++++++++++++ libselinux/utils/sefcontext_compile.c | 35 ++++++------- 5 files changed, 120 insertions(+), 44 deletions(-) create mode 100644 libselinux/src/label_support.c diff --git a/libselinux/src/label_android_property.c b/libselinux/src/label_android_property.c index 1a29356..dadb160 100644 --- a/libselinux/src/label_android_property.c +++ b/libselinux/src/label_android_property.c @@ -82,23 +82,15 @@ static int process_line(struct selabel_handle *rec, const char *path, char *line_buf, int pass, unsigned lineno) { - int items, len; - char buf1[BUFSIZ], buf2[BUFSIZ]; - char *buf_p, *prop = buf1, *context = buf2; + 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; - len = strlen(line_buf); - if (line_buf[len - 1] == '\n') - line_buf[len - 1] = 0; - 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, "%255s %255s", prop, context); + items = read_spec_entries(line_buf, 2, &prop, &context); + if (items <= 0) + return items; if (items != 2) { selinux_log(SELINUX_WARNING, "%s: line %u is missing fields, skipping\n", path, diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c index bfb64af..b8061f4 100644 --- a/libselinux/src/label_file.c +++ b/libselinux/src/label_file.c @@ -154,22 +154,16 @@ static int process_line(struct selabel_handle *rec, char *line_buf, unsigned lineno) { int items, len, rc; - char *buf_p, *regex, *type, *context; + char *regex = NULL, *type = NULL, *context = NULL; struct saved_data *data = (struct saved_data *)rec->data; struct spec *spec_arr; unsigned int nspec = data->nspec; const char *errbuf = NULL; - len = strlen(line_buf); - if (line_buf[len - 1] == '\n') - line_buf[len - 1] = 0; - 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, "%ms %ms %ms", ®ex, &type, &context); + items = read_spec_entries(line_buf, 3, ®ex, &type, &context); + if (items <= 0) + return items; + if (items < 2) { COMPAT_LOG(SELINUX_WARNING, "%s: line %u is missing fields, skipping\n", path, diff --git a/libselinux/src/label_internal.h b/libselinux/src/label_internal.h index ef6ad26..0e582b6 100644 --- a/libselinux/src/label_internal.h +++ b/libselinux/src/label_internal.h @@ -102,4 +102,10 @@ compat_validate(struct selabel_handle *rec, struct selabel_lookup_rec *contexts, const char *path, unsigned lineno) hidden; +/* + * The read_spec_entries function may be used to + * replace sscanf to read entries from spec files. + */ +extern int read_spec_entries(char *line_buf, int num_args, ...); + #endif /* _SELABEL_INTERNAL_H_ */ diff --git a/libselinux/src/label_support.c b/libselinux/src/label_support.c new file mode 100644 index 0000000..bcde883 --- /dev/null +++ b/libselinux/src/label_support.c @@ -0,0 +1,89 @@ +/* + * This file contains helper functions for labeling support. + * + * Author : Richard Haines <richard_c_haines@xxxxxxxxxxxxxx> + */ + +#include <stdlib.h> +#include <stdarg.h> +#include <ctype.h> +#include <string.h> +#include "label_internal.h" + +/* + * The read_spec_entries and read_spec_entry functions may be used to + * replace sscanf to read entries from spec files. The file and + * property services now use these. + */ + +/* Read an entry from a spec file (e.g. file_contexts) */ +static inline int read_spec_entry(char **entry, char **ptr) +{ + int entry_len = 0; + *entry = NULL; + char *tmp_buf = NULL; + + while (isspace(**ptr) && **ptr != '\0') + (*ptr)++; + + tmp_buf = *ptr; + + while (!isspace(**ptr) && **ptr != '\0') { + (*ptr)++; + entry_len++; + } + + *entry = strndup(tmp_buf, entry_len); + if (!*entry) + return -1; + + return 0; +} + +/* + * line_buf - Buffer containing the spec entries . + * num_args - The number of spec parameter entries to process. + * ... - A 'char **spec_entry' for each parameter. + * returns - The number of items processed. + * + * This function calls read_spec_entry() to do the actual string processing. + */ +int read_spec_entries(char *line_buf, int num_args, ...) +{ + char **spec_entry, *buf_p; + int len, rc, items; + va_list ap; + + len = strlen(line_buf); + if (line_buf[len - 1] == '\n') + line_buf[len - 1] = '\0'; + + buf_p = line_buf; + while (isspace(*buf_p)) + buf_p++; + + /* Skip comment lines and empty lines. */ + if (*buf_p == '#' || *buf_p == '\0') + return 0; + + /* Process the spec file entries */ + va_start(ap, num_args); + + for (items = 0; items < num_args; items++) { + spec_entry = va_arg(ap, char **); + + if (len - 1 == buf_p - line_buf) { + va_end(ap); + return items; + } + + rc = read_spec_entry(spec_entry, &buf_p); + if (rc < 0) { + va_end(ap); + return rc; + } + } + va_end(ap); + return items; +} + diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c index 33a4a42..03bc0a7 100644 --- a/libselinux/utils/sefcontext_compile.c +++ b/libselinux/utils/sefcontext_compile.c @@ -29,11 +29,10 @@ static int process_file(struct saved_data *data, const char *filename) line_num = 0; while ((len = getline(&line_buf, &line_len, context_file)) != -1) { - char *context; - char *mode; - char *regex; + char *context = NULL; + char *mode = NULL; + char *regex = NULL; char *cp, *anchored_regex; - char *buf_p; pcre *re; pcre_extra *sd; const char *err; @@ -41,23 +40,20 @@ static int process_file(struct saved_data *data, const char *filename) size_t regex_len; int32_t stem_id; - len = strlen(line_buf); - if (line_buf[len - 1] == '\n') - line_buf[len - 1] = 0; - buf_p = line_buf; - while (isspace(*buf_p)) - buf_p++; - /* Skip comment lines and empty lines. */ - if (*buf_p == '#' || *buf_p == 0) - continue; + line_num++; - items = sscanf(line_buf, "%ms %ms %ms", ®ex, &mode, &context); - if (items < 2 || items > 3) { - fprintf(stderr, "invalid entry, skipping:%s", line_buf); - continue; - } + items = read_spec_entries(line_buf, 3, ®ex, &mode, &context); + if (items < 0) + return -1; - if (items == 2) { + if (items == 0) + continue; + else if (items == 1) { + fprintf(stderr, + "line: %u has invalid entry - skipping: %s\n", + line_num, line_buf); + continue; + } else if (items == 2) { context = mode; mode = NULL; } @@ -115,7 +111,6 @@ static int process_file(struct saved_data *data, const char *filename) free(anchored_regex); spec->sd = sd; - line_num++; data->nspec++; } -- 2.1.0 _______________________________________________ Selinux mailing list Selinux@xxxxxxxxxxxxx To unsubscribe, send email to Selinux-leave@xxxxxxxxxxxxx. To get help, send an email containing "help" to Selinux-request@xxxxxxxxxxxxx.