Bug Summary

File:src/sbin/isakmpd/monitor.c
Warning:line 524, column 7
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name monitor.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sbin/isakmpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sbin/isakmpd -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/sbin/isakmpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/sbin/isakmpd/monitor.c
1/* $OpenBSD: monitor.c,v 1.82 2021/10/24 21:24:21 deraadt Exp $ */
2
3/*
4 * Copyright (c) 2003 Håkan Olsson. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/types.h>
28#include <sys/socket.h>
29#include <sys/ioctl.h>
30#include <sys/stat.h>
31#include <sys/wait.h>
32#include <netinet/in.h>
33
34#include <dirent.h>
35#include <errno(*__errno()).h>
36#include <fcntl.h>
37#include <pwd.h>
38#include <signal.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42#include <limits.h>
43
44#include <regex.h>
45#include <keynote.h>
46
47#include "conf.h"
48#include "log.h"
49#include "monitor.h"
50#include "policy.h"
51#include "ui.h"
52#include "util.h"
53#include "pf_key_v2.h"
54
55struct monitor_state {
56 pid_t pid;
57 int s;
58 char root[PATH_MAX1024];
59} m_state;
60
61extern char *pid_file;
62
63extern void set_slave_signals(void);
64
65/* Private functions. */
66static void must_read(void *, size_t);
67static void must_write(const void *, size_t);
68
69static void m_priv_getfd(void);
70static void m_priv_setsockopt(void);
71static void m_priv_req_readdir(void);
72static void m_priv_bind(void);
73static void m_priv_pfkey_open(void);
74static int m_priv_local_sanitize_path(const char *, size_t, int);
75static int m_priv_check_sockopt(int, int);
76static int m_priv_check_bind(const struct sockaddr *, socklen_t);
77
78static void set_monitor_signals(void);
79static void sig_pass_to_chld(int);
80
81/*
82 * Public functions, unprivileged.
83 */
84
85/* Setup monitor context, fork, drop child privs. */
86pid_t
87monitor_init(int debug)
88{
89 struct passwd *pw;
90 int p[2];
91
92 bzero(&m_state, sizeof m_state);
93
94 if (socketpair(AF_UNIX1, SOCK_STREAM1, PF_UNSPEC0, p) != 0)
95 log_fatal("monitor_init: socketpair() failed");
96
97 pw = getpwnam(ISAKMPD_PRIVSEP_USER"_isakmpd");
98 if (pw == NULL((void *)0))
99 log_fatalx("monitor_init: getpwnam(\"%s\") failed",
100 ISAKMPD_PRIVSEP_USER"_isakmpd");
101 strlcpy(m_state.root, pw->pw_dir, sizeof m_state.root);
102
103 set_monitor_signals();
104 m_state.pid = fork();
105
106 if (m_state.pid == -1)
107 log_fatal("monitor_init: fork of unprivileged child failed");
108 if (m_state.pid == 0) {
109 /* The child process drops privileges. */
110 set_slave_signals();
111
112 if (chroot(pw->pw_dir) != 0 || chdir("/") != 0)
113 log_fatal("monitor_init: chroot failed");
114
115 if (setgroups(1, &pw->pw_gid) == -1 ||
116 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
117 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
118 log_fatal("monitor_init: can't drop privileges");
119
120 m_state.s = p[0];
121 close(p[1]);
122
123 LOG_DBG((LOG_MISC, 10,log_debug (LOG_MISC, 10, "monitor_init: privileges dropped for child process"
)
124 "monitor_init: privileges dropped for child process"))log_debug (LOG_MISC, 10, "monitor_init: privileges dropped for child process"
)
;
125 } else {
126 /* Privileged monitor. */
127 setproctitle("monitor [priv]");
128
129 m_state.s = p[1];
130 close(p[0]);
131 }
132
133 /* With "-dd", stop and wait here. For gdb "attach" etc. */
134 if (debug > 1) {
135 log_print("monitor_init: stopped %s PID %d fd %d%s",
136 m_state.pid ? "priv" : "child", getpid(), m_state.s,
137 m_state.pid ? ", waiting for SIGCONT" : "");
138 kill(getpid(), SIGSTOP17); /* Wait here for SIGCONT. */
139 if (m_state.pid)
140 kill(m_state.pid, SIGCONT19); /* Continue child. */
141 }
142
143 return m_state.pid;
144}
145
146void
147monitor_exit(int code)
148{
149 int status = 0, gotstatus = 0;
150 pid_t pid;
151
152 if (m_state.pid != 0) {
153 /* When called from the monitor, kill slave and wait for it */
154 kill(m_state.pid, SIGTERM15);
155
156 do {
157 pid = waitpid(m_state.pid, &status, 0);
158 } while (pid == -1 && errno(*__errno()) == EINTR4);
159 if (pid != -1)
160 gotstatus = 1;
161
162 /* Remove FIFO and pid files. */
163 unlink(ui_fifo);
164 unlink(pid_file);
165 }
166
167 close(m_state.s);
168 if (code == 0 && gotstatus)
169 exit(WIFEXITED(status)(((status) & 0177) == 0)? WEXITSTATUS(status)(int)(((unsigned)(status) >> 8) & 0xff) : 1);
170 else
171 exit(code);
172}
173
174int
175monitor_pf_key_v2_open(void)
176{
177 int err, cmd;
178
179 cmd = MONITOR_PFKEY_OPEN;
180 must_write(&cmd, sizeof cmd);
181
182 must_read(&err, sizeof err);
183 if (err < 0) {
184 log_error("monitor_pf_key_v2_open: parent could not create "
185 "PF_KEY socket");
186 return -1;
187 }
188 pf_key_v2_socket = mm_receive_fd(m_state.s);
189 if (pf_key_v2_socket < 0) {
190 log_error("monitor_pf_key_v2_open: mm_receive_fd() failed");
191 return -1;
192 }
193
194 return pf_key_v2_socket;
195}
196
197int
198monitor_open(const char *path, int flags, mode_t mode)
199{
200 size_t len;
201 int fd, err, cmd;
202 char pathreal[PATH_MAX1024];
203
204 if (path[0] == '/')
205 strlcpy(pathreal, path, sizeof pathreal);
206 else
207 snprintf(pathreal, sizeof pathreal, "%s/%s", m_state.root,
208 path);
209
210 cmd = MONITOR_GET_FD;
211 must_write(&cmd, sizeof cmd);
212
213 len = strlen(pathreal);
214 must_write(&len, sizeof len);
215 must_write(&pathreal, len);
216
217 must_write(&flags, sizeof flags);
218 must_write(&mode, sizeof mode);
219
220 must_read(&err, sizeof err);
221 if (err != 0) {
222 errno(*__errno()) = err;
223 return -1;
224 }
225
226 fd = mm_receive_fd(m_state.s);
227 if (fd < 0) {
228 log_error("monitor_open: mm_receive_fd () failed");
229 return -1;
230 }
231
232 return fd;
233}
234
235FILE *
236monitor_fopen(const char *path, const char *mode)
237{
238 FILE *fp;
239 int fd, flags = 0, saved_errno;
240 mode_t mask, cur_umask;
241
242 /* Only the child process is supposed to run this. */
243 if (m_state.pid)
244 log_fatal("[priv] bad call to monitor_fopen");
245
246 switch (mode[0]) {
247 case 'r':
248 flags = (mode[1] == '+' ? O_RDWR0x0002 : O_RDONLY0x0000);
249 break;
250 case 'w':
251 flags = (mode[1] == '+' ? O_RDWR0x0002 : O_WRONLY0x0001) | O_CREAT0x0200 |
252 O_TRUNC0x0400;
253 break;
254 case 'a':
255 flags = (mode[1] == '+' ? O_RDWR0x0002 : O_WRONLY0x0001) | O_CREAT0x0200 |
256 O_APPEND0x0008;
257 break;
258 default:
259 log_fatal("monitor_fopen: bad call");
260 }
261
262 cur_umask = umask(0);
263 (void)umask(cur_umask);
264 mask = S_IRUSR0000400 | S_IWUSR0000200 | S_IRGRP0000040 | S_IWGRP0000020 | S_IROTH0000004 | S_IWOTH0000002;
265 mask &= ~cur_umask;
266
267 fd = monitor_open(path, flags, mask);
268 if (fd < 0)
269 return NULL((void *)0);
270
271 /* Got the fd, attach a FILE * to it. */
272 fp = fdopen(fd, mode);
273 if (!fp) {
274 log_error("monitor_fopen: fdopen() failed");
275 saved_errno = errno(*__errno());
276 close(fd);
277 errno(*__errno()) = saved_errno;
278 return NULL((void *)0);
279 }
280 return fp;
281}
282
283int
284monitor_stat(const char *path, struct stat *sb)
285{
286 int fd, r, saved_errno;
287
288 /* O_NONBLOCK is needed for stat'ing fifos. */
289 fd = monitor_open(path, O_RDONLY0x0000 | O_NONBLOCK0x0004, 0);
290 if (fd < 0)
291 return -1;
292
293 r = fstat(fd, sb);
294 saved_errno = errno(*__errno());
295 close(fd);
296 errno(*__errno()) = saved_errno;
297 return r;
298}
299
300int
301monitor_setsockopt(int s, int level, int optname, const void *optval,
302 socklen_t optlen)
303{
304 int ret, err, cmd;
305
306 cmd = MONITOR_SETSOCKOPT;
307 must_write(&cmd, sizeof cmd);
308 if (mm_send_fd(m_state.s, s)) {
309 log_print("monitor_setsockopt: read/write error");
310 return -1;
311 }
312
313 must_write(&level, sizeof level);
314 must_write(&optname, sizeof optname);
315 must_write(&optlen, sizeof optlen);
316 must_write(optval, optlen);
317
318 must_read(&err, sizeof err);
319 must_read(&ret, sizeof ret);
320 if (err != 0)
321 errno(*__errno()) = err;
322 return ret;
323}
324
325int
326monitor_bind(int s, const struct sockaddr *name, socklen_t namelen)
327{
328 int ret, err, cmd;
329
330 cmd = MONITOR_BIND;
331 must_write(&cmd, sizeof cmd);
332 if (mm_send_fd(m_state.s, s)) {
333 log_print("monitor_bind: read/write error");
334 return -1;
335 }
336
337 must_write(&namelen, sizeof namelen);
338 must_write(name, namelen);
339
340 must_read(&err, sizeof err);
341 must_read(&ret, sizeof ret);
342 if (err != 0)
343 errno(*__errno()) = err;
344 return ret;
345}
346
347int
348monitor_req_readdir(const char *filename)
349{
350 int cmd, err;
351 size_t len;
352
353 cmd = MONITOR_REQ_READDIR;
354 must_write(&cmd, sizeof cmd);
355
356 len = strlen(filename);
357 must_write(&len, sizeof len);
358 must_write(filename, len);
359
360 must_read(&err, sizeof err);
361 if (err == -1)
362 must_read(&errno(*__errno()), sizeof errno(*__errno()));
363
364 return err;
365}
366
367int
368monitor_readdir(char *file, size_t size)
369{
370 int fd;
371 size_t len;
372
373 must_read(&len, sizeof len);
374 if (len == 0)
375 return -1;
376 if (len >= size)
377 log_fatal("monitor_readdir: received bad length from monitor");
378 must_read(file, len);
379 file[len] = '\0';
380 fd = mm_receive_fd(m_state.s);
381 return fd;
382}
383
384void
385monitor_init_done(void)
386{
387 int cmd;
388
389 cmd = MONITOR_INIT_DONE;
390 must_write(&cmd, sizeof cmd);
391}
392
393/*
394 * Start of code running with privileges (the monitor process).
395 */
396
397static void
398set_monitor_signals(void)
399{
400 int n;
401
402 for (n = 1; n < _NSIG33; n++)
403 signal(n, SIG_DFL(void (*)(int))0);
404
405 /* Forward some signals to the child. */
406 signal(SIGTERM15, sig_pass_to_chld);
407 signal(SIGHUP1, sig_pass_to_chld);
408 signal(SIGUSR130, sig_pass_to_chld);
409}
410
411static void
412sig_pass_to_chld(int sig)
413{
414 int oerrno = errno(*__errno());
415
416 if (m_state.pid > 0)
417 kill(m_state.pid, sig);
418 errno(*__errno()) = oerrno;
419}
420
421/* This function is where the privileged process waits(loops) indefinitely. */
422void
423monitor_loop(int debug)
424{
425 int msgcode;
426
427 if (!debug)
428 log_to(0);
429
430 for (;;) {
431 must_read(&msgcode, sizeof msgcode);
432
433 switch (msgcode) {
434 case MONITOR_GET_FD:
435 m_priv_getfd();
436 break;
437
438 case MONITOR_PFKEY_OPEN:
439 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_PFKEY_OPEN")
440 "monitor_loop: MONITOR_PFKEY_OPEN"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_PFKEY_OPEN");
441 m_priv_pfkey_open();
442 break;
443
444 case MONITOR_SETSOCKOPT:
445 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_SETSOCKOPT")
446 "monitor_loop: MONITOR_SETSOCKOPT"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_SETSOCKOPT");
447 m_priv_setsockopt();
448 break;
449
450 case MONITOR_BIND:
451 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_BIND")
452 "monitor_loop: MONITOR_BIND"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_BIND");
453 m_priv_bind();
454 break;
455
456 case MONITOR_REQ_READDIR:
457 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_REQ_READDIR")
458 "monitor_loop: MONITOR_REQ_READDIR"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_REQ_READDIR");
459 m_priv_req_readdir();
460 break;
461
462 case MONITOR_INIT_DONE:
463 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_INIT_DONE")
464 "monitor_loop: MONITOR_INIT_DONE"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_INIT_DONE");
465 break;
466
467 case MONITOR_SHUTDOWN:
468 LOG_DBG((LOG_MISC, 80,log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_SHUTDOWN")
469 "monitor_loop: MONITOR_SHUTDOWN"))log_debug (LOG_MISC, 80, "monitor_loop: MONITOR_SHUTDOWN");
470 break;
471
472 default:
473 log_print("monitor_loop: got unknown code %d",
474 msgcode);
475 }
476 }
477
478 exit(0);
479}
480
481
482/* Privileged: called by monitor_loop. */
483static void
484m_priv_pfkey_open(void)
485{
486 int fd, err = 0;
487
488 fd = pf_key_v2_open();
489 if (fd < 0)
490 err = -1;
491
492 must_write(&err, sizeof err);
493
494 if (fd > 0 && mm_send_fd(m_state.s, fd)) {
495 log_error("m_priv_pfkey_open: read/write operation failed");
496 close(fd);
497 return;
498 }
499 close(fd);
500}
501
502/* Privileged: called by monitor_loop. */
503static void
504m_priv_getfd(void)
505{
506 char path[PATH_MAX1024];
507 size_t len;
508 int v, flags, ret;
509 int err = 0;
510 mode_t mode;
511
512 must_read(&len, sizeof len);
513 if (len == 0 || len >= sizeof path)
514 log_fatal("m_priv_getfd: invalid pathname length");
515
516 must_read(path, len);
517 path[len] = '\0';
518 if (strlen(path) != len)
519 log_fatal("m_priv_getfd: invalid pathname");
520
521 must_read(&flags, sizeof flags);
522 must_read(&mode, sizeof mode);
523
524 if ((ret = m_priv_local_sanitize_path(path, sizeof path, flags))
Although the value stored to 'ret' is used in the enclosing expression, the value is never actually read from 'ret'
525 != 0) {
526 if (errno(*__errno()) != ENOENT2)
527 log_print("m_priv_getfd: illegal path \"%s\"", path);
528 err = errno(*__errno());
529 v = -1;
530 } else {
531 if ((v = open(path, flags, mode)) == -1)
532 err = errno(*__errno());
533 }
534
535 must_write(&err, sizeof err);
536
537 if (v != -1) {
538 if (mm_send_fd(m_state.s, v) == -1)
539 log_error("m_priv_getfd: sending fd failed");
540 close(v);
541 }
542}
543
544/* Privileged: called by monitor_loop. */
545static void
546m_priv_setsockopt(void)
547{
548 int sock, level, optname, v;
549 int err = 0;
550 char *optval = 0;
551 socklen_t optlen;
552
553 sock = mm_receive_fd(m_state.s);
554 if (sock < 0) {
555 log_print("m_priv_setsockopt: read/write error");
556 return;
557 }
558
559 must_read(&level, sizeof level);
560 must_read(&optname, sizeof optname);
561 must_read(&optlen, sizeof optlen);
562
563 optval = malloc(optlen);
564 if (!optval) {
565 log_print("m_priv_setsockopt: malloc failed");
566 close(sock);
567 return;
568 }
569
570 must_read(optval, optlen);
571
572 if (m_priv_check_sockopt(level, optname) != 0) {
573 err = EACCES13;
574 v = -1;
575 } else {
576 v = setsockopt(sock, level, optname, optval, optlen);
577 if (v < 0)
578 err = errno(*__errno());
579 }
580
581 close(sock);
582 sock = -1;
583
584 must_write(&err, sizeof err);
585 must_write(&v, sizeof v);
586
587 free(optval);
588 return;
589}
590
591/* Privileged: called by monitor_loop. */
592static void
593m_priv_bind(void)
594{
595 int sock, v, err = 0;
596 struct sockaddr *name = 0;
597 socklen_t namelen;
598
599 sock = mm_receive_fd(m_state.s);
600 if (sock < 0) {
601 log_print("m_priv_bind: read/write error");
602 return;
603 }
604
605 must_read(&namelen, sizeof namelen);
606 name = malloc(namelen);
607 if (!name) {
608 log_print("m_priv_bind: malloc failed");
609 close(sock);
610 return;
611 }
612 must_read((char *)name, namelen);
613
614 if (m_priv_check_bind(name, namelen) != 0) {
615 err = EACCES13;
616 v = -1;
617 } else {
618 v = bind(sock, name, namelen);
619 if (v == -1) {
620 log_error("m_priv_bind: bind(%d,%p,%d) returned %d",
621 sock, name, namelen, v);
622 err = errno(*__errno());
623 }
624 }
625
626 close(sock);
627 sock = -1;
628
629 must_write(&err, sizeof err);
630 must_write(&v, sizeof v);
631
632 free(name);
633 return;
634}
635
636/*
637 * Help functions, used by both privileged and unprivileged code
638 */
639
640/*
641 * Read data with the assertion that it all must come through, or else abort
642 * the process. Based on atomicio() from openssh.
643 */
644static void
645must_read(void *buf, size_t n)
646{
647 char *s = buf;
648 size_t pos = 0;
649 ssize_t res;
650
651 while (n > pos) {
652 res = read(m_state.s, s + pos, n - pos);
653 switch (res) {
654 case -1:
655 if (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35)
656 continue;
657 case 0:
658 monitor_exit(0);
659 default:
660 pos += res;
661 }
662 }
663}
664
665/*
666 * Write data with the assertion that it all has to be written, or else abort
667 * the process. Based on atomicio() from openssh.
668 */
669static void
670must_write(const void *buf, size_t n)
671{
672 const char *s = buf;
673 size_t pos = 0;
674 ssize_t res;
675
676 while (n > pos) {
677 res = write(m_state.s, s + pos, n - pos);
678 switch (res) {
679 case -1:
680 if (errno(*__errno()) == EINTR4 || errno(*__errno()) == EAGAIN35)
681 continue;
682 case 0:
683 monitor_exit(0);
684 default:
685 pos += res;
686 }
687 }
688}
689
690/* Check that path/mode is permitted. */
691static int
692m_priv_local_sanitize_path(const char *path, size_t pmax, int flags)
693{
694 char new_path[PATH_MAX1024], var_run[PATH_MAX1024], *enddir;
695
696 /*
697 * We only permit paths starting with
698 * /etc/isakmpd/ (read only)
699 * /var/run/ (rw)
700 */
701
702 if (realpath(path, new_path) == NULL((void *)0)) {
703 if (errno(*__errno()) != ENOENT2)
704 return 1;
705 /*
706 * It is ok if the directory exists,
707 * but the file should be created.
708 */
709 if (strlcpy(new_path, path, sizeof(new_path)) >=
710 sizeof(new_path))
711 return 1;
712 enddir = strrchr(new_path, '/');
713 if (enddir == NULL((void *)0) || enddir[1] == '\0')
714 return 1;
715 enddir[1] = '\0';
716 if (realpath(new_path, new_path) == NULL((void *)0)) {
717 errno(*__errno()) = ENOENT2;
718 return 1;
719 }
720 enddir = strrchr(path, '/');
721 strlcat(new_path, enddir, sizeof(new_path));
722 }
723
724 if (realpath("/var/run/", var_run) == NULL((void *)0))
725 return 1;
726 strlcat(var_run, "/", sizeof(var_run));
727
728 if (strncmp(var_run, new_path, strlen(var_run)) == 0)
729 return 0;
730
731 if (strncmp(ISAKMPD_ROOT"/etc/isakmpd/", new_path, strlen(ISAKMPD_ROOT"/etc/isakmpd/")) == 0 &&
732 (flags & O_ACCMODE0x0003) == O_RDONLY0x0000)
733 return 0;
734
735 errno(*__errno()) = EACCES13;
736 return 1;
737}
738
739/* Check setsockopt */
740static int
741m_priv_check_sockopt(int level, int name)
742{
743 switch (level) {
744 /* These are allowed */
745 case SOL_SOCKET0xffff:
746 case IPPROTO_IP0:
747 case IPPROTO_IPV641:
748 break;
749
750 default:
751 log_print("m_priv_check_sockopt: Illegal level %d", level);
752 return 1;
753 }
754
755 switch (name) {
756 /* These are allowed */
757 case SO_REUSEPORT0x0200:
758 case SO_REUSEADDR0x0004:
759 case IP_AUTH_LEVEL20:
760 case IP_ESP_TRANS_LEVEL21:
761 case IP_ESP_NETWORK_LEVEL22:
762 case IP_IPCOMP_LEVEL29:
763 case IPV6_AUTH_LEVEL53:
764 case IPV6_ESP_TRANS_LEVEL54:
765 case IPV6_ESP_NETWORK_LEVEL55:
766 case IPV6_IPCOMP_LEVEL60:
767 break;
768
769 default:
770 log_print("m_priv_check_sockopt: Illegal option name %d",
771 name);
772 return 1;
773 }
774
775 return 0;
776}
777
778/* Check bind */
779static int
780m_priv_check_bind(const struct sockaddr *sa, socklen_t salen)
781{
782 in_port_t port;
783
784 if (sa == NULL((void *)0)) {
785 log_print("NULL address");
786 return 1;
787 }
788 if (SA_LEN(sa)((sa)->sa_len) != salen) {
789 log_print("Length mismatch: %lu %lu", (unsigned long)sa->sa_len,
790 (unsigned long)salen);
791 return 1;
792 }
793 switch (sa->sa_family) {
794 case AF_INET2:
795 if (salen != sizeof(struct sockaddr_in)) {
796 log_print("Invalid inet address length");
797 return 1;
798 }
799 port = ((const struct sockaddr_in *)sa)->sin_port;
800 break;
801 case AF_INET624:
802 if (salen != sizeof(struct sockaddr_in6)) {
803 log_print("Invalid inet6 address length");
804 return 1;
805 }
806 port = ((const struct sockaddr_in6 *)sa)->sin6_port;
807 break;
808 default:
809 log_print("Unknown address family");
810 return 1;
811 }
812
813 port = ntohs(port)(__uint16_t)(__builtin_constant_p(port) ? (__uint16_t)(((__uint16_t
)(port) & 0xffU) << 8 | ((__uint16_t)(port) & 0xff00U
) >> 8) : __swap16md(port))
;
814
815 if (port != ISAKMP_PORT_DEFAULT500 && port < 1024) {
816 log_print("Disallowed port %u", port);
817 return 1;
818 }
819 return 0;
820}
821
822static void
823m_priv_req_readdir()
824{
825 size_t len;
826 char path[PATH_MAX1024];
827 DIR *dp;
828 struct dirent *file;
829 struct stat sb;
830 int off, size, fd, ret, serrno;
831
832 must_read(&len, sizeof len);
833 if (len == 0 || len >= sizeof path)
834 log_fatal("m_priv_req_readdir: invalid pathname length");
835 must_read(path, len);
836 path[len] = '\0';
837 if (strlen(path) != len)
838 log_fatal("m_priv_req_readdir: invalid pathname");
839
840 off = strlen(path);
841 size = sizeof path - off;
842
843 if ((dp = opendir(path)) == NULL((void *)0)) {
844 serrno = errno(*__errno());
845 ret = -1;
846 must_write(&ret, sizeof ret);
847 must_write(&serrno, sizeof serrno);
848 return;
849 }
850
851 /* report opendir() success */
852 ret = 0;
853 must_write(&ret, sizeof ret);
854
855 while ((file = readdir(dp)) != NULL((void *)0)) {
856 strlcpy(path + off, file->d_name, size);
857
858 if (m_priv_local_sanitize_path(path, sizeof path, O_RDONLY0x0000)
859 != 0)
860 continue;
861 fd = open(path, O_RDONLY0x0000);
862 if (fd == -1) {
863 log_error("m_priv_req_readdir: open "
864 "(\"%s\", O_RDONLY, 0) failed", path);
865 continue;
866 }
867 if ((fstat(fd, &sb) == -1) ||
868 !(S_ISREG(sb.st_mode)((sb.st_mode & 0170000) == 0100000) || S_ISLNK(sb.st_mode)((sb.st_mode & 0170000) == 0120000))) {
869 close(fd);
870 continue;
871 }
872
873 len = strlen(path);
874 must_write(&len, sizeof len);
875 must_write(path, len);
876
877 mm_send_fd(m_state.s, fd);
878 close(fd);
879 }
880 closedir(dp);
881
882 len = 0;
883 must_write(&len, sizeof len);
884}