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