#include <getopt.h> #include <stdio.h> #include <stdlib.h> #include <sepol/sepol.h> #include <selinux/selinux.h> #include <selinux/label.h> static int nerr; static int validate(char **contextp) { char *context = *contextp; if (sepol_check_context(context) < 0) { nerr++; return -1; } return 0; } static void usage(char *name) { fprintf(stderr, "usage: %s [OPTIONS] sepolicy context_file\n\n", name); fprintf(stderr, "Parses a context file and checks for syntax errors.\n"); fprintf(stderr, "The context_file is assumed to be a file_contexts file\n"); fprintf(stderr, "unless explicitly switched by an option.\n\n"); fprintf(stderr, " OPTIONS:\n"); fprintf(stderr, " -p : context file represents a property_context file.\n"); fprintf(stderr, "\n"); exit(1); } int main(int argc, char **argv) { struct selinux_opt opts[] = { { SELABEL_OPT_VALIDATE, (void*)1 }, { SELABEL_OPT_PATH, NULL } }; // Default backend unless changed by input argument. unsigned int backend = SELABEL_CTX_FILE; FILE *fp; struct selabel_handle *sehnd; char c; while ((c = getopt(argc, argv, "ph")) != -1) { switch (c) { case 'p': backend = SELABEL_CTX_ANDROID_PROP; break; case 'h': default: usage(argv[0]); break; } } int index = optind; if (argc - optind != 2) { fprintf(stderr, "Expected sepolicy file and context file as arguments.\n"); usage(argv[0]); } // remaining args are sepolicy file and context file char *sepolicyFile = argv[index]; char *contextFile = argv[index + 1]; fp = fopen(sepolicyFile, "r"); if (!fp) { perror(sepolicyFile); exit(2); } if (sepol_set_policydb_from_file(fp) < 0) { fprintf(stderr, "Error loading policy from %s\n", sepolicyFile); exit(3); } selinux_set_callback(SELINUX_CB_VALIDATE, (union selinux_callback)&validate); opts[1].value = contextFile; sehnd = selabel_open(backend, opts, 2); if (!sehnd) { fprintf(stderr, "Error loading context file from %s\n", contextFile); exit(4); } if (nerr) { fprintf(stderr, "Invalid context file found in %s\n", contextFile); exit(5); } exit(0); }