xref: /aosp_15_r20/external/selinux/mcstrans/src/mcstransd.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Copyright (c) 2006 Trusted Computer Solutions, Inc. */
2*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
3*2d543d20SAndroid Build Coastguard Worker #include <poll.h>
4*2d543d20SAndroid Build Coastguard Worker #include <signal.h>
5*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
6*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <string.h>
9*2d543d20SAndroid Build Coastguard Worker #include <syslog.h>
10*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
11*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
12*2d543d20SAndroid Build Coastguard Worker #include <sys/capability.h>
13*2d543d20SAndroid Build Coastguard Worker #include <sys/resource.h>
14*2d543d20SAndroid Build Coastguard Worker #include <sys/socket.h>
15*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
16*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
17*2d543d20SAndroid Build Coastguard Worker #include <sys/uio.h>
18*2d543d20SAndroid Build Coastguard Worker #include <sys/un.h>
19*2d543d20SAndroid Build Coastguard Worker 
20*2d543d20SAndroid Build Coastguard Worker #include "mcscolor.h"
21*2d543d20SAndroid Build Coastguard Worker #include "mcstrans.h"
22*2d543d20SAndroid Build Coastguard Worker 
23*2d543d20SAndroid Build Coastguard Worker #ifdef UNUSED
24*2d543d20SAndroid Build Coastguard Worker #elif defined(__GNUC__)
25*2d543d20SAndroid Build Coastguard Worker # define UNUSED(x) UNUSED_ ## x __attribute__((unused))
26*2d543d20SAndroid Build Coastguard Worker #elif defined(__LCLINT__)
27*2d543d20SAndroid Build Coastguard Worker # define UNUSED(x) /*@unused@*/ x
28*2d543d20SAndroid Build Coastguard Worker #else
29*2d543d20SAndroid Build Coastguard Worker # define UNUSED(x) x
30*2d543d20SAndroid Build Coastguard Worker #endif
31*2d543d20SAndroid Build Coastguard Worker 
32*2d543d20SAndroid Build Coastguard Worker #define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix"
33*2d543d20SAndroid Build Coastguard Worker 
34*2d543d20SAndroid Build Coastguard Worker #define SETRANS_INIT			1
35*2d543d20SAndroid Build Coastguard Worker #define RAW_TO_TRANS_CONTEXT		2
36*2d543d20SAndroid Build Coastguard Worker #define TRANS_TO_RAW_CONTEXT		3
37*2d543d20SAndroid Build Coastguard Worker #define RAW_CONTEXT_TO_COLOR		4
38*2d543d20SAndroid Build Coastguard Worker #define MAX_DATA_BUF			4096
39*2d543d20SAndroid Build Coastguard Worker #define MAX_DESCRIPTORS			8192
40*2d543d20SAndroid Build Coastguard Worker 
41*2d543d20SAndroid Build Coastguard Worker #ifdef DEBUG
42*2d543d20SAndroid Build Coastguard Worker //#define log_debug(fmt, ...) syslog(LOG_DEBUG, fmt, __VA_ARGS__)
43*2d543d20SAndroid Build Coastguard Worker #define log_debug(fmt, ...) fprintf(stderr, fmt, __VA_ARGS__)
44*2d543d20SAndroid Build Coastguard Worker #else
45*2d543d20SAndroid Build Coastguard Worker #define log_debug(fmt, ...) do {} while (0)
46*2d543d20SAndroid Build Coastguard Worker #endif
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker #define SETRANSD_PATHNAME "/sbin/mcstransd"
49*2d543d20SAndroid Build Coastguard Worker 
50*2d543d20SAndroid Build Coastguard Worker /* name of program (for error messages) */
51*2d543d20SAndroid Build Coastguard Worker #define SETRANSD_PROGNAME "mcstransd"
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker static int sockfd = -1;	/* socket we are listening on */
54*2d543d20SAndroid Build Coastguard Worker 
55*2d543d20SAndroid Build Coastguard Worker static volatile int restart_daemon = 0;
56*2d543d20SAndroid Build Coastguard Worker static void cleanup_exit(int ret) __attribute__ ((noreturn));
57*2d543d20SAndroid Build Coastguard Worker static void
cleanup_exit(int ret)58*2d543d20SAndroid Build Coastguard Worker cleanup_exit(int ret)
59*2d543d20SAndroid Build Coastguard Worker {
60*2d543d20SAndroid Build Coastguard Worker 	finish_context_colors();
61*2d543d20SAndroid Build Coastguard Worker 	finish_context_translations();
62*2d543d20SAndroid Build Coastguard Worker 	if (sockfd >=0)
63*2d543d20SAndroid Build Coastguard Worker 		(void)unlink(SETRANS_UNIX_SOCKET);
64*2d543d20SAndroid Build Coastguard Worker 
65*2d543d20SAndroid Build Coastguard Worker 	log_debug("%s\n", "cleanup_exit");
66*2d543d20SAndroid Build Coastguard Worker 
67*2d543d20SAndroid Build Coastguard Worker 	exit(ret);
68*2d543d20SAndroid Build Coastguard Worker }
69*2d543d20SAndroid Build Coastguard Worker 
70*2d543d20SAndroid Build Coastguard Worker static void clean_exit(void);
clean_exit(void)71*2d543d20SAndroid Build Coastguard Worker static  __attribute__((noreturn)) void clean_exit(void)
72*2d543d20SAndroid Build Coastguard Worker {
73*2d543d20SAndroid Build Coastguard Worker 	log_debug("%s\n", "clean_exit");
74*2d543d20SAndroid Build Coastguard Worker 	cleanup_exit(0);
75*2d543d20SAndroid Build Coastguard Worker }
76*2d543d20SAndroid Build Coastguard Worker 
77*2d543d20SAndroid Build Coastguard Worker static int
send_response(int fd,uint32_t function,char * data,int32_t ret_val)78*2d543d20SAndroid Build Coastguard Worker send_response(int fd, uint32_t function, char *data, int32_t ret_val)
79*2d543d20SAndroid Build Coastguard Worker {
80*2d543d20SAndroid Build Coastguard Worker 	struct iovec resp_hdr[3];
81*2d543d20SAndroid Build Coastguard Worker 	uint32_t data_size;
82*2d543d20SAndroid Build Coastguard Worker 	struct iovec resp_data;
83*2d543d20SAndroid Build Coastguard Worker 	ssize_t count;
84*2d543d20SAndroid Build Coastguard Worker 
85*2d543d20SAndroid Build Coastguard Worker 	if (!data)
86*2d543d20SAndroid Build Coastguard Worker 		data = (char *)"";
87*2d543d20SAndroid Build Coastguard Worker 
88*2d543d20SAndroid Build Coastguard Worker 	data_size = strlen(data) + 1;
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[0].iov_base = &function;
91*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[0].iov_len = sizeof(function);
92*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[1].iov_base = &data_size;
93*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[1].iov_len = sizeof(data_size);
94*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[2].iov_base = &ret_val;
95*2d543d20SAndroid Build Coastguard Worker 	resp_hdr[2].iov_len = sizeof(ret_val);
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker 	while (((count = writev(fd, resp_hdr, 3)) < 0) && (errno == EINTR));
98*2d543d20SAndroid Build Coastguard Worker 	if (count != (sizeof(function) + sizeof(data_size) + sizeof(ret_val))) {
99*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to write response header");
100*2d543d20SAndroid Build Coastguard Worker 		return -1;
101*2d543d20SAndroid Build Coastguard Worker 	}
102*2d543d20SAndroid Build Coastguard Worker 
103*2d543d20SAndroid Build Coastguard Worker 	resp_data.iov_base = data;
104*2d543d20SAndroid Build Coastguard Worker 	resp_data.iov_len = data_size;
105*2d543d20SAndroid Build Coastguard Worker 
106*2d543d20SAndroid Build Coastguard Worker 	while (((count = writev(fd, &resp_data, 1)) < 0) && (errno == EINTR));
107*2d543d20SAndroid Build Coastguard Worker 	if (count < 0 || (size_t)count != data_size) {
108*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to write response data");
109*2d543d20SAndroid Build Coastguard Worker 		return -1;
110*2d543d20SAndroid Build Coastguard Worker 	}
111*2d543d20SAndroid Build Coastguard Worker 
112*2d543d20SAndroid Build Coastguard Worker 	return ret_val;
113*2d543d20SAndroid Build Coastguard Worker }
114*2d543d20SAndroid Build Coastguard Worker 
115*2d543d20SAndroid Build Coastguard Worker static int
get_peer_pid(int fd,pid_t * pid)116*2d543d20SAndroid Build Coastguard Worker get_peer_pid(int fd, pid_t *pid)
117*2d543d20SAndroid Build Coastguard Worker {
118*2d543d20SAndroid Build Coastguard Worker 	int ret;
119*2d543d20SAndroid Build Coastguard Worker 	socklen_t size = sizeof(struct ucred);
120*2d543d20SAndroid Build Coastguard Worker 	struct ucred peercred;
121*2d543d20SAndroid Build Coastguard Worker 
122*2d543d20SAndroid Build Coastguard Worker 	/* get the context of the requesting process */
123*2d543d20SAndroid Build Coastguard Worker 	ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &size);
124*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0) {
125*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to get PID of client process");
126*2d543d20SAndroid Build Coastguard Worker 		return -1;
127*2d543d20SAndroid Build Coastguard Worker 	}
128*2d543d20SAndroid Build Coastguard Worker 	*pid = peercred.pid;
129*2d543d20SAndroid Build Coastguard Worker 	return ret;
130*2d543d20SAndroid Build Coastguard Worker }
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 
133*2d543d20SAndroid Build Coastguard Worker static int
process_request(int fd,uint32_t function,char * data1,char * UNUSED (data2))134*2d543d20SAndroid Build Coastguard Worker process_request(int fd, uint32_t function, char *data1, char *UNUSED(data2))
135*2d543d20SAndroid Build Coastguard Worker {
136*2d543d20SAndroid Build Coastguard Worker 	int32_t result;
137*2d543d20SAndroid Build Coastguard Worker 	char *out = NULL;
138*2d543d20SAndroid Build Coastguard Worker 	int ret;
139*2d543d20SAndroid Build Coastguard Worker 
140*2d543d20SAndroid Build Coastguard Worker 	switch (function) {
141*2d543d20SAndroid Build Coastguard Worker 	case SETRANS_INIT:
142*2d543d20SAndroid Build Coastguard Worker 		result = 0;
143*2d543d20SAndroid Build Coastguard Worker 		ret = send_response(fd, function, NULL, result);
144*2d543d20SAndroid Build Coastguard Worker 		break;
145*2d543d20SAndroid Build Coastguard Worker 	case RAW_TO_TRANS_CONTEXT:
146*2d543d20SAndroid Build Coastguard Worker 		result = trans_context(data1, &out);
147*2d543d20SAndroid Build Coastguard Worker 		ret = send_response(fd, function, out, result);
148*2d543d20SAndroid Build Coastguard Worker 		break;
149*2d543d20SAndroid Build Coastguard Worker 	case TRANS_TO_RAW_CONTEXT:
150*2d543d20SAndroid Build Coastguard Worker 		result = untrans_context(data1, &out);
151*2d543d20SAndroid Build Coastguard Worker 		ret = send_response(fd, function, out, result);
152*2d543d20SAndroid Build Coastguard Worker 		break;
153*2d543d20SAndroid Build Coastguard Worker 	case RAW_CONTEXT_TO_COLOR:
154*2d543d20SAndroid Build Coastguard Worker 		result = raw_color(data1, &out);
155*2d543d20SAndroid Build Coastguard Worker 		ret = send_response(fd, function, out, result);
156*2d543d20SAndroid Build Coastguard Worker 		break;
157*2d543d20SAndroid Build Coastguard Worker 	default:
158*2d543d20SAndroid Build Coastguard Worker 		result = -1;
159*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
160*2d543d20SAndroid Build Coastguard Worker 		break;
161*2d543d20SAndroid Build Coastguard Worker 	}
162*2d543d20SAndroid Build Coastguard Worker 
163*2d543d20SAndroid Build Coastguard Worker 	if (result) {
164*2d543d20SAndroid Build Coastguard Worker 		pid_t pid = 0;
165*2d543d20SAndroid Build Coastguard Worker 		get_peer_pid(fd, &pid);
166*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Invalid request func=%d from=%u",
167*2d543d20SAndroid Build Coastguard Worker 		       function, pid);
168*2d543d20SAndroid Build Coastguard Worker 	}
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 	free(out);
171*2d543d20SAndroid Build Coastguard Worker 
172*2d543d20SAndroid Build Coastguard Worker 	return ret;
173*2d543d20SAndroid Build Coastguard Worker }
174*2d543d20SAndroid Build Coastguard Worker 
175*2d543d20SAndroid Build Coastguard Worker static int
service_request(int fd)176*2d543d20SAndroid Build Coastguard Worker service_request(int fd)
177*2d543d20SAndroid Build Coastguard Worker {
178*2d543d20SAndroid Build Coastguard Worker 	struct iovec req_hdr[3];
179*2d543d20SAndroid Build Coastguard Worker 	uint32_t function;
180*2d543d20SAndroid Build Coastguard Worker 	uint32_t data1_size;
181*2d543d20SAndroid Build Coastguard Worker 	uint32_t data2_size;
182*2d543d20SAndroid Build Coastguard Worker 	struct iovec req_data[2];
183*2d543d20SAndroid Build Coastguard Worker 	char *data1;
184*2d543d20SAndroid Build Coastguard Worker 	char *data2;
185*2d543d20SAndroid Build Coastguard Worker 	int ret;
186*2d543d20SAndroid Build Coastguard Worker 	ssize_t count;
187*2d543d20SAndroid Build Coastguard Worker 
188*2d543d20SAndroid Build Coastguard Worker 	req_hdr[0].iov_base = &function;
189*2d543d20SAndroid Build Coastguard Worker 	req_hdr[0].iov_len = sizeof(function);
190*2d543d20SAndroid Build Coastguard Worker 	req_hdr[1].iov_base = &data1_size;
191*2d543d20SAndroid Build Coastguard Worker 	req_hdr[1].iov_len = sizeof(data1_size);
192*2d543d20SAndroid Build Coastguard Worker 	req_hdr[2].iov_base = &data2_size;
193*2d543d20SAndroid Build Coastguard Worker 	req_hdr[2].iov_len = sizeof(data2_size);
194*2d543d20SAndroid Build Coastguard Worker 
195*2d543d20SAndroid Build Coastguard Worker 	while (((count = readv(fd, req_hdr, 3)) < 0) && (errno == EINTR));
196*2d543d20SAndroid Build Coastguard Worker 	if (count <= 0) {
197*2d543d20SAndroid Build Coastguard Worker 		return 1;
198*2d543d20SAndroid Build Coastguard Worker 	}
199*2d543d20SAndroid Build Coastguard Worker 	if (count != (sizeof(function) + sizeof(data1_size) +
200*2d543d20SAndroid Build Coastguard Worker 	              sizeof(data2_size) )) {
201*2d543d20SAndroid Build Coastguard Worker 		log_debug("Failed to read request header %d != %u\n",(int)count,
202*2d543d20SAndroid Build Coastguard Worker 			(unsigned)(sizeof(function) + sizeof(data1_size) +
203*2d543d20SAndroid Build Coastguard Worker                       sizeof(data2_size) ));
204*2d543d20SAndroid Build Coastguard Worker 		return -1;
205*2d543d20SAndroid Build Coastguard Worker 	}
206*2d543d20SAndroid Build Coastguard Worker 
207*2d543d20SAndroid Build Coastguard Worker 	if (!data1_size || !data2_size || data1_size > MAX_DATA_BUF ||
208*2d543d20SAndroid Build Coastguard Worker 						data2_size > MAX_DATA_BUF ) {
209*2d543d20SAndroid Build Coastguard Worker 		log_debug("Header invalid data1_size=%u data2_size=%u\n",
210*2d543d20SAndroid Build Coastguard Worker 		        data1_size, data2_size);
211*2d543d20SAndroid Build Coastguard Worker 		return -1;
212*2d543d20SAndroid Build Coastguard Worker 	}
213*2d543d20SAndroid Build Coastguard Worker 
214*2d543d20SAndroid Build Coastguard Worker 	data1 = malloc(data1_size);
215*2d543d20SAndroid Build Coastguard Worker 	if (!data1) {
216*2d543d20SAndroid Build Coastguard Worker 		log_debug("Could not allocate %d bytes\n", data1_size);
217*2d543d20SAndroid Build Coastguard Worker 		return -1;
218*2d543d20SAndroid Build Coastguard Worker 	}
219*2d543d20SAndroid Build Coastguard Worker 	data2 = malloc(data2_size);
220*2d543d20SAndroid Build Coastguard Worker 	if (!data2) {
221*2d543d20SAndroid Build Coastguard Worker 		free(data1);
222*2d543d20SAndroid Build Coastguard Worker 		log_debug("Could not allocate %d bytes\n", data2_size);
223*2d543d20SAndroid Build Coastguard Worker 		return -1;
224*2d543d20SAndroid Build Coastguard Worker 	}
225*2d543d20SAndroid Build Coastguard Worker 
226*2d543d20SAndroid Build Coastguard Worker 	req_data[0].iov_base = data1;
227*2d543d20SAndroid Build Coastguard Worker 	req_data[0].iov_len = data1_size;
228*2d543d20SAndroid Build Coastguard Worker 	req_data[1].iov_base = data2;
229*2d543d20SAndroid Build Coastguard Worker 	req_data[1].iov_len = data2_size;
230*2d543d20SAndroid Build Coastguard Worker 
231*2d543d20SAndroid Build Coastguard Worker 	while (((count = readv(fd, req_data, 2)) < 0) && (errno == EINTR));
232*2d543d20SAndroid Build Coastguard Worker 	if (count <= 0 || (size_t)count != (data1_size + data2_size) ||
233*2d543d20SAndroid Build Coastguard Worker 	    data1[data1_size - 1] != '\0' || data2[data2_size - 1] != '\0') {
234*2d543d20SAndroid Build Coastguard Worker 		free(data1);
235*2d543d20SAndroid Build Coastguard Worker 		free(data2);
236*2d543d20SAndroid Build Coastguard Worker 		log_debug("Failed to read request data (%d)\n", (int)count);
237*2d543d20SAndroid Build Coastguard Worker 		return -1;
238*2d543d20SAndroid Build Coastguard Worker 	}
239*2d543d20SAndroid Build Coastguard Worker 
240*2d543d20SAndroid Build Coastguard Worker 	ret = process_request(fd, function, data1, data2);
241*2d543d20SAndroid Build Coastguard Worker 
242*2d543d20SAndroid Build Coastguard Worker 	free(data1);
243*2d543d20SAndroid Build Coastguard Worker 	free(data2);
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker 	return ret;
246*2d543d20SAndroid Build Coastguard Worker }
247*2d543d20SAndroid Build Coastguard Worker 
248*2d543d20SAndroid Build Coastguard Worker static int
add_pollfd(struct pollfd ** ufds,int * nfds,int connfd)249*2d543d20SAndroid Build Coastguard Worker add_pollfd(struct pollfd **ufds, int *nfds, int connfd)
250*2d543d20SAndroid Build Coastguard Worker {
251*2d543d20SAndroid Build Coastguard Worker 	int ii = 0;
252*2d543d20SAndroid Build Coastguard Worker 
253*2d543d20SAndroid Build Coastguard Worker 	/* First see if we can find an already invalidated ufd */
254*2d543d20SAndroid Build Coastguard Worker 	for (ii = 0; ii < *nfds; ii++) {
255*2d543d20SAndroid Build Coastguard Worker 		if ((*ufds)[ii].fd == -1)
256*2d543d20SAndroid Build Coastguard Worker 			break;
257*2d543d20SAndroid Build Coastguard Worker 	}
258*2d543d20SAndroid Build Coastguard Worker 
259*2d543d20SAndroid Build Coastguard Worker 	if (ii == *nfds) {
260*2d543d20SAndroid Build Coastguard Worker 		struct pollfd *tmp = (struct pollfd *)realloc(*ufds,
261*2d543d20SAndroid Build Coastguard Worker 					(*nfds+1)*sizeof(struct pollfd));
262*2d543d20SAndroid Build Coastguard Worker 		if (!tmp) {
263*2d543d20SAndroid Build Coastguard Worker 			syslog(LOG_ERR, "realloc failed for %d fds", *nfds+1);
264*2d543d20SAndroid Build Coastguard Worker 			return -1;
265*2d543d20SAndroid Build Coastguard Worker 		}
266*2d543d20SAndroid Build Coastguard Worker 
267*2d543d20SAndroid Build Coastguard Worker 		*ufds = tmp;
268*2d543d20SAndroid Build Coastguard Worker 		(*nfds)++;
269*2d543d20SAndroid Build Coastguard Worker 	}
270*2d543d20SAndroid Build Coastguard Worker 
271*2d543d20SAndroid Build Coastguard Worker 	(*ufds)[ii].fd = connfd;
272*2d543d20SAndroid Build Coastguard Worker 	(*ufds)[ii].events = POLLIN|POLLPRI;
273*2d543d20SAndroid Build Coastguard Worker 	(*ufds)[ii].revents = 0;
274*2d543d20SAndroid Build Coastguard Worker 
275*2d543d20SAndroid Build Coastguard Worker 	return 0;
276*2d543d20SAndroid Build Coastguard Worker }
277*2d543d20SAndroid Build Coastguard Worker 
278*2d543d20SAndroid Build Coastguard Worker static void
adj_pollfds(struct pollfd ** ufds,int * nfds)279*2d543d20SAndroid Build Coastguard Worker adj_pollfds(struct pollfd **ufds, int *nfds)
280*2d543d20SAndroid Build Coastguard Worker {
281*2d543d20SAndroid Build Coastguard Worker 	int ii, jj;
282*2d543d20SAndroid Build Coastguard Worker 
283*2d543d20SAndroid Build Coastguard Worker 	jj = 0;
284*2d543d20SAndroid Build Coastguard Worker 	for (ii = 0; ii < *nfds; ii++) {
285*2d543d20SAndroid Build Coastguard Worker 		if ((*ufds)[ii].fd != -1) {
286*2d543d20SAndroid Build Coastguard Worker 			if (jj < ii)
287*2d543d20SAndroid Build Coastguard Worker 				(*ufds)[jj] = (*ufds)[ii];
288*2d543d20SAndroid Build Coastguard Worker 			jj++;
289*2d543d20SAndroid Build Coastguard Worker 		}
290*2d543d20SAndroid Build Coastguard Worker 	}
291*2d543d20SAndroid Build Coastguard Worker 	*nfds = jj;
292*2d543d20SAndroid Build Coastguard Worker }
293*2d543d20SAndroid Build Coastguard Worker 
294*2d543d20SAndroid Build Coastguard Worker static int
process_events(struct pollfd ** ufds,int * nfds)295*2d543d20SAndroid Build Coastguard Worker process_events(struct pollfd **ufds, int *nfds)
296*2d543d20SAndroid Build Coastguard Worker {
297*2d543d20SAndroid Build Coastguard Worker 	int ii = 0;
298*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
299*2d543d20SAndroid Build Coastguard Worker 
300*2d543d20SAndroid Build Coastguard Worker 	for (ii = 0; ii < *nfds; ii++) {
301*2d543d20SAndroid Build Coastguard Worker 		short revents = (*ufds)[ii].revents;
302*2d543d20SAndroid Build Coastguard Worker 		int connfd = (*ufds)[ii].fd;
303*2d543d20SAndroid Build Coastguard Worker 
304*2d543d20SAndroid Build Coastguard Worker 		if (revents & (POLLIN | POLLPRI)) {
305*2d543d20SAndroid Build Coastguard Worker 			if (connfd == sockfd) {
306*2d543d20SAndroid Build Coastguard Worker 
307*2d543d20SAndroid Build Coastguard Worker 				/* Probably received a connection */
308*2d543d20SAndroid Build Coastguard Worker 				if ((connfd = accept(sockfd, NULL, NULL)) < 0) {
309*2d543d20SAndroid Build Coastguard Worker 					syslog(LOG_ERR, "accept() failed: %m");
310*2d543d20SAndroid Build Coastguard Worker 					return -1;
311*2d543d20SAndroid Build Coastguard Worker 				}
312*2d543d20SAndroid Build Coastguard Worker 
313*2d543d20SAndroid Build Coastguard Worker 				if (add_pollfd(ufds, nfds, connfd)) {
314*2d543d20SAndroid Build Coastguard Worker 					syslog(LOG_ERR,
315*2d543d20SAndroid Build Coastguard Worker 					  "Failed to add fd (%d) to poll list\n",
316*2d543d20SAndroid Build Coastguard Worker 						connfd);
317*2d543d20SAndroid Build Coastguard Worker 					return -1;
318*2d543d20SAndroid Build Coastguard Worker 				}
319*2d543d20SAndroid Build Coastguard Worker 			} else {
320*2d543d20SAndroid Build Coastguard Worker 				ret = service_request(connfd);
321*2d543d20SAndroid Build Coastguard Worker 				if (ret) {
322*2d543d20SAndroid Build Coastguard Worker 					if (ret < 0) {
323*2d543d20SAndroid Build Coastguard Worker 						syslog(LOG_ERR,
324*2d543d20SAndroid Build Coastguard Worker 							"Servicing of request "
325*2d543d20SAndroid Build Coastguard Worker 							"failed for fd (%d)\n",
326*2d543d20SAndroid Build Coastguard Worker 							connfd);
327*2d543d20SAndroid Build Coastguard Worker 					}
328*2d543d20SAndroid Build Coastguard Worker 					/* Setup pollfd for deletion later. */
329*2d543d20SAndroid Build Coastguard Worker 					(*ufds)[ii].fd = -1;
330*2d543d20SAndroid Build Coastguard Worker 					close(connfd);
331*2d543d20SAndroid Build Coastguard Worker 					connfd = -1;
332*2d543d20SAndroid Build Coastguard Worker 					/* So we don't get bothered later */
333*2d543d20SAndroid Build Coastguard Worker 					revents = revents & ~(POLLHUP);
334*2d543d20SAndroid Build Coastguard Worker 				}
335*2d543d20SAndroid Build Coastguard Worker 			}
336*2d543d20SAndroid Build Coastguard Worker 			revents = revents & ~(POLLIN | POLLPRI);
337*2d543d20SAndroid Build Coastguard Worker 		}
338*2d543d20SAndroid Build Coastguard Worker 		if (revents & POLLHUP) {
339*2d543d20SAndroid Build Coastguard Worker 			log_debug("The connection with fd (%d) hung up\n",
340*2d543d20SAndroid Build Coastguard Worker 				connfd);
341*2d543d20SAndroid Build Coastguard Worker 
342*2d543d20SAndroid Build Coastguard Worker 			/* Set the pollfd up for deletion later. */
343*2d543d20SAndroid Build Coastguard Worker 			(*ufds)[ii].fd = -1;
344*2d543d20SAndroid Build Coastguard Worker 			close(connfd);
345*2d543d20SAndroid Build Coastguard Worker 			connfd = -1;
346*2d543d20SAndroid Build Coastguard Worker 
347*2d543d20SAndroid Build Coastguard Worker 			revents = revents & ~(POLLHUP);
348*2d543d20SAndroid Build Coastguard Worker 		}
349*2d543d20SAndroid Build Coastguard Worker 		if (revents && connfd != -1) {
350*2d543d20SAndroid Build Coastguard Worker 			syslog(LOG_ERR, "Unknown/error events (%x) encountered"
351*2d543d20SAndroid Build Coastguard Worker 					" for fd (%d)\n", revents, connfd);
352*2d543d20SAndroid Build Coastguard Worker 
353*2d543d20SAndroid Build Coastguard Worker 			/* Set the pollfd up for deletion later. */
354*2d543d20SAndroid Build Coastguard Worker 			(*ufds)[ii].fd = -1;
355*2d543d20SAndroid Build Coastguard Worker 			close(connfd);
356*2d543d20SAndroid Build Coastguard Worker 		}
357*2d543d20SAndroid Build Coastguard Worker 
358*2d543d20SAndroid Build Coastguard Worker 		(*ufds)[ii].revents = 0;
359*2d543d20SAndroid Build Coastguard Worker 	}
360*2d543d20SAndroid Build Coastguard Worker 
361*2d543d20SAndroid Build Coastguard Worker 	/* Delete any invalidated ufds */
362*2d543d20SAndroid Build Coastguard Worker 	adj_pollfds(ufds, nfds);
363*2d543d20SAndroid Build Coastguard Worker 
364*2d543d20SAndroid Build Coastguard Worker 	return 0;
365*2d543d20SAndroid Build Coastguard Worker }
366*2d543d20SAndroid Build Coastguard Worker 
367*2d543d20SAndroid Build Coastguard Worker static void
368*2d543d20SAndroid Build Coastguard Worker process_connections(void) __attribute__ ((noreturn));
369*2d543d20SAndroid Build Coastguard Worker 
370*2d543d20SAndroid Build Coastguard Worker static void
process_connections(void)371*2d543d20SAndroid Build Coastguard Worker process_connections(void)
372*2d543d20SAndroid Build Coastguard Worker {
373*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
374*2d543d20SAndroid Build Coastguard Worker 	int nfds = 1;
375*2d543d20SAndroid Build Coastguard Worker 
376*2d543d20SAndroid Build Coastguard Worker 	struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd));
377*2d543d20SAndroid Build Coastguard Worker 	if (!ufds) {
378*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to allocate a pollfd");
379*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
380*2d543d20SAndroid Build Coastguard Worker 	}
381*2d543d20SAndroid Build Coastguard Worker 	ufds[0].fd = sockfd;
382*2d543d20SAndroid Build Coastguard Worker 	ufds[0].events = POLLIN|POLLPRI;
383*2d543d20SAndroid Build Coastguard Worker 	ufds[0].revents = 0;
384*2d543d20SAndroid Build Coastguard Worker 
385*2d543d20SAndroid Build Coastguard Worker 	while (1) {
386*2d543d20SAndroid Build Coastguard Worker 		if (restart_daemon) {
387*2d543d20SAndroid Build Coastguard Worker 			syslog(LOG_NOTICE, "Reload Translations");
388*2d543d20SAndroid Build Coastguard Worker 			finish_context_colors();
389*2d543d20SAndroid Build Coastguard Worker 			finish_context_translations();
390*2d543d20SAndroid Build Coastguard Worker 			if (init_translations()) {
391*2d543d20SAndroid Build Coastguard Worker 				syslog(LOG_ERR, "Failed to initialize label translations");
392*2d543d20SAndroid Build Coastguard Worker 				cleanup_exit(1);
393*2d543d20SAndroid Build Coastguard Worker 			}
394*2d543d20SAndroid Build Coastguard Worker 			if (init_colors()) {
395*2d543d20SAndroid Build Coastguard Worker 				syslog(LOG_ERR, "Failed to initialize color translations");
396*2d543d20SAndroid Build Coastguard Worker 				syslog(LOG_ERR, "No color information will be available");
397*2d543d20SAndroid Build Coastguard Worker 			}
398*2d543d20SAndroid Build Coastguard Worker 			restart_daemon = 0;
399*2d543d20SAndroid Build Coastguard Worker 		}
400*2d543d20SAndroid Build Coastguard Worker 
401*2d543d20SAndroid Build Coastguard Worker 		ret = poll(ufds, nfds, -1);
402*2d543d20SAndroid Build Coastguard Worker 		if (ret < 0) {
403*2d543d20SAndroid Build Coastguard Worker 			if (errno == EINTR) {
404*2d543d20SAndroid Build Coastguard Worker 				continue;
405*2d543d20SAndroid Build Coastguard Worker 			}
406*2d543d20SAndroid Build Coastguard Worker 			syslog(LOG_ERR, "poll() failed: %m");
407*2d543d20SAndroid Build Coastguard Worker 			cleanup_exit(1);
408*2d543d20SAndroid Build Coastguard Worker 		}
409*2d543d20SAndroid Build Coastguard Worker 
410*2d543d20SAndroid Build Coastguard Worker 		ret = process_events(&ufds, &nfds);
411*2d543d20SAndroid Build Coastguard Worker 		if (ret) {
412*2d543d20SAndroid Build Coastguard Worker 			syslog(LOG_ERR, "Error processing events");
413*2d543d20SAndroid Build Coastguard Worker 			cleanup_exit(1);
414*2d543d20SAndroid Build Coastguard Worker 		}
415*2d543d20SAndroid Build Coastguard Worker 	}
416*2d543d20SAndroid Build Coastguard Worker }
417*2d543d20SAndroid Build Coastguard Worker 
418*2d543d20SAndroid Build Coastguard Worker static void
419*2d543d20SAndroid Build Coastguard Worker sigterm_handler(int sig) __attribute__ ((noreturn));
420*2d543d20SAndroid Build Coastguard Worker 
421*2d543d20SAndroid Build Coastguard Worker static void
sigterm_handler(int UNUSED (sig))422*2d543d20SAndroid Build Coastguard Worker sigterm_handler(int UNUSED(sig))
423*2d543d20SAndroid Build Coastguard Worker {
424*2d543d20SAndroid Build Coastguard Worker 	cleanup_exit(0);
425*2d543d20SAndroid Build Coastguard Worker }
426*2d543d20SAndroid Build Coastguard Worker 
427*2d543d20SAndroid Build Coastguard Worker static void
sighup_handler(int UNUSED (sig))428*2d543d20SAndroid Build Coastguard Worker sighup_handler(int UNUSED(sig))
429*2d543d20SAndroid Build Coastguard Worker {
430*2d543d20SAndroid Build Coastguard Worker 	restart_daemon = 1;
431*2d543d20SAndroid Build Coastguard Worker }
432*2d543d20SAndroid Build Coastguard Worker 
433*2d543d20SAndroid Build Coastguard Worker static void
initialize(void)434*2d543d20SAndroid Build Coastguard Worker initialize(void)
435*2d543d20SAndroid Build Coastguard Worker {
436*2d543d20SAndroid Build Coastguard Worker 	struct sigaction act;
437*2d543d20SAndroid Build Coastguard Worker 	struct sockaddr_un addr;
438*2d543d20SAndroid Build Coastguard Worker 	struct rlimit rl ;
439*2d543d20SAndroid Build Coastguard Worker 
440*2d543d20SAndroid Build Coastguard Worker 	if (init_translations()) {
441*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to initialize label translations");
442*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
443*2d543d20SAndroid Build Coastguard Worker 	}
444*2d543d20SAndroid Build Coastguard Worker 	if (init_colors()) {
445*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Failed to initialize color translations");
446*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "No color information will be available");
447*2d543d20SAndroid Build Coastguard Worker 	}
448*2d543d20SAndroid Build Coastguard Worker 
449*2d543d20SAndroid Build Coastguard Worker 	/* the socket will be unlinked when the daemon terminates */
450*2d543d20SAndroid Build Coastguard Worker 	act.sa_handler = sigterm_handler;
451*2d543d20SAndroid Build Coastguard Worker 	sigemptyset(&act.sa_mask);
452*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGINT);
453*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGQUIT);
454*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGTERM);
455*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGHUP);
456*2d543d20SAndroid Build Coastguard Worker 	act.sa_flags = 0;
457*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGINT, &act, NULL);
458*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGQUIT, &act, NULL);
459*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGTERM, &act, NULL);
460*2d543d20SAndroid Build Coastguard Worker 
461*2d543d20SAndroid Build Coastguard Worker 	/* restart the daemon on SIGHUP */
462*2d543d20SAndroid Build Coastguard Worker 	act.sa_handler = sighup_handler;
463*2d543d20SAndroid Build Coastguard Worker 	sigemptyset(&act.sa_mask);
464*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGINT);
465*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGQUIT);
466*2d543d20SAndroid Build Coastguard Worker 	sigaddset(&act.sa_mask, SIGTERM);
467*2d543d20SAndroid Build Coastguard Worker 	act.sa_flags = 0;
468*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGHUP, &act, NULL);
469*2d543d20SAndroid Build Coastguard Worker 
470*2d543d20SAndroid Build Coastguard Worker 	/* ignore SIGPIPE (in case a client terminates after sending request) */
471*2d543d20SAndroid Build Coastguard Worker 	act.sa_handler = SIG_IGN;
472*2d543d20SAndroid Build Coastguard Worker 	sigemptyset(&act.sa_mask);
473*2d543d20SAndroid Build Coastguard Worker 	act.sa_flags = 0;
474*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGPIPE, &act, NULL);
475*2d543d20SAndroid Build Coastguard Worker 
476*2d543d20SAndroid Build Coastguard Worker 	atexit(clean_exit);
477*2d543d20SAndroid Build Coastguard Worker 
478*2d543d20SAndroid Build Coastguard Worker 	sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
479*2d543d20SAndroid Build Coastguard Worker 	if (sockfd < 0)	{
480*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "socket() failed: %m");
481*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
482*2d543d20SAndroid Build Coastguard Worker 	}
483*2d543d20SAndroid Build Coastguard Worker 
484*2d543d20SAndroid Build Coastguard Worker 	memset(&addr, 0, sizeof(addr));
485*2d543d20SAndroid Build Coastguard Worker 	addr.sun_family = AF_UNIX;
486*2d543d20SAndroid Build Coastguard Worker 	strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path) - 1);
487*2d543d20SAndroid Build Coastguard Worker 
488*2d543d20SAndroid Build Coastguard Worker 	(void)unlink(SETRANS_UNIX_SOCKET);
489*2d543d20SAndroid Build Coastguard Worker 
490*2d543d20SAndroid Build Coastguard Worker 	if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
491*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "bind() failed: %m");
492*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
493*2d543d20SAndroid Build Coastguard Worker 	}
494*2d543d20SAndroid Build Coastguard Worker 
495*2d543d20SAndroid Build Coastguard Worker 	if (listen(sockfd, SOMAXCONN) < 0) {
496*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "listen() failed: %m");
497*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
498*2d543d20SAndroid Build Coastguard Worker 	}
499*2d543d20SAndroid Build Coastguard Worker 
500*2d543d20SAndroid Build Coastguard Worker 	if (chmod(SETRANS_UNIX_SOCKET, S_IRWXU | S_IRWXG | S_IRWXO)) {
501*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "chmod() failed: %m");
502*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
503*2d543d20SAndroid Build Coastguard Worker 	}
504*2d543d20SAndroid Build Coastguard Worker 
505*2d543d20SAndroid Build Coastguard Worker 	/* Raise the rlimit for file descriptors... */
506*2d543d20SAndroid Build Coastguard Worker 	rl.rlim_max = MAX_DESCRIPTORS;
507*2d543d20SAndroid Build Coastguard Worker 	rl.rlim_cur = MAX_DESCRIPTORS;
508*2d543d20SAndroid Build Coastguard Worker 	setrlimit(RLIMIT_NOFILE, &rl);
509*2d543d20SAndroid Build Coastguard Worker 
510*2d543d20SAndroid Build Coastguard Worker }
511*2d543d20SAndroid Build Coastguard Worker 
dropprivs(void)512*2d543d20SAndroid Build Coastguard Worker static void dropprivs(void)
513*2d543d20SAndroid Build Coastguard Worker {
514*2d543d20SAndroid Build Coastguard Worker 	cap_t new_caps;
515*2d543d20SAndroid Build Coastguard Worker 
516*2d543d20SAndroid Build Coastguard Worker 	new_caps = cap_init();
517*2d543d20SAndroid Build Coastguard Worker 	if (cap_set_proc(new_caps)) {
518*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "Error dropping capabilities, aborting: %s\n",
519*2d543d20SAndroid Build Coastguard Worker 			 strerror(errno));
520*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(-1);
521*2d543d20SAndroid Build Coastguard Worker 	}
522*2d543d20SAndroid Build Coastguard Worker 	cap_free(new_caps);
523*2d543d20SAndroid Build Coastguard Worker }
524*2d543d20SAndroid Build Coastguard Worker 
usage(char * program)525*2d543d20SAndroid Build Coastguard Worker static void usage(char *program)
526*2d543d20SAndroid Build Coastguard Worker {
527*2d543d20SAndroid Build Coastguard Worker 	printf("%s [-f] [-h] \n", program);
528*2d543d20SAndroid Build Coastguard Worker }
529*2d543d20SAndroid Build Coastguard Worker 
530*2d543d20SAndroid Build Coastguard Worker int
main(int argc,char * argv[])531*2d543d20SAndroid Build Coastguard Worker main(int argc, char *argv[])
532*2d543d20SAndroid Build Coastguard Worker {
533*2d543d20SAndroid Build Coastguard Worker 	int opt;
534*2d543d20SAndroid Build Coastguard Worker 	int do_fork = 1;
535*2d543d20SAndroid Build Coastguard Worker 	while ((opt = getopt(argc, argv, "hf")) > 0) {
536*2d543d20SAndroid Build Coastguard Worker 		switch (opt) {
537*2d543d20SAndroid Build Coastguard Worker 		case 'f':
538*2d543d20SAndroid Build Coastguard Worker 			do_fork = 0;
539*2d543d20SAndroid Build Coastguard Worker 			break;
540*2d543d20SAndroid Build Coastguard Worker 		case 'h':
541*2d543d20SAndroid Build Coastguard Worker 			usage(argv[0]);
542*2d543d20SAndroid Build Coastguard Worker 			exit(0);
543*2d543d20SAndroid Build Coastguard Worker 			break;
544*2d543d20SAndroid Build Coastguard Worker 		case '?':
545*2d543d20SAndroid Build Coastguard Worker 			usage(argv[0]);
546*2d543d20SAndroid Build Coastguard Worker 			exit(-1);
547*2d543d20SAndroid Build Coastguard Worker 		}
548*2d543d20SAndroid Build Coastguard Worker 	}
549*2d543d20SAndroid Build Coastguard Worker 
550*2d543d20SAndroid Build Coastguard Worker #ifndef DEBUG
551*2d543d20SAndroid Build Coastguard Worker 	/* Make sure we are root */
552*2d543d20SAndroid Build Coastguard Worker 	if (getuid() != 0) {
553*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "You must be root to run this program.\n");
554*2d543d20SAndroid Build Coastguard Worker 		return 4;
555*2d543d20SAndroid Build Coastguard Worker 	}
556*2d543d20SAndroid Build Coastguard Worker #endif
557*2d543d20SAndroid Build Coastguard Worker 
558*2d543d20SAndroid Build Coastguard Worker 	openlog(SETRANSD_PROGNAME, 0, LOG_DAEMON);
559*2d543d20SAndroid Build Coastguard Worker 	syslog(LOG_NOTICE, "%s starting", argv[0]);
560*2d543d20SAndroid Build Coastguard Worker 
561*2d543d20SAndroid Build Coastguard Worker 	initialize();
562*2d543d20SAndroid Build Coastguard Worker 
563*2d543d20SAndroid Build Coastguard Worker #ifndef DEBUG
564*2d543d20SAndroid Build Coastguard Worker 	dropprivs();
565*2d543d20SAndroid Build Coastguard Worker 
566*2d543d20SAndroid Build Coastguard Worker 	/* run in the background as a daemon */
567*2d543d20SAndroid Build Coastguard Worker 	if (do_fork && daemon(0, 0)) {
568*2d543d20SAndroid Build Coastguard Worker 		syslog(LOG_ERR, "daemon() failed: %m");
569*2d543d20SAndroid Build Coastguard Worker 		cleanup_exit(1);
570*2d543d20SAndroid Build Coastguard Worker 	}
571*2d543d20SAndroid Build Coastguard Worker #endif
572*2d543d20SAndroid Build Coastguard Worker 
573*2d543d20SAndroid Build Coastguard Worker 	syslog(LOG_NOTICE, "%s initialized", argv[0]);
574*2d543d20SAndroid Build Coastguard Worker 	process_connections();
575*2d543d20SAndroid Build Coastguard Worker 
576*2d543d20SAndroid Build Coastguard Worker 	/* we should never get here */
577*2d543d20SAndroid Build Coastguard Worker 	return 1;
578*2d543d20SAndroid Build Coastguard Worker }
579*2d543d20SAndroid Build Coastguard Worker 
580