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 9 char **exclude_list; 10 int exclude_count; 11 12 struct restore_opts *r_opts; 13 14 void 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 r_opts->mass_relabel; 40 41 /* Use setfiles, restorecon and restorecond own handles */ 42 selinux_restorecon_set_sehandle(r_opts->hnd); 43 44 if (r_opts->rootpath) { 45 rc = selinux_restorecon_set_alt_rootpath(r_opts->rootpath); 46 if (rc) { 47 fprintf(stderr, 48 "selinux_restorecon_set_alt_rootpath error: %s.\n", 49 strerror(errno)); 50 exit(-1); 51 } 52 } 53 54 if (exclude_list) 55 selinux_restorecon_set_exclude_list 56 ((const char **)exclude_list); 57 } 58 59 void restore_finish(void) 60 { 61 int i; 62 63 if (exclude_list) { 64 for (i = 0; exclude_list[i]; i++) 65 free(exclude_list[i]); 66 free(exclude_list); 67 } 68 } 69 70 int process_glob(char *name, struct restore_opts *opts) 71 { 72 glob_t globbuf; 73 size_t i = 0; 74 int len, rc, errors; 75 76 r_opts = opts; 77 memset(&globbuf, 0, sizeof(globbuf)); 78 79 errors = glob(name, GLOB_TILDE | GLOB_PERIOD | 80 GLOB_NOCHECK | GLOB_BRACE, NULL, &globbuf); 81 if (errors) 82 return errors; 83 84 for (i = 0; i < globbuf.gl_pathc; i++) { 85 len = strlen(globbuf.gl_pathv[i]) - 2; 86 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0) 87 continue; 88 if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0) 89 continue; 90 rc = selinux_restorecon(globbuf.gl_pathv[i], 91 r_opts->restorecon_flags); 92 if (rc < 0) 93 errors = rc; 94 } 95 96 globfree(&globbuf); 97 98 return errors; 99 } 100 101 void add_exclude(const char *directory) 102 { 103 char **tmp_list; 104 105 if (directory == NULL || directory[0] != '/') { 106 fprintf(stderr, "Full path required for exclude: %s.\n", 107 directory); 108 exit(-1); 109 } 110 111 /* Add another two entries, one for directory, and the other to 112 * terminate the list. 113 */ 114 tmp_list = realloc(exclude_list, sizeof(char *) * (exclude_count + 2)); 115 if (!tmp_list) { 116 fprintf(stderr, "realloc failed while excluding %s.\n", 117 directory); 118 exit(-1); 119 } 120 exclude_list = tmp_list; 121 122 exclude_list[exclude_count] = strdup(directory); 123 if (!exclude_list[exclude_count]) { 124 fprintf(stderr, "strdup failed while excluding %s.\n", 125 directory); 126 exit(-1); 127 } 128 exclude_count++; 129 exclude_list[exclude_count] = NULL; 130 } 131