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