xref: /openbsd-src/sbin/iked/proc.c (revision de8cc8edbc71bd3e3bc7fbffa27ba0e564c37d8b)
1 /*	$OpenBSD: proc.c,v 1.34 2021/01/28 01:20:37 mortimer Exp $	*/
2 
3 /*
4  * Copyright (c) 2010 - 2014 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 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <signal.h>
31 #include <pwd.h>
32 #include <event.h>
33 #include <imsg.h>
34 
35 #include "iked.h"
36 
37 enum privsep_procid privsep_process;
38 
39 void	 proc_open(struct privsep *, struct privsep_proc *,
40 	    struct privsep_proc *, size_t);
41 void	 proc_close(struct privsep *);
42 int	 proc_ispeer(struct privsep_proc *, unsigned int, enum privsep_procid);
43 void	 proc_shutdown(struct privsep_proc *);
44 void	 proc_sig_handler(int, short, void *);
45 void	 proc_range(struct privsep *, enum privsep_procid, int *, int *);
46 int	 proc_dispatch_null(int, struct privsep_proc *, struct imsg *);
47 
48 int
49 proc_ispeer(struct privsep_proc *procs, unsigned int nproc,
50     enum privsep_procid type)
51 {
52 	unsigned int	i;
53 
54 	for (i = 0; i < nproc; i++)
55 		if (procs[i].p_id == type)
56 			return (1);
57 	return (0);
58 }
59 
60 void
61 proc_init(struct privsep *ps, struct privsep_proc *procs, unsigned int nproc)
62 {
63 	unsigned int		 i, j, src, dst;
64 	struct privsep_pipes	*pp;
65 
66 	/*
67 	 * Allocate pipes for all process instances (incl. parent)
68 	 *
69 	 * - ps->ps_pipes: N:M mapping
70 	 * N source processes connected to M destination processes:
71 	 * [src][instances][dst][instances], for example
72 	 * [PROC_RELAY][3][PROC_CA][3]
73 	 *
74 	 * - ps->ps_pp: per-process 1:M part of ps->ps_pipes
75 	 * Each process instance has a destination array of socketpair fds:
76 	 * [dst][instances], for example
77 	 * [PROC_PARENT][0]
78 	 */
79 	for (src = 0; src < PROC_MAX; src++) {
80 		/* Allocate destination array for each process */
81 		if ((ps->ps_pipes[src] = calloc(ps->ps_ninstances,
82 		    sizeof(struct privsep_pipes))) == NULL)
83 			fatal("proc_init: calloc");
84 
85 		for (i = 0; i < ps->ps_ninstances; i++) {
86 			pp = &ps->ps_pipes[src][i];
87 
88 			for (dst = 0; dst < PROC_MAX; dst++) {
89 				/* Allocate maximum fd integers */
90 				if ((pp->pp_pipes[dst] =
91 				    calloc(ps->ps_ninstances,
92 				    sizeof(int))) == NULL)
93 					fatal("proc_init: calloc");
94 
95 				/* Mark fd as unused */
96 				for (j = 0; j < ps->ps_ninstances; j++)
97 					pp->pp_pipes[dst][j] = -1;
98 			}
99 		}
100 	}
101 
102 	/*
103 	 * Setup and run the parent and its children
104 	 */
105 	privsep_process = PROC_PARENT;
106 	ps->ps_instances[PROC_PARENT] = 1;
107 	ps->ps_title[PROC_PARENT] = "parent";
108 	ps->ps_pid[PROC_PARENT] = getpid();
109 	ps->ps_pp = &ps->ps_pipes[privsep_process][0];
110 
111 	for (i = 0; i < nproc; i++) {
112 		/* Default to 1 process instance */
113 		if (ps->ps_instances[procs[i].p_id] < 1)
114 			ps->ps_instances[procs[i].p_id] = 1;
115 		ps->ps_title[procs[i].p_id] = procs[i].p_title;
116 	}
117 
118 	proc_open(ps, NULL, procs, nproc);
119 
120 	/* Engage! */
121 	for (i = 0; i < nproc; i++)
122 		ps->ps_pid[procs[i].p_id] = (*procs[i].p_init)(ps, &procs[i]);
123 }
124 
125 void
126 proc_kill(struct privsep *ps)
127 {
128 	pid_t		 pid;
129 	unsigned int	 i;
130 
131 	if (privsep_process != PROC_PARENT)
132 		return;
133 
134 	for (i = 0; i < PROC_MAX; i++) {
135 		if (ps->ps_pid[i] == 0)
136 			continue;
137 		killpg(ps->ps_pid[i], SIGTERM);
138 	}
139 
140 	do {
141 		pid = waitpid(WAIT_ANY, NULL, 0);
142 	} while (pid != -1 || (pid == -1 && errno == EINTR));
143 
144 	proc_close(ps);
145 }
146 
147 void
148 proc_open(struct privsep *ps, struct privsep_proc *p,
149     struct privsep_proc *procs, size_t nproc)
150 {
151 	struct privsep_pipes	*pa, *pb;
152 	int			 fds[2];
153 	unsigned int		 i, j, src, proc;
154 
155 	if (p == NULL)
156 		src = privsep_process; /* parent */
157 	else
158 		src = p->p_id;
159 
160 	/*
161 	 * Open socket pairs for our peers
162 	 */
163 	for (proc = 0; proc < nproc; proc++) {
164 		procs[proc].p_ps = ps;
165 		procs[proc].p_env = ps->ps_env;
166 		if (procs[proc].p_cb == NULL)
167 			procs[proc].p_cb = proc_dispatch_null;
168 
169 		for (i = 0; i < ps->ps_instances[src]; i++) {
170 			for (j = 0; j < ps->ps_instances[procs[proc].p_id];
171 			    j++) {
172 				pa = &ps->ps_pipes[src][i];
173 				pb = &ps->ps_pipes[procs[proc].p_id][j];
174 
175 				/* Check if fds are already set by peer */
176 				if (pa->pp_pipes[procs[proc].p_id][j] != -1)
177 					continue;
178 
179 				if (socketpair(AF_UNIX,
180 				    SOCK_STREAM | SOCK_NONBLOCK,
181 				    PF_UNSPEC, fds) == -1)
182 					fatal("socketpair");
183 
184 				pa->pp_pipes[procs[proc].p_id][j] = fds[0];
185 				pb->pp_pipes[src][i] = fds[1];
186 			}
187 		}
188 	}
189 }
190 
191 void
192 proc_listen(struct privsep *ps, struct privsep_proc *procs, size_t nproc)
193 {
194 	unsigned int		 i, dst, src, n, m;
195 	struct privsep_pipes	*pp;
196 
197 	/*
198 	 * Close unused pipes
199 	 */
200 	for (src = 0; src < PROC_MAX; src++) {
201 		for (n = 0; n < ps->ps_instances[src]; n++) {
202 			/* Ingore current process */
203 			if (src == (unsigned int)privsep_process &&
204 			    n == ps->ps_instance)
205 				continue;
206 
207 			pp = &ps->ps_pipes[src][n];
208 
209 			for (dst = 0; dst < PROC_MAX; dst++) {
210 				if (src == dst)
211 					continue;
212 				for (m = 0; m < ps->ps_instances[dst]; m++) {
213 					if (pp->pp_pipes[dst][m] == -1)
214 						continue;
215 
216 					/* Close and invalidate fd */
217 					close(pp->pp_pipes[dst][m]);
218 					pp->pp_pipes[dst][m] = -1;
219 				}
220 			}
221 		}
222 	}
223 
224 	src = privsep_process;
225 	ps->ps_pp = pp = &ps->ps_pipes[src][ps->ps_instance];
226 
227 	/*
228 	 * Listen on appropriate pipes
229 	 */
230 	for (i = 0; i < nproc; i++) {
231 		dst = procs[i].p_id;
232 
233 		if (src == dst)
234 			fatal("proc_listen: cannot peer with oneself");
235 
236 		if ((ps->ps_ievs[dst] = calloc(ps->ps_instances[dst],
237 		    sizeof(struct imsgev))) == NULL)
238 			fatal("proc_open");
239 
240 		for (n = 0; n < ps->ps_instances[dst]; n++) {
241 			if (pp->pp_pipes[dst][n] == -1)
242 				continue;
243 
244 			imsg_init(&(ps->ps_ievs[dst][n].ibuf),
245 			    pp->pp_pipes[dst][n]);
246 			ps->ps_ievs[dst][n].handler = proc_dispatch;
247 			ps->ps_ievs[dst][n].events = EV_READ;
248 			ps->ps_ievs[dst][n].proc = &procs[i];
249 			ps->ps_ievs[dst][n].data = &ps->ps_ievs[dst][n];
250 			procs[i].p_instance = n;
251 
252 			event_set(&(ps->ps_ievs[dst][n].ev),
253 			    ps->ps_ievs[dst][n].ibuf.fd,
254 			    ps->ps_ievs[dst][n].events,
255 			    ps->ps_ievs[dst][n].handler,
256 			    ps->ps_ievs[dst][n].data);
257 			event_add(&(ps->ps_ievs[dst][n].ev), NULL);
258 		}
259 	}
260 }
261 
262 void
263 proc_close(struct privsep *ps)
264 {
265 	unsigned int		 src, dst, n, i, j;
266 	struct privsep_pipes	*pp;
267 
268 	if (ps == NULL)
269 		return;
270 
271 	pp = ps->ps_pp;
272 
273 	for (dst = 0; dst < PROC_MAX; dst++) {
274 		if (ps->ps_ievs[dst] == NULL)
275 			continue;
276 
277 		for (n = 0; n < ps->ps_instances[dst]; n++) {
278 			if (pp->pp_pipes[dst][n] == -1)
279 				continue;
280 
281 			/* Cancel the fd, close and invalidate the fd */
282 			event_del(&(ps->ps_ievs[dst][n].ev));
283 			imsg_clear(&(ps->ps_ievs[dst][n].ibuf));
284 			close(pp->pp_pipes[dst][n]);
285 			pp->pp_pipes[dst][n] = -1;
286 		}
287 		free(ps->ps_ievs[dst]);
288 	}
289 
290 	/* undo proc_init() */
291 	for (src = 0; src < PROC_MAX; src++) {
292 		for (i = 0; i < ps->ps_ninstances; i++) {
293 			pp = &ps->ps_pipes[src][i];
294 			for (dst = 0; dst < PROC_MAX; dst++) {
295 				for (j = 0; j < ps->ps_ninstances; j++)
296 					if (pp->pp_pipes[dst][j] != -1)
297 						close(pp->pp_pipes[dst][j]);
298 				free(pp->pp_pipes[dst]);
299 			}
300 		}
301 		free(ps->ps_pipes[src]);
302 	}
303 }
304 
305 void
306 proc_shutdown(struct privsep_proc *p)
307 {
308 	struct privsep	*ps = p->p_ps;
309 
310 	if (p->p_shutdown != NULL)
311 		(*p->p_shutdown)(p);
312 
313 	proc_close(ps);
314 
315 	log_info("%s exiting, pid %d", p->p_title, getpid());
316 
317 	_exit(0);
318 }
319 
320 void
321 proc_sig_handler(int sig, short event, void *arg)
322 {
323 	struct privsep_proc	*p = arg;
324 
325 	switch (sig) {
326 	case SIGINT:
327 	case SIGTERM:
328 		proc_shutdown(p);
329 		break;
330 	case SIGCHLD:
331 	case SIGHUP:
332 	case SIGPIPE:
333 	case SIGUSR1:
334 		/* ignore */
335 		break;
336 	default:
337 		fatalx("proc_sig_handler: unexpected signal");
338 		/* NOTREACHED */
339 	}
340 }
341 
342 pid_t
343 proc_run(struct privsep *ps, struct privsep_proc *p,
344     struct privsep_proc *procs, unsigned int nproc,
345     void (*run)(struct privsep *, struct privsep_proc *, void *), void *arg)
346 {
347 	pid_t			 pid;
348 	struct passwd		*pw;
349 	const char		*root;
350 	struct control_sock	*rcs;
351 	unsigned int		 n;
352 
353 	if (ps->ps_noaction)
354 		return (0);
355 
356 	proc_open(ps, p, procs, nproc);
357 
358 	/* Fork child handlers */
359 	switch (pid = fork()) {
360 	case -1:
361 		fatal("proc_run: cannot fork");
362 	case 0:
363 		log_procinit(p->p_title);
364 
365 		/* Set the process group of the current process */
366 		setpgid(0, 0);
367 		break;
368 	default:
369 		return (pid);
370 	}
371 
372 	pw = ps->ps_pw;
373 
374 	if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
375 		if (control_init(ps, &ps->ps_csock) == -1)
376 			fatalx(__func__);
377 		TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
378 			if (control_init(ps, rcs) == -1)
379 				fatalx(__func__);
380 	}
381 
382 	/* Change root directory */
383 	if (p->p_chroot != NULL)
384 		root = p->p_chroot;
385 	else
386 		root = pw->pw_dir;
387 
388 	if (chroot(root) == -1)
389 		fatal("proc_run: chroot");
390 	if (chdir("/") == -1)
391 		fatal("proc_run: chdir(\"/\")");
392 
393 	privsep_process = p->p_id;
394 
395 	setproctitle("%s", p->p_title);
396 
397 	if (setgroups(1, &pw->pw_gid) ||
398 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
399 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
400 		fatal("proc_run: cannot drop privileges");
401 
402 	/* Fork child handlers */
403 	for (n = 1; n < ps->ps_instances[p->p_id]; n++) {
404 		if (fork() == 0) {
405 			ps->ps_instance = p->p_instance = n;
406 			break;
407 		}
408 	}
409 
410 #ifdef DEBUG
411 	log_debug("%s: %s %d/%d, pid %d", __func__, p->p_title,
412 	    ps->ps_instance + 1, ps->ps_instances[p->p_id], getpid());
413 #endif
414 
415 	event_init();
416 
417 	signal_set(&ps->ps_evsigint, SIGINT, proc_sig_handler, p);
418 	signal_set(&ps->ps_evsigterm, SIGTERM, proc_sig_handler, p);
419 	signal_set(&ps->ps_evsigchld, SIGCHLD, proc_sig_handler, p);
420 	signal_set(&ps->ps_evsighup, SIGHUP, proc_sig_handler, p);
421 	signal_set(&ps->ps_evsigpipe, SIGPIPE, proc_sig_handler, p);
422 	signal_set(&ps->ps_evsigusr1, SIGUSR1, proc_sig_handler, p);
423 
424 	signal_add(&ps->ps_evsigint, NULL);
425 	signal_add(&ps->ps_evsigterm, NULL);
426 	signal_add(&ps->ps_evsigchld, NULL);
427 	signal_add(&ps->ps_evsighup, NULL);
428 	signal_add(&ps->ps_evsigpipe, NULL);
429 	signal_add(&ps->ps_evsigusr1, NULL);
430 
431 	proc_listen(ps, procs, nproc);
432 
433 	if (p->p_id == PROC_CONTROL && ps->ps_instance == 0) {
434 		TAILQ_INIT(&ctl_conns);
435 		if (control_listen(&ps->ps_csock) == -1)
436 			fatalx(__func__);
437 		TAILQ_FOREACH(rcs, &ps->ps_rcsocks, cs_entry)
438 			if (control_listen(rcs) == -1)
439 				fatalx(__func__);
440 	}
441 
442 	if (run != NULL)
443 		run(ps, p, arg);
444 
445 	event_dispatch();
446 
447 	proc_shutdown(p);
448 
449 	return (0);
450 }
451 
452 void
453 proc_dispatch(int fd, short event, void *arg)
454 {
455 	struct imsgev		*iev = arg;
456 	struct privsep_proc	*p = iev->proc;
457 	struct privsep		*ps = p->p_ps;
458 	struct imsgbuf		*ibuf;
459 	struct imsg		 imsg;
460 	ssize_t			 n;
461 	int			 verbose;
462 	const char		*title;
463 
464 	title = ps->ps_title[privsep_process];
465 	ibuf = &iev->ibuf;
466 
467 	if (event & EV_READ) {
468 		if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
469 			fatal(__func__);
470 		if (n == 0) {
471 			/* this pipe is dead, so remove the event handler */
472 			event_del(&iev->ev);
473 			event_loopexit(NULL);
474 			return;
475 		}
476 	}
477 
478 	if (event & EV_WRITE) {
479 		if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN)
480 			fatal(__func__);
481 	}
482 
483 	for (;;) {
484 		if ((n = imsg_get(ibuf, &imsg)) == -1)
485 			fatal(__func__);
486 		if (n == 0)
487 			break;
488 
489 #if DEBUG > 1
490 		log_debug("%s: %s %d got imsg %d peerid %d from %s %d",
491 		    __func__, title, ps->ps_instance + 1,
492 		    imsg.hdr.type, imsg.hdr.peerid, p->p_title, p->p_instance);
493 #endif
494 
495 		/*
496 		 * Check the message with the program callback
497 		 */
498 		if ((p->p_cb)(fd, p, &imsg) == 0) {
499 			/* Message was handled by the callback, continue */
500 			imsg_free(&imsg);
501 			continue;
502 		}
503 
504 		/*
505 		 * Generic message handling
506 		 */
507 		switch (imsg.hdr.type) {
508 		case IMSG_CTL_VERBOSE:
509 			IMSG_SIZE_CHECK(&imsg, &verbose);
510 			memcpy(&verbose, imsg.data, sizeof(verbose));
511 			log_setverbose(verbose);
512 			break;
513 		default:
514 			log_warnx("%s: %s %d got invalid imsg %d peerid %d "
515 			    "from %s %d",
516 			    __func__, title, ps->ps_instance + 1,
517 			    imsg.hdr.type, imsg.hdr.peerid,
518 			    p->p_title, p->p_instance);
519 			fatalx(__func__);
520 		}
521 		imsg_free(&imsg);
522 	}
523 	imsg_event_add(iev);
524 }
525 
526 int
527 proc_dispatch_null(int fd, struct privsep_proc *p, struct imsg *imsg)
528 {
529 	return (-1);
530 }
531 
532 /*
533  * imsg helper functions
534  */
535 
536 void
537 imsg_event_add(struct imsgev *iev)
538 {
539 	if (iev->handler == NULL) {
540 		imsg_flush(&iev->ibuf);
541 		return;
542 	}
543 
544 	iev->events = EV_READ;
545 	if (iev->ibuf.w.queued)
546 		iev->events |= EV_WRITE;
547 
548 	event_del(&iev->ev);
549 	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data);
550 	event_add(&iev->ev, NULL);
551 }
552 
553 int
554 imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
555     pid_t pid, int fd, void *data, uint16_t datalen)
556 {
557 	int	ret;
558 
559 	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
560 	    pid, fd, data, datalen)) == -1)
561 		return (ret);
562 	imsg_event_add(iev);
563 	return (ret);
564 }
565 
566 int
567 imsg_composev_event(struct imsgev *iev, uint16_t type, uint32_t peerid,
568     pid_t pid, int fd, const struct iovec *iov, int iovcnt)
569 {
570 	int	ret;
571 
572 	if ((ret = imsg_composev(&iev->ibuf, type, peerid,
573 	    pid, fd, iov, iovcnt)) == -1)
574 		return (ret);
575 	imsg_event_add(iev);
576 	return (ret);
577 }
578 
579 void
580 proc_range(struct privsep *ps, enum privsep_procid id, int *n, int *m)
581 {
582 	if (*n == -1) {
583 		/* Use a range of all target instances */
584 		*n = 0;
585 		*m = ps->ps_instances[id];
586 	} else {
587 		/* Use only a single slot of the specified peer process */
588 		*m = *n + 1;
589 	}
590 }
591 
592 int
593 proc_compose_imsg(struct privsep *ps, enum privsep_procid id, int n,
594     uint16_t type, uint32_t peerid, int fd, void *data, uint16_t datalen)
595 {
596 	int	 m;
597 
598 	proc_range(ps, id, &n, &m);
599 	for (; n < m; n++) {
600 		if (imsg_compose_event(&ps->ps_ievs[id][n],
601 		    type, peerid, 0, fd, data, datalen) == -1)
602 			return (-1);
603 	}
604 
605 	return (0);
606 }
607 
608 int
609 proc_compose(struct privsep *ps, enum privsep_procid id,
610     uint16_t type, void *data, uint16_t datalen)
611 {
612 	return (proc_compose_imsg(ps, id, -1, type, -1, -1, data, datalen));
613 }
614 
615 int
616 proc_composev_imsg(struct privsep *ps, enum privsep_procid id, int n,
617     uint16_t type, uint32_t peerid, int fd, const struct iovec *iov, int iovcnt)
618 {
619 	int	 m;
620 
621 	proc_range(ps, id, &n, &m);
622 	for (; n < m; n++)
623 		if (imsg_composev_event(&ps->ps_ievs[id][n],
624 		    type, peerid, 0, fd, iov, iovcnt) == -1)
625 			return (-1);
626 
627 	return (0);
628 }
629 
630 int
631 proc_composev(struct privsep *ps, enum privsep_procid id,
632     uint16_t type, const struct iovec *iov, int iovcnt)
633 {
634 	return (proc_composev_imsg(ps, id, -1, type, -1, -1, iov, iovcnt));
635 }
636 
637 int
638 proc_forward_imsg(struct privsep *ps, struct imsg *imsg,
639     enum privsep_procid id, int n)
640 {
641 	return (proc_compose_imsg(ps, id, n, imsg->hdr.type,
642 	    imsg->hdr.peerid, imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg)));
643 }
644 
645 struct imsgbuf *
646 proc_ibuf(struct privsep *ps, enum privsep_procid id, int n)
647 {
648 	int	 m;
649 
650 	proc_range(ps, id, &n, &m);
651 	return (&ps->ps_ievs[id][n].ibuf);
652 }
653 
654 struct imsgev *
655 proc_iev(struct privsep *ps, enum privsep_procid id, int n)
656 {
657 	int	 m;
658 
659 	proc_range(ps, id, &n, &m);
660 	return (&ps->ps_ievs[id][n]);
661 }
662