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
restore_init(struct restore_opts * opts)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
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
restore_finish(void)58 void 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
process_glob(char * name,struct restore_opts * opts)69 int 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
add_exclude(const char * directory)100 void 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