xref: /aosp_15_r20/external/selinux/restorecond/restore.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
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 
restore_init(struct restore_opts * opts)15 void restore_init(struct restore_opts *opts)
16 {
17 	int rc;
18 
19 	struct selinux_opt selinux_opts[] = {
20 		{ SELABEL_OPT_VALIDATE, opts->selabel_opt_validate },
21 		{ SELABEL_OPT_PATH, opts->selabel_opt_path },
22 		{ SELABEL_OPT_DIGEST, opts->selabel_opt_digest }
23 	};
24 
25 	opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 3);
26 	if (!opts->hnd) {
27 		perror(opts->selabel_opt_path);
28 		exit(1);
29 	}
30 
31 	opts->restorecon_flags = 0;
32 	opts->restorecon_flags = opts->nochange | opts->verbose |
33 			   opts->progress | opts->set_specctx  |
34 			   opts->add_assoc | opts->ignore_digest |
35 			   opts->recurse | opts->userealpath |
36 			   opts->xdev | opts->abort_on_error |
37 			   opts->syslog_changes | opts->log_matches |
38 			   opts->ignore_noent | opts->ignore_mounts;
39 
40 	/* Use setfiles, restorecon and restorecond own handles */
41 	selinux_restorecon_set_sehandle(opts->hnd);
42 
43 	if (opts->rootpath) {
44 		rc = selinux_restorecon_set_alt_rootpath(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 	memset(&globbuf, 0, sizeof(globbuf));
76 
77 	errors = glob(name, GLOB_TILDE | GLOB_PERIOD |
78 			  GLOB_NOCHECK | GLOB_BRACE, NULL, &globbuf);
79 	if (errors)
80 		return errors;
81 
82 	for (i = 0; i < globbuf.gl_pathc; i++) {
83 		len = strlen(globbuf.gl_pathv[i]) - 2;
84 		if (len > 0 && strcmp(&globbuf.gl_pathv[i][len--], "/.") == 0)
85 			continue;
86 		if (len > 0 && strcmp(&globbuf.gl_pathv[i][len], "/..") == 0)
87 			continue;
88 		rc = selinux_restorecon(globbuf.gl_pathv[i],
89 					opts->restorecon_flags);
90 		if (rc < 0)
91 			errors = rc;
92 	}
93 
94 	globfree(&globbuf);
95 
96 	return errors;
97 }
98 
add_exclude(const char * directory)99 void add_exclude(const char *directory)
100 {
101 	char **tmp_list;
102 
103 	if (directory == NULL || directory[0] != '/') {
104 		fprintf(stderr, "Full path required for exclude: %s.\n",
105 			    directory);
106 		exit(-1);
107 	}
108 
109 	/* Add another two entries, one for directory, and the other to
110 	 * terminate the list.
111 	 */
112 	tmp_list = realloc(exclude_list, sizeof(char *) * (exclude_count + 2));
113 	if (!tmp_list) {
114 		fprintf(stderr, "realloc failed while excluding %s.\n",
115 			    directory);
116 		exit(-1);
117 	}
118 	exclude_list = tmp_list;
119 
120 	exclude_list[exclude_count] = strdup(directory);
121 	if (!exclude_list[exclude_count]) {
122 		fprintf(stderr, "strdup failed while excluding %s.\n",
123 			    directory);
124 		exit(-1);
125 	}
126 	exclude_count++;
127 	exclude_list[exclude_count] = NULL;
128 }
129