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); }
int main(int argc, char *argv[]) { const char *path = NULL; const char *out_file = NULL; char stack_path[PATH_MAX + 1]; char *tmp = NULL; int fd, rc, opt; FILE *policy_fp = NULL; struct stat buf; struct selabel_handle *rec = NULL; struct saved_data *data = NULL; if (argc < 2) usage(argv[0]); while ((opt = getopt(argc, argv, "o:p:")) > 0) { switch (opt) { case 'o': out_file = optarg; break; case 'p': policy_file = optarg; break; default: usage(argv[0]); } } if (optind >= argc) usage(argv[0]); path = argv[optind]; if (stat(path, &buf) < 0) { fprintf(stderr, "Can not stat: %s: %m\n", path); exit(EXIT_FAILURE); } /* Open binary policy if supplied. */ if (policy_file) { policy_fp = fopen(policy_file, "r"); if (!policy_fp) { fprintf(stderr, "Failed to open policy: %s\n", policy_file); exit(EXIT_FAILURE); } if (sepol_set_policydb_from_file(policy_fp) < 0) { fprintf(stderr, "Failed to load policy: %s\n", policy_file); fclose(policy_fp); exit(EXIT_FAILURE); } } /* Generate dummy handle for process_line() function */ rec = (struct selabel_handle *)calloc(1, sizeof(*rec)); if (!rec) { fprintf(stderr, "Failed to calloc handle\n"); if (policy_fp) fclose(policy_fp); exit(EXIT_FAILURE); } rec->backend = SELABEL_CTX_FILE; /* Need to set validation on to get the bin file generated by the * process_line function, however as the bin file being generated * may not be related to the currently loaded policy (that it * would be validated against), then set callback to ignore any * validation - unless the -p option is used in which case if an * error is detected, the process will be aborted. */ rec->validating = 1; selinux_set_callback(SELINUX_CB_VALIDATE, (union selinux_callback)&validate_context); data = (struct saved_data *)calloc(1, sizeof(*data)); if (!data) { fprintf(stderr, "Failed to calloc saved_data\n"); free(rec); if (policy_fp) fclose(policy_fp); exit(EXIT_FAILURE); } rec->data = data; rc = process_file(rec, path); if (rc < 0) goto err; rc = sort_specs(data); if (rc) goto err; if (out_file) rc = snprintf(stack_path, sizeof(stack_path), "%s", out_file); else rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path); if (rc < 0 || rc >= (int)sizeof(stack_path)) goto err; tmp = malloc(strlen(stack_path) + 7); if (!tmp) goto err; rc = sprintf(tmp, "%sXXXXXX", stack_path); if (rc < 0) goto err; fd = mkstemp(tmp); if (fd < 0) goto err; rc = fchmod(fd, buf.st_mode); if (rc < 0) { perror("fchmod failed to set permission on compiled regexs"); goto err_unlink; } rc = write_binary_file(data, fd); if (rc < 0) goto err_unlink; rc = rename(tmp, stack_path); if (rc < 0) goto err_unlink; rc = 0; out: if (policy_fp) fclose(policy_fp); free_specs(data); free(rec); free(data); free(tmp); return rc; err_unlink: unlink(tmp); err: rc = -1; goto out; }
int main(int argc, char **argv) { struct stat sb; int opt, i = 0; const char *input_filename = NULL; int use_input_file = 0; char *buf = NULL; size_t buf_len; int recurse; /* Recursive descent. */ const char *base; int mass_relabel = 0, errors = 0; const char *ropts = "e:f:hilno:pqrsvFRW0"; const char *sopts = "c:de:f:hilno:pqr:svFR:W0"; const char *opts; memset(&r_opts, 0, sizeof(r_opts)); /* Initialize variables */ r_opts.progress = 0; r_opts.count = 0; r_opts.nfile = 0; r_opts.debug = 0; r_opts.change = 1; r_opts.verbose = 0; r_opts.logging = 0; r_opts.rootpath = NULL; r_opts.rootpathlen = 0; r_opts.outfile = NULL; r_opts.force = 0; r_opts.hard_links = 1; altpath = NULL; r_opts.progname = strdup(argv[0]); if (!r_opts.progname) { fprintf(stderr, "%s: Out of memory!\n", argv[0]); exit(-1); } base = basename(r_opts.progname); if (!strcmp(base, SETFILES)) { /* * setfiles: * Recursive descent, * Does not expand paths via realpath, * Aborts on errors during the file tree walk, * Try to track inode associations for conflict detection, * Does not follow mounts, * Validates all file contexts at init time. */ iamrestorecon = 0; recurse = 1; r_opts.expand_realpath = 0; r_opts.abort_on_error = 1; r_opts.add_assoc = 1; r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV; ctx_validate = 1; opts = sopts; } else { /* * restorecon: * No recursive descent unless -r/-R, * Expands paths via realpath, * Do not abort on errors during the file tree walk, * Do not try to track inode associations for conflict detection, * Follows mounts, * Does lazy validation of contexts upon use. */ if (strcmp(base, RESTORECON) && !r_opts.quiet) printf("Executed with an unrecognized name (%s), defaulting to %s behavior.\n", base, RESTORECON); iamrestorecon = 1; recurse = 0; r_opts.expand_realpath = 1; r_opts.abort_on_error = 0; r_opts.add_assoc = 0; r_opts.fts_flags = FTS_PHYSICAL; ctx_validate = 0; opts = ropts; /* restorecon only: silent exit if no SELinux. Allows unconditional execution by scripts. */ if (is_selinux_enabled() <= 0) exit(0); } /* This must happen before getopt. */ r_opts.nfile = exclude_non_seclabel_mounts(); if (iamrestorecon) opts = ropts; else opts = sopts; /* Process any options. */ while ((opt = getopt(argc, argv, opts)) > 0) { switch (opt) { case 'c': { FILE *policystream; if (iamrestorecon) usage(argv[0]); policyfile = optarg; policystream = fopen(policyfile, "r"); if (!policystream) { fprintf(stderr, "Error opening %s: %s\n", policyfile, strerror(errno)); exit(-1); } __fsetlocking(policystream, FSETLOCKING_BYCALLER); if (sepol_set_policydb_from_file(policystream) < 0) { fprintf(stderr, "Error reading policy %s: %s\n", policyfile, strerror(errno)); exit(-1); } fclose(policystream); ctx_validate = 1; break; } case 'e': remove_exclude(optarg); if (lstat(optarg, &sb) < 0 && errno != EACCES) { fprintf(stderr, "Can't stat exclude path \"%s\", %s - ignoring.\n", optarg, strerror(errno)); break; } if (add_exclude(optarg)) exit(-1); break; case 'f': use_input_file = 1; input_filename = optarg; break; case 'd': if (iamrestorecon) usage(argv[0]); r_opts.debug = 1; break; case 'i': r_opts.ignore_enoent = 1; break; case 'l': r_opts.logging = 1; break; case 'F': r_opts.force = 1; break; case 'n': r_opts.change = 0; break; case 'o': if (strcmp(optarg, "-") == 0) { r_opts.outfile = stdout; break; } r_opts.outfile = fopen(optarg, "w"); if (!r_opts.outfile) { fprintf(stderr, "Error opening %s: %s\n", optarg, strerror(errno)); usage(argv[0]); } __fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER); break; case 'q': r_opts.quiet = 1; break; case 'R': case 'r': if (iamrestorecon) { recurse = 1; break; } if (NULL != r_opts.rootpath) { fprintf(stderr, "%s: only one -r can be specified\n", argv[0]); exit(-1); } set_rootpath(optarg); break; case 's': use_input_file = 1; input_filename = "-"; r_opts.add_assoc = 0; break; case 'v': if (r_opts.progress) { fprintf(stderr, "Progress and Verbose mutually exclusive\n"); usage(argv[0]); } r_opts.verbose++; break; case 'p': if (r_opts.verbose) { fprintf(stderr, "Progress and Verbose mutually exclusive\n"); usage(argv[0]); } r_opts.progress++; break; case 'W': warn_no_match = 1; break; case '0': null_terminated = 1; break; case 'h': case '?': usage(argv[0]); } } for (i = optind; i < argc; i++) { if (!strcmp(argv[i], "/")) { mass_relabel = 1; if (r_opts.progress) r_opts.progress++; } } if (!iamrestorecon) { if (policyfile) { if (optind != (argc - 1)) usage(argv[0]); } else if (use_input_file) { if (optind != (argc - 1)) { /* Cannot mix with pathname arguments. */ usage(argv[0]); } } else { if (optind > (argc - 2)) usage(argv[0]); } /* Use our own invalid context checking function so that we can support either checking against the active policy or checking against a binary policy file. */ selinux_set_callback(SELINUX_CB_VALIDATE, (union selinux_callback)&canoncon); if (stat(argv[optind], &sb) < 0) { perror(argv[optind]); exit(-1); } if (!S_ISREG(sb.st_mode)) { fprintf(stderr, "%s: spec file %s is not a regular file.\n", argv[0], argv[optind]); exit(-1); } altpath = argv[optind]; optind++; } else if (argc == 1) usage(argv[0]); /* Load the file contexts configuration and check it. */ r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL); r_opts.selabel_opt_path = altpath; if (nerr) exit(-1); restore_init(&r_opts); if (use_input_file) { FILE *f = stdin; ssize_t len; int delim; if (strcmp(input_filename, "-") != 0) f = fopen(input_filename, "r"); if (f == NULL) { fprintf(stderr, "Unable to open %s: %s\n", input_filename, strerror(errno)); usage(argv[0]); } __fsetlocking(f, FSETLOCKING_BYCALLER); delim = (null_terminated != 0) ? '\0' : '\n'; while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) { buf[len - 1] = 0; if (!strcmp(buf, "/")) mass_relabel = 1; errors |= process_glob(buf, recurse) < 0; } if (strcmp(input_filename, "-") != 0) fclose(f); } else { for (i = optind; i < argc; i++) errors |= process_glob(argv[i], recurse) < 0; } maybe_audit_mass_relabel(mass_relabel, errors); if (warn_no_match) selabel_stats(r_opts.hnd); selabel_close(r_opts.hnd); restore_finish(); if (r_opts.outfile) fclose(r_opts.outfile); if (r_opts.progress && r_opts.count >= STAR_COUNT) printf("\n"); exit(errors ? -1: 0); }