xref: /aosp_15_r20/external/selinux/restorecond/restorecond.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * restorecond
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2006-2009 Red Hat
5*2d543d20SAndroid Build Coastguard Worker  * see file 'COPYING' for use and warranty information
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or
8*2d543d20SAndroid Build Coastguard Worker  * modify it under the terms of the GNU General Public License as
9*2d543d20SAndroid Build Coastguard Worker  * published by the Free Software Foundation; either version 2 of
10*2d543d20SAndroid Build Coastguard Worker  * the License, or (at your option) any later version.
11*2d543d20SAndroid Build Coastguard Worker  *
12*2d543d20SAndroid Build Coastguard Worker  * This program is distributed in the hope that it will be useful,
13*2d543d20SAndroid Build Coastguard Worker  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14*2d543d20SAndroid Build Coastguard Worker  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*2d543d20SAndroid Build Coastguard Worker  * GNU General Public License for more details.
16*2d543d20SAndroid Build Coastguard Worker .*
17*2d543d20SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
18*2d543d20SAndroid Build Coastguard Worker  * along with this program; if not, write to the Free Software
19*2d543d20SAndroid Build Coastguard Worker  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20*2d543d20SAndroid Build Coastguard Worker  * 02111-1307  USA
21*2d543d20SAndroid Build Coastguard Worker  *
22*2d543d20SAndroid Build Coastguard Worker  * Authors:
23*2d543d20SAndroid Build Coastguard Worker  *   Dan Walsh <[email protected]>
24*2d543d20SAndroid Build Coastguard Worker  *
25*2d543d20SAndroid Build Coastguard Worker */
26*2d543d20SAndroid Build Coastguard Worker 
27*2d543d20SAndroid Build Coastguard Worker /*
28*2d543d20SAndroid Build Coastguard Worker  * PURPOSE:
29*2d543d20SAndroid Build Coastguard Worker  * This daemon program watches for the creation of files listed in a config file
30*2d543d20SAndroid Build Coastguard Worker  * and makes sure that there security context matches the systems defaults
31*2d543d20SAndroid Build Coastguard Worker  *
32*2d543d20SAndroid Build Coastguard Worker  * USAGE:
33*2d543d20SAndroid Build Coastguard Worker  * restorecond [-d] [-u] [-v] [-f restorecond_file ]
34*2d543d20SAndroid Build Coastguard Worker  *
35*2d543d20SAndroid Build Coastguard Worker  * -d   Run in debug mode
36*2d543d20SAndroid Build Coastguard Worker  * -f   Use alternative restorecond_file
37*2d543d20SAndroid Build Coastguard Worker  * -u   Run in user mode
38*2d543d20SAndroid Build Coastguard Worker  * -v   Run in verbose mode (Report missing files)
39*2d543d20SAndroid Build Coastguard Worker  *
40*2d543d20SAndroid Build Coastguard Worker  * EXAMPLE USAGE:
41*2d543d20SAndroid Build Coastguard Worker  * restorecond
42*2d543d20SAndroid Build Coastguard Worker  *
43*2d543d20SAndroid Build Coastguard Worker  */
44*2d543d20SAndroid Build Coastguard Worker 
45*2d543d20SAndroid Build Coastguard Worker #define _GNU_SOURCE
46*2d543d20SAndroid Build Coastguard Worker #include <sys/inotify.h>
47*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
48*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
49*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
50*2d543d20SAndroid Build Coastguard Worker #include <signal.h>
51*2d543d20SAndroid Build Coastguard Worker #include <string.h>
52*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
53*2d543d20SAndroid Build Coastguard Worker #include "restore.h"
54*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
55*2d543d20SAndroid Build Coastguard Worker #include <syslog.h>
56*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
57*2d543d20SAndroid Build Coastguard Worker #include <pwd.h>
58*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
59*2d543d20SAndroid Build Coastguard Worker #include <string.h>
60*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
61*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
62*2d543d20SAndroid Build Coastguard Worker #include "restorecond.h"
63*2d543d20SAndroid Build Coastguard Worker #include "utmpwatcher.h"
64*2d543d20SAndroid Build Coastguard Worker 
65*2d543d20SAndroid Build Coastguard Worker const char *homedir;
66*2d543d20SAndroid Build Coastguard Worker static int master_fd = -1;
67*2d543d20SAndroid Build Coastguard Worker 
68*2d543d20SAndroid Build Coastguard Worker static const char *server_watch_file  = "/etc/selinux/restorecond.conf";
69*2d543d20SAndroid Build Coastguard Worker static const char *user_watch_file  = "/etc/selinux/restorecond_user.conf";
70*2d543d20SAndroid Build Coastguard Worker static const char *watch_file;
71*2d543d20SAndroid Build Coastguard Worker struct restore_opts r_opts;
72*2d543d20SAndroid Build Coastguard Worker 
73*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker int debug_mode = 0;
76*2d543d20SAndroid Build Coastguard Worker int terminate = 0;
77*2d543d20SAndroid Build Coastguard Worker int master_wd = -1;
78*2d543d20SAndroid Build Coastguard Worker int run_as_user = 0;
79*2d543d20SAndroid Build Coastguard Worker 
done(void)80*2d543d20SAndroid Build Coastguard Worker static void done(void) {
81*2d543d20SAndroid Build Coastguard Worker 	watch_list_free(master_fd);
82*2d543d20SAndroid Build Coastguard Worker 	close(master_fd);
83*2d543d20SAndroid Build Coastguard Worker 	utmpwatcher_free();
84*2d543d20SAndroid Build Coastguard Worker 	selabel_close(r_opts.hnd);
85*2d543d20SAndroid Build Coastguard Worker }
86*2d543d20SAndroid Build Coastguard Worker 
87*2d543d20SAndroid Build Coastguard Worker static const char *pidfile = "/run/restorecond.pid";
88*2d543d20SAndroid Build Coastguard Worker 
write_pid_file(void)89*2d543d20SAndroid Build Coastguard Worker static int write_pid_file(void)
90*2d543d20SAndroid Build Coastguard Worker {
91*2d543d20SAndroid Build Coastguard Worker 	int pidfd, len;
92*2d543d20SAndroid Build Coastguard Worker 	char val[16];
93*2d543d20SAndroid Build Coastguard Worker 
94*2d543d20SAndroid Build Coastguard Worker 	len = snprintf(val, sizeof(val), "%u\n", getpid());
95*2d543d20SAndroid Build Coastguard Worker 	if (len < 0) {
96*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Pid error (%s)", strerror(errno));
97*2d543d20SAndroid Build Coastguard Worker 		pidfile = 0;
98*2d543d20SAndroid Build Coastguard Worker 		return 1;
99*2d543d20SAndroid Build Coastguard Worker 	}
100*2d543d20SAndroid Build Coastguard Worker 	pidfd = open(pidfile, O_CREAT | O_TRUNC | O_NOFOLLOW | O_WRONLY, 0644);
101*2d543d20SAndroid Build Coastguard Worker 	if (pidfd < 0) {
102*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Unable to set pidfile (%s)", strerror(errno));
103*2d543d20SAndroid Build Coastguard Worker 		pidfile = 0;
104*2d543d20SAndroid Build Coastguard Worker 		return 1;
105*2d543d20SAndroid Build Coastguard Worker 	}
106*2d543d20SAndroid Build Coastguard Worker 	if (write(pidfd, val, (unsigned int)len) != len) {
107*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Unable to write to pidfile (%s)", strerror(errno));
108*2d543d20SAndroid Build Coastguard Worker 		close(pidfd);
109*2d543d20SAndroid Build Coastguard Worker 		return 1;
110*2d543d20SAndroid Build Coastguard Worker 	}
111*2d543d20SAndroid Build Coastguard Worker 	close(pidfd);
112*2d543d20SAndroid Build Coastguard Worker 	return 0;
113*2d543d20SAndroid Build Coastguard Worker }
114*2d543d20SAndroid Build Coastguard Worker 
115*2d543d20SAndroid Build Coastguard Worker /*
116*2d543d20SAndroid Build Coastguard Worker  * SIGTERM handler
117*2d543d20SAndroid Build Coastguard Worker  */
term_handler(int s)118*2d543d20SAndroid Build Coastguard Worker static void term_handler(int s __attribute__ ((unused)))
119*2d543d20SAndroid Build Coastguard Worker {
120*2d543d20SAndroid Build Coastguard Worker 	terminate = 1;
121*2d543d20SAndroid Build Coastguard Worker 	/* trigger a failure in the watch */
122*2d543d20SAndroid Build Coastguard Worker 	close(master_fd);
123*2d543d20SAndroid Build Coastguard Worker }
124*2d543d20SAndroid Build Coastguard Worker 
usage(char * program)125*2d543d20SAndroid Build Coastguard Worker static void usage(char *program)
126*2d543d20SAndroid Build Coastguard Worker {
127*2d543d20SAndroid Build Coastguard Worker 	printf("%s [-d] [-f restorecond_file ] [-u] [-v] \n", program);
128*2d543d20SAndroid Build Coastguard Worker }
129*2d543d20SAndroid Build Coastguard Worker 
exitApp(const char * msg)130*2d543d20SAndroid Build Coastguard Worker void exitApp(const char *msg)
131*2d543d20SAndroid Build Coastguard Worker {
132*2d543d20SAndroid Build Coastguard Worker 	perror(msg);
133*2d543d20SAndroid Build Coastguard Worker 	exit(-1);
134*2d543d20SAndroid Build Coastguard Worker }
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker /*
137*2d543d20SAndroid Build Coastguard Worker    Add a file to the watch list.  We are watching for file creation, so we actually
138*2d543d20SAndroid Build Coastguard Worker    put the watch on the directory and then examine all files created in that directory
139*2d543d20SAndroid Build Coastguard Worker    to see if it is one that we are watching.
140*2d543d20SAndroid Build Coastguard Worker */
141*2d543d20SAndroid Build Coastguard Worker 
main(int argc,char ** argv)142*2d543d20SAndroid Build Coastguard Worker int main(int argc, char **argv)
143*2d543d20SAndroid Build Coastguard Worker {
144*2d543d20SAndroid Build Coastguard Worker 	int opt;
145*2d543d20SAndroid Build Coastguard Worker 	struct sigaction sa;
146*2d543d20SAndroid Build Coastguard Worker 
147*2d543d20SAndroid Build Coastguard Worker 	/* If we are not running SELinux then just exit */
148*2d543d20SAndroid Build Coastguard Worker 	if (is_selinux_enabled() != 1)
149*2d543d20SAndroid Build Coastguard Worker 		return 0;
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 	watch_file = server_watch_file;
152*2d543d20SAndroid Build Coastguard Worker 
153*2d543d20SAndroid Build Coastguard Worker 	/* Set all options to zero/NULL except for ignore_noent & digest. */
154*2d543d20SAndroid Build Coastguard Worker 	memset(&r_opts, 0, sizeof(r_opts));
155*2d543d20SAndroid Build Coastguard Worker 	r_opts.ignore_noent = SELINUX_RESTORECON_IGNORE_NOENTRY;
156*2d543d20SAndroid Build Coastguard Worker 	r_opts.ignore_digest = SELINUX_RESTORECON_IGNORE_DIGEST;
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker 	/* As r_opts.selabel_opt_digest = NULL, no digest will be requested. */
159*2d543d20SAndroid Build Coastguard Worker 	restore_init(&r_opts);
160*2d543d20SAndroid Build Coastguard Worker 
161*2d543d20SAndroid Build Coastguard Worker 	/* Register sighandlers */
162*2d543d20SAndroid Build Coastguard Worker 	sa.sa_flags = 0;
163*2d543d20SAndroid Build Coastguard Worker 	sa.sa_handler = term_handler;
164*2d543d20SAndroid Build Coastguard Worker 	sigemptyset(&sa.sa_mask);
165*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGTERM, &sa, NULL);
166*2d543d20SAndroid Build Coastguard Worker 
167*2d543d20SAndroid Build Coastguard Worker 	atexit( done );
168*2d543d20SAndroid Build Coastguard Worker 	while ((opt = getopt(argc, argv, "hdf:uv")) > 0) {
169*2d543d20SAndroid Build Coastguard Worker 		switch (opt) {
170*2d543d20SAndroid Build Coastguard Worker 		case 'd':
171*2d543d20SAndroid Build Coastguard Worker 			debug_mode = 1;
172*2d543d20SAndroid Build Coastguard Worker 			break;
173*2d543d20SAndroid Build Coastguard Worker 		case 'f':
174*2d543d20SAndroid Build Coastguard Worker 			watch_file = optarg;
175*2d543d20SAndroid Build Coastguard Worker 			break;
176*2d543d20SAndroid Build Coastguard Worker 		case 'u':
177*2d543d20SAndroid Build Coastguard Worker 			run_as_user = 1;
178*2d543d20SAndroid Build Coastguard Worker 			break;
179*2d543d20SAndroid Build Coastguard Worker 		case 'h':
180*2d543d20SAndroid Build Coastguard Worker 			usage(argv[0]);
181*2d543d20SAndroid Build Coastguard Worker 			exit(0);
182*2d543d20SAndroid Build Coastguard Worker 			break;
183*2d543d20SAndroid Build Coastguard Worker 		case 'v':
184*2d543d20SAndroid Build Coastguard Worker 			r_opts.verbose = SELINUX_RESTORECON_VERBOSE;
185*2d543d20SAndroid Build Coastguard Worker 			break;
186*2d543d20SAndroid Build Coastguard Worker 		case '?':
187*2d543d20SAndroid Build Coastguard Worker 			usage(argv[0]);
188*2d543d20SAndroid Build Coastguard Worker 			exit(-1);
189*2d543d20SAndroid Build Coastguard Worker 		}
190*2d543d20SAndroid Build Coastguard Worker 	}
191*2d543d20SAndroid Build Coastguard Worker 
192*2d543d20SAndroid Build Coastguard Worker 	master_fd = inotify_init();
193*2d543d20SAndroid Build Coastguard Worker 	if (master_fd < 0)
194*2d543d20SAndroid Build Coastguard Worker 		exitApp("inotify_init");
195*2d543d20SAndroid Build Coastguard Worker 
196*2d543d20SAndroid Build Coastguard Worker 	uid_t uid = getuid();
197*2d543d20SAndroid Build Coastguard Worker 	struct passwd *pwd = getpwuid(uid);
198*2d543d20SAndroid Build Coastguard Worker 	if (!pwd)
199*2d543d20SAndroid Build Coastguard Worker 		exitApp("getpwuid");
200*2d543d20SAndroid Build Coastguard Worker 
201*2d543d20SAndroid Build Coastguard Worker 	homedir = pwd->pw_dir;
202*2d543d20SAndroid Build Coastguard Worker 	if (uid != 0) {
203*2d543d20SAndroid Build Coastguard Worker 		if (run_as_user)
204*2d543d20SAndroid Build Coastguard Worker 			return server(master_fd, user_watch_file);
205*2d543d20SAndroid Build Coastguard Worker 		if (start() != 0)
206*2d543d20SAndroid Build Coastguard Worker 			return server(master_fd, user_watch_file);
207*2d543d20SAndroid Build Coastguard Worker 		return 0;
208*2d543d20SAndroid Build Coastguard Worker 	}
209*2d543d20SAndroid Build Coastguard Worker 
210*2d543d20SAndroid Build Coastguard Worker 	read_config(master_fd, watch_file);
211*2d543d20SAndroid Build Coastguard Worker 
212*2d543d20SAndroid Build Coastguard Worker 	if (!debug_mode) {
213*2d543d20SAndroid Build Coastguard Worker 		if (daemon(0, 0) < 0)
214*2d543d20SAndroid Build Coastguard Worker 			exitApp("daemon");
215*2d543d20SAndroid Build Coastguard Worker 	}
216*2d543d20SAndroid Build Coastguard Worker 
217*2d543d20SAndroid Build Coastguard Worker 	write_pid_file();
218*2d543d20SAndroid Build Coastguard Worker 
219*2d543d20SAndroid Build Coastguard Worker 	while (watch(master_fd, watch_file) == 0) {
220*2d543d20SAndroid Build Coastguard Worker 	}
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker 	watch_list_free(master_fd);
223*2d543d20SAndroid Build Coastguard Worker 	close(master_fd);
224*2d543d20SAndroid Build Coastguard Worker 
225*2d543d20SAndroid Build Coastguard Worker 	if (pidfile)
226*2d543d20SAndroid Build Coastguard Worker 		unlink(pidfile);
227*2d543d20SAndroid Build Coastguard Worker 
228*2d543d20SAndroid Build Coastguard Worker 	return 0;
229*2d543d20SAndroid Build Coastguard Worker }
230