GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/iked/proc.c Lines: 0 258 0.0 %
Date: 2017-11-13 Branches: 0 180 0.0 %

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