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