xref: /openbsd-src/usr.sbin/relayd/proc.c (revision d13be5d47e4149db2549a9828e244d59dbc43f15)
1 /*	$OpenBSD: proc.c,v 1.3 2011/09/04 20:26:58 bluhm Exp $	*/
2 
3 /*
4  * Copyright (c) 2010,2011 Reyk Floeter <reyk@openbsd.org>
5  * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/types.h>
21 #include <sys/queue.h>
22 #include <sys/socket.h>
23 #include <sys/wait.h>
24 #include <sys/tree.h>
25 
26 #include <net/if.h>
27 #include <netinet/in_systm.h>
28 #include <netinet/in.h>
29 #include <netinet/ip.h>
30 #include <arpa/inet.h>
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <signal.h>
38 #include <pwd.h>
39 #include <event.h>
40 
41 #include <openssl/rand.h>
42 #include <openssl/ssl.h>
43 
44 #include "relayd.h"
45 
46 void	 proc_setup(struct privsep *);
47 int	 proc_ispeer(struct privsep_proc *, u_int, enum privsep_procid);
48 void	 proc_shutdown(struct privsep_proc *);
49 void	 proc_sig_handler(int, short, void *);
50 void	 proc_range(struct privsep *, enum privsep_procid, int *, int *);
51 
52 int
53 proc_ispeer(struct privsep_proc *p, u_int nproc, enum privsep_procid type)
54 {
55 	u_int	i;
56 
57 	for (i = 0; i < nproc; i++)
58 		if (p[i].p_id == type)
59 			return (1);
60 	return (0);
61 }
62 
63 void
64 proc_init(struct privsep *ps, struct privsep_proc *p, u_int nproc)
65 {
66 	u_int	 i;
67 
68 	/*
69 	 * Called from parent
70 	 */
71 	privsep_process = PROC_PARENT;
72 	ps->ps_instances[PROC_PARENT] = 1;
73 	ps->ps_title[PROC_PARENT] = "parent";
74 	ps->ps_pid[PROC_PARENT] = getpid();
75 
76 	for (i = 0; i < nproc; i++) {
77 		/* Default to 1 process instance */
78 		if (ps->ps_instances[p[i].p_id] < 1)
79 			ps->ps_instances[p[i].p_id] = 1;
80 		ps->ps_title[p[i].p_id] = p[i].p_title;
81 	}
82 
83 	proc_setup(ps);
84 
85 	/* Engage! */
86 	for (i = 0; i < nproc; i++)
87 		ps->ps_pid[p[i].p_id] = (*p[i].p_init)(ps, &p[i]);
88 }
89 
90 void
91 proc_kill(struct privsep *ps)
92 {
93 	pid_t		 pid;
94 	u_int		 i;
95 
96 	if (privsep_process != PROC_PARENT)
97 		return;
98 
99 	for (i = 0; i < PROC_MAX; i++) {
100 		if (ps->ps_pid[i] == 0)
101 			continue;
102 		killpg(ps->ps_pid[i], SIGTERM);
103 	}
104 
105 	do {
106 		pid = waitpid(WAIT_ANY, NULL, 0);
107 	} while (pid != -1 || (pid == -1 && errno == EINTR));
108 
109 	proc_clear(ps, 1);
110 }
111 
112 void
113 proc_setup(struct privsep *ps)
114 {
115 	int	 i, j, n, count, sockpair[2];
116 
117 	for (i = 0; i < PROC_MAX; i++)
118 		for (j = 0; j < PROC_MAX; j++) {
119 			/*
120 			 * find out how many instances of this peer there are.
121 			 */
122 			if (i >= j || ps->ps_instances[i] == 0||
123 			   ps->ps_instances[j] == 0)
124 				continue;
125 
126 			if (ps->ps_instances[i] > 1 &&
127 			    ps->ps_instances[j] > 1)
128 				fatalx("N:M peering not supported");
129 
130 			count = ps->ps_instances[i] * ps->ps_instances[j];
131 
132 			if ((ps->ps_pipes[i][j] =
133 			    calloc(count, sizeof(int))) == NULL ||
134 			    (ps->ps_pipes[j][i] =
135 			    calloc(count, sizeof(int))) == NULL)
136 				fatal(NULL);
137 
138 			for (n = 0; n < count; n++) {
139 				if (ps->ps_noaction)
140 					continue;
141 				if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
142 				    sockpair) == -1)
143 					fatal("socketpair");
144 				ps->ps_pipes[i][j][n] = sockpair[0];
145 				ps->ps_pipes[j][i][n] = sockpair[1];
146 				socket_set_blockmode(
147 				    ps->ps_pipes[i][j][n],
148 				    BM_NONBLOCK);
149 				socket_set_blockmode(
150 				    ps->ps_pipes[j][i][n],
151 				    BM_NONBLOCK);
152 			}
153 		}
154 }
155 
156 void
157 proc_config(struct privsep *ps, struct privsep_proc *p, u_int nproc)
158 {
159 	u_int	i, j, src, dst, count, n, instance;
160 
161 	src = privsep_process;
162 
163 	/*
164 	 * close unused pipes
165 	 */
166 	for (i = 0; i < PROC_MAX; i++) {
167 		for (j = 0; j < PROC_MAX; j++) {
168 			if (i == j ||
169 			    ps->ps_instances[i] == 0 ||
170 			    ps->ps_instances[j] == 0)
171 				continue;
172 
173 			count = ps->ps_instances[i] * ps->ps_instances[j];
174 
175 			for (n = 0; n < count; n++) {
176 				instance = ps->ps_instances[i] > 1 ? n : 0;
177 				if (i == src &&
178 				    proc_ispeer(p, nproc, j) &&
179 				    ps->ps_instance == instance)
180 					continue;
181 
182 				if (!ps->ps_noaction)
183 					close(ps->ps_pipes[i][j][n]);
184 				ps->ps_pipes[i][j][n] = -1;
185 			}
186 		}
187 	}
188 
189 	/*
190 	 * listen on appropriate pipes
191 	 */
192 	for (i = 0; i < nproc; i++) {
193 		dst = p[i].p_id;
194 		p[i].p_ps = ps;
195 		p[i].p_env = ps->ps_env;
196 
197 		if (src == dst)
198 			fatal("proc_config: cannot peer with oneself");
199 
200 		count = ps->ps_instances[src] * ps->ps_instances[dst];
201 
202 		if ((ps->ps_ievs[dst] = calloc(count,
203 		    sizeof(struct imsgev))) == NULL)
204 			fatal("proc_config");
205 
206 		for (n = 0; n < count; n++) {
207 			if (ps->ps_pipes[src][dst][n] == -1)
208 				continue;
209 
210 			imsg_init(&(ps->ps_ievs[dst][n].ibuf),
211 			    ps->ps_pipes[src][dst][n]);
212 			ps->ps_ievs[dst][n].handler = proc_dispatch;
213 			ps->ps_ievs[dst][n].events = EV_READ;
214 			ps->ps_ievs[dst][n].proc = &p[i];
215 			ps->ps_ievs[dst][n].data = &ps->ps_ievs[dst][n];
216 			p[i].p_instance = n;
217 
218 			event_set(&(ps->ps_ievs[dst][n].ev),
219 			    ps->ps_ievs[dst][n].ibuf.fd,
220 			    ps->ps_ievs[dst][n].events,
221 			    ps->ps_ievs[dst][n].handler,
222 			    ps->ps_ievs[dst][n].data);
223 			event_add(&(ps->ps_ievs[dst][n].ev), NULL);
224 		}
225 	}
226 }
227 
228 void
229 proc_clear(struct privsep *ps, int purge)
230 {
231 	u_int	 src = privsep_process, dst, n, count;
232 
233 	if (ps == NULL)
234 		return;
235 
236 	for (dst = 0; dst < PROC_MAX; dst++) {
237 		if (src == dst || ps->ps_ievs[dst] == NULL)
238 			continue;
239 
240 		count = ps->ps_instances[src] * ps->ps_instances[dst];
241 
242 		for (n = 0; n < count; n++) {
243 			if (ps->ps_pipes[src][dst][n] == -1)
244 				continue;
245 			if (purge) {
246 				event_del(&(ps->ps_ievs[dst][n].ev));
247 				imsg_clear(&(ps->ps_ievs[dst][n].ibuf));
248 				close(ps->ps_pipes[src][dst][n]);
249 			} else
250 				imsg_flush(&(ps->ps_ievs[dst][n].ibuf));
251 		}
252 		if (purge)
253 			free(ps->ps_ievs[dst]);
254 	}
255 }
256 
257 void
258 proc_shutdown(struct privsep_proc *p)
259 {
260 	struct privsep	*ps = p->p_ps;
261 
262 	if (p->p_id == PROC_CONTROL && ps)
263 		control_cleanup(&ps->ps_csock);
264 
265 	if (p->p_shutdown != NULL)
266 		(*p->p_shutdown)();
267 
268 	proc_clear(ps, 1);
269 
270 	log_info("%s exiting, pid %d", p->p_title, getpid());
271 
272 	_exit(0);
273 }
274 
275 void
276 proc_sig_handler(int sig, short event, void *arg)
277 {
278 	struct privsep_proc	*p = arg;
279 
280 	switch (sig) {
281 	case SIGINT:
282 	case SIGTERM:
283 		proc_shutdown(p);
284 		break;
285 	case SIGCHLD:
286 	case SIGHUP:
287 	case SIGPIPE:
288 		/* ignore */
289 		break;
290 	default:
291 		fatalx("proc_sig_handler: unexpected signal");
292 		/* NOTREACHED */
293 	}
294 }
295 
296 pid_t
297 proc_run(struct privsep *ps, struct privsep_proc *p,
298     struct privsep_proc *procs, u_int nproc,
299     void (*init)(struct privsep *, struct privsep_proc *, void *), void *arg)
300 {
301 	pid_t		 pid;
302 	struct passwd	*pw;
303 	const char	*root;
304 	u_int32_t	 seed[256];
305 	u_int		 n;
306 
307 	if (ps->ps_noaction)
308 		return (0);
309 
310 	switch (pid = fork()) {
311 	case -1:
312 		fatal("run_proc: cannot fork");
313 	case 0:
314 		/* Set the process group of the current process */
315 		setpgrp(0, getpid());
316 		break;
317 	default:
318 		return (pid);
319 	}
320 
321 	pw = ps->ps_pw;
322 
323 	if (p->p_id == PROC_CONTROL) {
324 		if (control_init(ps, &ps->ps_csock) == -1)
325 			fatalx(p->p_title);
326 	}
327 
328 	/* Change root directory */
329 	if (p->p_chroot != NULL)
330 		root = p->p_chroot;
331 	else
332 		root = pw->pw_dir;
333 
334 #ifndef DEBUG
335 	if (chroot(root) == -1)
336 		fatal("run_proc: chroot");
337 	if (chdir("/") == -1)
338 		fatal("run_proc: chdir(\"/\")");
339 #else
340 #warning disabling privilege revocation and chroot in DEBUG MODE
341 	if (p->p_chroot != NULL) {
342 		if (chroot(root) == -1)
343 			fatal("run_proc: chroot");
344 		if (chdir("/") == -1)
345 			fatal("run_proc: chdir(\"/\")");
346 	}
347 #endif
348 
349 	privsep_process = p->p_id;
350 
351 	setproctitle("%s", p->p_title);
352 
353 #ifndef DEBUG
354 	if (setgroups(1, &pw->pw_gid) ||
355 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
356 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
357 		fatal("run_proc: cannot drop privileges");
358 #endif
359 
360 	/* Fork child handlers */
361 	for (n = 1; n < ps->ps_instances[p->p_id]; n++) {
362 		if (fork() == 0) {
363 			ps->ps_instance = p->p_instance = n;
364 			break;
365 		}
366 	}
367 
368 #ifdef DEBUG
369 	log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title,
370 	    ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid());
371 #endif
372 
373 	event_init();
374 
375 	signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p);
376 	signal_set(&ps->ps_evsigterm, SIGTERM, proc_sig_handler, p);
377 	signal_set(&ps->ps_evsigchld, SIGCHLD, proc_sig_handler, p);
378 	signal_set(&ps->ps_evsighup, SIGHUP, proc_sig_handler, p);
379 	signal_set(&ps->ps_evsigpipe, SIGPIPE, proc_sig_handler, p);
380 
381 	signal_add(&ps->ps_evsigint, NULL);
382 	signal_add(&ps->ps_evsigterm, NULL);
383 	signal_add(&ps->ps_evsigchld, NULL);
384 	signal_add(&ps->ps_evsighup, NULL);
385 	signal_add(&ps->ps_evsigpipe, NULL);
386 
387 	proc_config(ps, procs, nproc);
388 
389 	arc4random_buf(seed, sizeof(seed));
390 	RAND_seed(seed, sizeof(seed));
391 
392 	if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
393 		TAILQ_INIT(&ctl_conns);
394 		if (control_listen(&ps->ps_csock) == -1)
395 			fatalx(p->p_title);
396 	}
397 
398 	if (init != NULL)
399 		init(ps, p, arg);
400 
401 	event_dispatch();
402 
403 	proc_shutdown(p);
404 
405 	return (0);
406 }
407 
408 void
409 proc_dispatch(int fd, short event, void *arg)
410 {
411 	struct imsgev		*iev = (struct imsgev *)arg;
412 	struct privsep_proc	*p = iev->proc;
413 	struct privsep		*ps = p->p_ps;
414 	struct imsgbuf		*ibuf;
415 	struct imsg		 imsg;
416 	ssize_t			 n;
417 	int			 verbose;
418 	const char		*title;
419 
420 	title = ps->ps_title[privsep_process];
421 	ibuf = &iev->ibuf;
422 
423 	if (event & EV_READ) {
424 		if ((n = imsg_read(ibuf)) == -1)
425 			fatal(title);
426 		if (n == 0) {
427 			/* this pipe is dead, so remove the event handler */
428 			event_del(&iev->ev);
429 			event_loopexit(NULL);
430 			return;
431 		}
432 	}
433 
434 	if (event & EV_WRITE) {
435 		if (msgbuf_write(&ibuf->w) == -1)
436 			fatal(title);
437 	}
438 
439 	for (;;) {
440 		if ((n = imsg_get(ibuf, &imsg)) == -1)
441 			fatal(title);
442 		if (n == 0)
443 			break;
444 
445 #if DEBUG > 1
446 		log_debug("%s: %s %d got imsg %d from %s %d",
447 		    __func__, title, ps->ps_instance + 1,
448 		    imsg.hdr.type, p->p_title, p->p_instance);
449 #endif
450 
451 		/*
452 		 * Check the message with the program callback
453 		 */
454 		if ((p->p_cb)(fd, p, &imsg) == 0) {
455 			/* Message was handled by the callback, continue */
456 			imsg_free(&imsg);
457 			continue;
458 		}
459 
460 		/*
461 		 * Generic message handling
462 		 */
463 		switch (imsg.hdr.type) {
464 		case IMSG_CTL_VERBOSE:
465 			IMSG_SIZE_CHECK(&imsg, &verbose);
466 			memcpy(&verbose, imsg.data, sizeof(verbose));
467 			log_verbose(verbose);
468 			break;
469 		default:
470 			log_warnx("%s: %s %d got invalid imsg %d from %s %d",
471 			    __func__, title, ps->ps_instance + 1,
472 			    imsg.hdr.type, p->p_title, p->p_instance);
473 			fatalx(title);
474 		}
475 		imsg_free(&imsg);
476 	}
477 	imsg_event_add(iev);
478 }
479 
480 /*
481  * imsg helper functions
482  */
483 
484 void
485 imsg_event_add(struct imsgev *iev)
486 {
487 	if (iev->handler == NULL) {
488 		imsg_flush(&iev->ibuf);
489 		return;
490 	}
491 
492 	iev->events = EV_READ;
493 	if (iev->ibuf.w.queued)
494 		iev->events |= EV_WRITE;
495 
496 	event_del(&iev->ev);
497 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
498 	event_add(&iev->ev, NULL);
499 }
500 
501 int
502 imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
503     pid_t pid, int fd, void *data, u_int16_t datalen)
504 {
505 	int	ret;
506 
507 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
508 	    pid, fd, data, datalen)) == -1)
509 		return (ret);
510 	imsg_event_add(iev);
511 	return (ret);
512 }
513 
514 int
515 imsg_composev_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid,
516     pid_t pid, int fd, const struct iovec *iov, int iovcnt)
517 {
518 	int	ret;
519 
520 	if ((ret = imsg_composev(&iev->ibuf, type, peerid,
521 	    pid, fd, iov, iovcnt)) == -1)
522 		return (ret);
523 	imsg_event_add(iev);
524 	return (ret);
525 }
526 
527 void
528 proc_range(struct privsep *ps, enum privsep_procid id, int *n, int *m)
529 {
530 	if (*n == -1) {
531 		/*
532 		 * -1 means that the current process is
533 		 * N:1 - one of many processes connected to a single peer,
534 		 *       so find the right slot of the peer.
535 		 * 1:N - a single process connected to many peers,
536 		 *       so find the range of slots of all peers.
537 		 */
538 		if (ps->ps_instances[privsep_process] <=
539 		    ps->ps_instances[id]) {
540 			*n = 0;
541 			*m = ps->ps_instances[id];
542 			return;
543 		}
544 
545 		*n = ps->ps_instance;
546 		*m = ps->ps_instance + 1;
547 	} else {
548 		/* Use only a single slot of the specified peer process */
549 		*m = *n + 1;
550 	}
551 }
552 
553 int
554 proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
555     u_int16_t type, int fd, void *data, u_int16_t datalen)
556 {
557 	int	 m;
558 
559 	proc_range(ps, id, &n, &m);
560 	for (; n < m; n++)
561 		if (imsg_compose_event(&ps->ps_ievs[id][n],
562 		    type, -1, 0, fd, data, datalen) == -1)
563 			return (-1);
564 
565 	return (0);
566 }
567 
568 int
569 proc_composev_imsg(struct privsep *ps, enum privsep_procid id, int n,
570     u_int16_t type, int fd, const struct iovec *iov, int iovcnt)
571 {
572 	int	 m;
573 
574 	proc_range(ps, id, &n, &m);
575 	for (; n < m; n++)
576 		if (imsg_composev_event(&ps->ps_ievs[id][n],
577 		    type, -1, 0, fd, iov, iovcnt) == -1)
578 			return (-1);
579 
580 	return (0);
581 }
582 
583 int
584 proc_forward_imsg(struct privsep *ps, struct imsg *imsg,
585     enum privsep_procid id, int n)
586 {
587 	return (proc_compose_imsg(ps, id, n, imsg->hdr.type,
588 	    imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg)));
589 }
590 
591 void
592 proc_flush_imsg(struct privsep *ps, enum privsep_procid id, int n)
593 {
594 	int	 m;
595 
596 	proc_range(ps, id, &n, &m);
597 	for (; n < m; n++)
598 		imsg_flush(&ps->ps_ievs[id][n].ibuf);
599 }
600 
601 struct imsgbuf *
602 proc_ibuf(struct privsep *ps, enum privsep_procid id, int n)
603 {
604 	int	 m;
605 
606 	proc_range(ps, id, &n, &m);
607 	return (&ps->ps_ievs[id][n].ibuf);
608 }
609