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