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