From 922b4e95220de78f18335a79de6188dd4f4f9911 Mon Sep 17 00:00:00 2001 From: William Roberts <william.c.roberts@intel.com> Date: Thu, 14 Jan 2016 17:06:37 -0800 Subject: [PATCH] checkfc: do not die on 0 length fc's Checkfc was treating 0 size fc files as a fatal error. An empty fc file should be treated as "nothing to check" so long as the -e option is passed. We add this option, so we don't allow empty file_context files to pass CTS checking. Change-Id: Ibca6bd948a13389e10c605d613acc48c5504443e Signed-off-by: William Roberts <william.c.roberts@intel.com> --- tools/checkfc.c | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tools/checkfc.c b/tools/checkfc.c index 602a05f76..e7d19b02b 100644 --- a/tools/checkfc.c +++ b/tools/checkfc.c @@ -3,11 +3,14 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include <sepol/module.h> #include <sepol/policydb/policydb.h> #include <sepol/sepol.h> #include <selinux/selinux.h> #include <selinux/label.h> +#include <sys/stat.h> +#include <sys/types.h> static const char * const CHECK_FC_ASSERT_ATTRS[] = { "fs_type", "dev_type", "file_type", NULL }; static const char * const CHECK_PC_ASSERT_ATTRS[] = { "property_type", NULL }; @@ -182,10 +185,11 @@ static int validate(char **contextp) } static void usage(char *name) { - fprintf(stderr, "usage1: %s [-p|-s] sepolicy context_file\n\n" + fprintf(stderr, "usage1: %s [-p|-s] [-e] sepolicy context_file\n\n" "Parses a context file and checks for syntax errors.\n" "The context_file is assumed to be a file_contexts file\n" - "unless the -p or -s option is used to indicate the property or service backend respectively.\n\n" + "unless the -p or -s option is used to indicate the property or service backend respectively.\n" + "If -e is specified, then the context_file is allowed to be empty.\n\n" "usage2: %s -c file_contexts1 file_contexts2\n\n" "Compares two file contexts files and reports one of subset, equal, superset, or incomparable.\n\n", @@ -244,8 +248,22 @@ static void do_compare_and_die_on_error(struct selinux_opt opts[], unsigned int } static void do_fc_check_and_die_on_error(struct selinux_opt opts[], unsigned int backend, filemode mode, - const char *sepolicy_file, const char *context_file) + const char *sepolicy_file, const char *context_file, bool allow_empty) { + struct stat sb; + if (stat(context_file, &sb) < 0) { + perror("Error: could not get stat on file contexts file"); + exit(1); + } + + if (sb.st_size == 0) { + /* Nothing to check on empty file_contexts file if allowed*/ + if (allow_empty) { + return; + } + /* else: We could throw the error here, but libselinux backend will catch it */ + } + global_state.sepolicy.file = fopen(sepolicy_file, "r"); if (!global_state.sepolicy.file) { perror("Error: could not open policy file"); @@ -308,16 +326,20 @@ int main(int argc, char **argv) // Default backend unless changed by input argument. unsigned int backend = SELABEL_CTX_FILE; + bool allow_empty = false; bool compare = false; char c; filemode mode = filemode_file_contexts; - while ((c = getopt(argc, argv, "cps")) != -1) { + while ((c = getopt(argc, argv, "cpse")) != -1) { switch (c) { case 'c': compare = true; break; + case 'e': + allow_empty = true; + break; case 'p': mode = filemode_property_contexts; backend = SELABEL_CTX_ANDROID_PROP; @@ -351,7 +373,7 @@ int main(int argc, char **argv) char *sepolicy_file = argv[index]; char *context_file = argv[index + 1]; - do_fc_check_and_die_on_error(opts, backend, mode, sepolicy_file, context_file); + do_fc_check_and_die_on_error(opts, backend, mode, sepolicy_file, context_file, allow_empty); } exit(0); } -- GitLab