1/* 2 * Note that the restorecond(8) service build links with these functions. 3 * Therefore any changes here should also be tested against that utility. 4 */ 5 6#include "restore.h" 7#include <glob.h> 8 9char **exclude_list; 10int exclude_count; 11 12struct restore_opts *r_opts; 13 14void restore_init(struct restore_opts *opts) 15{ 16 int rc; 17 18 r_opts = opts; 19 struct selinux_opt selinux_opts[] = { 20 { SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate }, 21 { SELABEL_OPT_PATH, r_opts->selabel_opt_path }, 22 { SELABEL_OPT_DIGEST, r_opts->selabel_opt_digest } 23 }; 24 25 r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 3); 26 if (!r_opts->hnd) { 27 perror(r_opts->selabel_opt_path); 28 exit(1); 29 } 30 31 r_opts->restorecon_flags = 0; 32 r_opts->restorecon_flags = r_opts->nochange | r_opts->verbose | 33 r_opts->progress | r_opts->set_specctx | 34 r_opts->add_assoc | r_opts->ignore_digest | 35 r_opts->recurse | r_opts->userealpath | 36 r_opts->xdev | r_opts->abort_on_error | 37 r_opts->syslog_changes | r_opts->log_matches | 38 r_opts->ignore_noent | r_opts->ignore_mounts; 39 40 /* Use setfiles, restorecon and restorecond own handles */ 41 selinux_restorecon_set_sehandle(r_opts->hnd); 42 43 if (r_opts->rootpath) { 44 rc = selinux_restorecon_set_alt_rootpath(r_opts->rootpath); 45 if (rc) { 46 fprintf(stderr, 47 "selinux_restorecon_set_alt_rootpath error: %s.\n", 48 strerror(errno)); 49 exit(-1); 50 } 51 } 52 53 if (exclude_list) 54 selinux_restorecon_set_exclude_list 55 ((const char **)exclude_list); 56} 57 58void restore_finish(void) 59{ 60 int i; 61 62 if (exclude_list) { 63 for (i = 0; exclude_list[i]; i++) 64 free(exclude_list[i]); 65 free(exclude_list); 66 } 67} 68 69int process_glob(char *name, struct restore_opts *opts) 70{ 71 glob_t globbuf; 72 size_t i = 0; 73 int len, rc, errors; 74 75 r_opts = opts; 76 memset(&globbuf, 0, sizeof(globbuf)); 77 78 errors = glob(name, GLOB_TILDE | GLOB_PERIOD | 79 GLOB_NOCHECK | GLOB_BRACE, NULL, &globbuf); 80 if (errors) 81 return errors; 82 83 for (i = 0; i < globbuf.gl_pathc; i++) { 84 len = strlen(globbuf.gl_pathv[i]) - 2; 85 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) 86 continue; 87 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) 88 continue; 89 rc = selinux_restorecon(globbuf.gl_pathv[i], 90 r_opts->restorecon_flags); 91 if (rc < 0) 92 errors = rc; 93 } 94 95 globfree(&globbuf); 96 97 return errors; 98} 99 100void add_exclude(const char *directory) 101{ 102 char **tmp_list; 103 104 if (directory == NULL || directory[0] != '/') { 105 fprintf(stderr, "Full path required for exclude: %s.\n", 106 directory); 107 exit(-1); 108 } 109 110 /* Add another two entries, one for directory, and the other to 111 * terminate the list. 112 */ 113 tmp_list = realloc(exclude_list, sizeof(char *) * (exclude_count + 2)); 114 if (!tmp_list) { 115 fprintf(stderr, "realloc failed while excluding %s.\n", 116 directory); 117 exit(-1); 118 } 119 exclude_list = tmp_list; 120 121 exclude_list[exclude_count] = strdup(directory); 122 if (!exclude_list[exclude_count]) { 123 fprintf(stderr, "strdup failed while excluding %s.\n", 124 directory); 125 exit(-1); 126 } 127 exclude_count++; 128 exclude_list[exclude_count] = NULL; 129} 130