1 /*-
2 * Copyright (c) 2005 Andrey Simonenko
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD: stable/12/tools/regression/sockets/unix_cmsg/uc_common.c 309554 2016-12-05 17:21:04Z sobomax $");
29
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <err.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <inttypes.h>
36 #include <stdarg.h>
37 #include <stdbool.h>
38 #include <stdlib.h>
39 #include <stdio.h>
40 #include <string.h>
41 #include <unistd.h>
42 #include <sys/wait.h>
43
44 #include "uc_common.h"
45
46 #ifndef LISTENQ
47 # define LISTENQ 1
48 #endif
49
50 #ifndef TIMEOUT
51 # define TIMEOUT 2
52 #endif
53
54 #define SYNC_SERVER 0
55 #define SYNC_CLIENT 1
56 #define SYNC_RECV 0
57 #define SYNC_SEND 1
58
59 #define LOGMSG_SIZE 128
60
61 void
uc_output(const char * format,...)62 uc_output(const char *format, ...)
63 {
64 char buf[LOGMSG_SIZE];
65 va_list ap;
66
67 va_start(ap, format);
68 if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
69 err(EXIT_FAILURE, "output: vsnprintf failed");
70 write(STDOUT_FILENO, buf, strlen(buf));
71 va_end(ap);
72 }
73
74 void
uc_logmsg(const char * format,...)75 uc_logmsg(const char *format, ...)
76 {
77 char buf[LOGMSG_SIZE];
78 va_list ap;
79 int errno_save;
80
81 errno_save = errno;
82 va_start(ap, format);
83 if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
84 err(EXIT_FAILURE, "logmsg: vsnprintf failed");
85 if (errno_save == 0)
86 uc_output("%s: %s\n", uc_cfg.proc_name, buf);
87 else
88 uc_output("%s: %s: %s\n", uc_cfg.proc_name, buf,
89 strerror(errno_save));
90 va_end(ap);
91 errno = errno_save;
92 }
93
94 void
uc_vlogmsgx(const char * format,va_list ap)95 uc_vlogmsgx(const char *format, va_list ap)
96 {
97 char buf[LOGMSG_SIZE];
98
99 if (vsnprintf(buf, sizeof(buf), format, ap) < 0)
100 err(EXIT_FAILURE, "uc_logmsgx: vsnprintf failed");
101 uc_output("%s: %s\n", uc_cfg.proc_name, buf);
102 }
103
104 void
uc_logmsgx(const char * format,...)105 uc_logmsgx(const char *format, ...)
106 {
107 va_list ap;
108
109 va_start(ap, format);
110 uc_vlogmsgx(format, ap);
111 va_end(ap);
112 }
113
114 void
uc_dbgmsg(const char * format,...)115 uc_dbgmsg(const char *format, ...)
116 {
117 va_list ap;
118
119 if (uc_cfg.debug) {
120 va_start(ap, format);
121 uc_vlogmsgx(format, ap);
122 va_end(ap);
123 }
124 }
125
126 int
uc_socket_create(void)127 uc_socket_create(void)
128 {
129 struct timeval tv;
130 int fd;
131
132 fd = socket(PF_LOCAL, uc_cfg.sock_type, 0);
133 if (fd < 0) {
134 uc_logmsg("socket_create: socket(PF_LOCAL, %s, 0)", uc_cfg.sock_type_str);
135 return (-1);
136 }
137 if (uc_cfg.server_flag)
138 uc_cfg.serv_sock_fd = fd;
139
140 tv.tv_sec = TIMEOUT;
141 tv.tv_usec = 0;
142 if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0 ||
143 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0) {
144 uc_logmsg("socket_create: setsockopt(SO_RCVTIMEO/SO_SNDTIMEO)");
145 goto failed;
146 }
147
148 if (uc_cfg.server_flag) {
149 if (bind(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun,
150 uc_cfg.serv_addr_sun.sun_len) < 0) {
151 uc_logmsg("socket_create: bind(%s)",
152 uc_cfg.serv_addr_sun.sun_path);
153 goto failed;
154 }
155 if (uc_cfg.sock_type == SOCK_STREAM) {
156 int val;
157
158 if (listen(fd, LISTENQ) < 0) {
159 uc_logmsg("socket_create: listen");
160 goto failed;
161 }
162 val = fcntl(fd, F_GETFL, 0);
163 if (val < 0) {
164 uc_logmsg("socket_create: fcntl(F_GETFL)");
165 goto failed;
166 }
167 if (fcntl(fd, F_SETFL, val | O_NONBLOCK) < 0) {
168 uc_logmsg("socket_create: fcntl(F_SETFL)");
169 goto failed;
170 }
171 }
172 }
173
174 return (fd);
175
176 failed:
177 if (close(fd) < 0)
178 uc_logmsg("socket_create: close");
179 if (uc_cfg.server_flag)
180 if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0)
181 uc_logmsg("socket_close: unlink(%s)",
182 uc_cfg.serv_addr_sun.sun_path);
183 return (-1);
184 }
185
186 int
uc_socket_close(int fd)187 uc_socket_close(int fd)
188 {
189 int rv;
190
191 rv = 0;
192 if (close(fd) < 0) {
193 uc_logmsg("socket_close: close");
194 rv = -1;
195 }
196 if (uc_cfg.server_flag && fd == uc_cfg.serv_sock_fd)
197 if (unlink(uc_cfg.serv_addr_sun.sun_path) < 0) {
198 uc_logmsg("socket_close: unlink(%s)",
199 uc_cfg.serv_addr_sun.sun_path);
200 rv = -1;
201 }
202 return (rv);
203 }
204
205 int
uc_socket_connect(int fd)206 uc_socket_connect(int fd)
207 {
208 uc_dbgmsg("connect");
209
210 if (connect(fd, (struct sockaddr *)&uc_cfg.serv_addr_sun,
211 uc_cfg.serv_addr_sun.sun_len) < 0) {
212 uc_logmsg("socket_connect: connect(%s)", uc_cfg.serv_addr_sun.sun_path);
213 return (-1);
214 }
215 return (0);
216 }
217
218 int
uc_sync_recv(void)219 uc_sync_recv(void)
220 {
221 ssize_t ssize;
222 int fd;
223 char buf;
224
225 uc_dbgmsg("sync: wait");
226
227 fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_SERVER : SYNC_CLIENT][SYNC_RECV];
228
229 ssize = read(fd, &buf, 1);
230 if (ssize < 0) {
231 uc_logmsg("sync_recv: read");
232 return (-1);
233 }
234 if (ssize < 1) {
235 uc_logmsgx("sync_recv: read %zd of 1 byte", ssize);
236 return (-1);
237 }
238
239 uc_dbgmsg("sync: received");
240
241 return (0);
242 }
243
244 int
uc_sync_send(void)245 uc_sync_send(void)
246 {
247 ssize_t ssize;
248 int fd;
249
250 uc_dbgmsg("sync: send");
251
252 fd = uc_cfg.sync_fd[uc_cfg.server_flag ? SYNC_CLIENT : SYNC_SERVER][SYNC_SEND];
253
254 ssize = write(fd, "", 1);
255 if (ssize < 0) {
256 uc_logmsg("uc_sync_send: write");
257 return (-1);
258 }
259 if (ssize < 1) {
260 uc_logmsgx("uc_sync_send: sent %zd of 1 byte", ssize);
261 return (-1);
262 }
263
264 return (0);
265 }
266
267 int
uc_message_send(int fd,const struct msghdr * msghdr)268 uc_message_send(int fd, const struct msghdr *msghdr)
269 {
270 const struct cmsghdr *cmsghdr;
271 size_t size;
272 ssize_t ssize;
273
274 size = msghdr->msg_iov != 0 ? msghdr->msg_iov->iov_len : 0;
275 uc_dbgmsg("send: data size %zu", size);
276 uc_dbgmsg("send: msghdr.msg_controllen %u",
277 (u_int)msghdr->msg_controllen);
278 cmsghdr = CMSG_FIRSTHDR(msghdr);
279 if (cmsghdr != NULL)
280 uc_dbgmsg("send: cmsghdr.cmsg_len %u",
281 (u_int)cmsghdr->cmsg_len);
282
283 ssize = sendmsg(fd, msghdr, 0);
284 if (ssize < 0) {
285 uc_logmsg("message_send: sendmsg");
286 return (-1);
287 }
288 if ((size_t)ssize != size) {
289 uc_logmsgx("message_send: sendmsg: sent %zd of %zu bytes",
290 ssize, size);
291 return (-1);
292 }
293
294 if (!uc_cfg.send_data_flag)
295 if (uc_sync_send() < 0)
296 return (-1);
297
298 return (0);
299 }
300
301 int
uc_message_sendn(int fd,struct msghdr * msghdr)302 uc_message_sendn(int fd, struct msghdr *msghdr)
303 {
304 u_int i;
305
306 for (i = 1; i <= uc_cfg.ipc_msg.msg_num; ++i) {
307 uc_dbgmsg("message #%u", i);
308 if (uc_message_send(fd, msghdr) < 0)
309 return (-1);
310 }
311 return (0);
312 }
313
314 int
uc_message_recv(int fd,struct msghdr * msghdr)315 uc_message_recv(int fd, struct msghdr *msghdr)
316 {
317 const struct cmsghdr *cmsghdr;
318 size_t size;
319 ssize_t ssize;
320
321 if (!uc_cfg.send_data_flag)
322 if (uc_sync_recv() < 0)
323 return (-1);
324
325 size = msghdr->msg_iov != NULL ? msghdr->msg_iov->iov_len : 0;
326 ssize = recvmsg(fd, msghdr, MSG_WAITALL);
327 if (ssize < 0) {
328 uc_logmsg("message_recv: recvmsg");
329 return (-1);
330 }
331 if ((size_t)ssize != size) {
332 uc_logmsgx("message_recv: recvmsg: received %zd of %zu bytes",
333 ssize, size);
334 return (-1);
335 }
336
337 uc_dbgmsg("recv: data size %zd", ssize);
338 uc_dbgmsg("recv: msghdr.msg_controllen %u",
339 (u_int)msghdr->msg_controllen);
340 cmsghdr = CMSG_FIRSTHDR(msghdr);
341 if (cmsghdr != NULL)
342 uc_dbgmsg("recv: cmsghdr.cmsg_len %u",
343 (u_int)cmsghdr->cmsg_len);
344
345 if (memcmp(uc_cfg.ipc_msg.buf_recv, uc_cfg.ipc_msg.buf_send, size) != 0) {
346 uc_logmsgx("message_recv: received message has wrong content");
347 return (-1);
348 }
349
350 return (0);
351 }
352
353 int
uc_socket_accept(int listenfd)354 uc_socket_accept(int listenfd)
355 {
356 fd_set rset;
357 struct timeval tv;
358 int fd, rv, val;
359
360 uc_dbgmsg("accept");
361
362 FD_ZERO(&rset);
363 FD_SET(listenfd, &rset);
364 tv.tv_sec = TIMEOUT;
365 tv.tv_usec = 0;
366 rv = select(listenfd + 1, &rset, (fd_set *)NULL, (fd_set *)NULL, &tv);
367 if (rv < 0) {
368 uc_logmsg("socket_accept: select");
369 return (-1);
370 }
371 if (rv == 0) {
372 uc_logmsgx("socket_accept: select timeout");
373 return (-1);
374 }
375
376 fd = accept(listenfd, (struct sockaddr *)NULL, (socklen_t *)NULL);
377 if (fd < 0) {
378 uc_logmsg("socket_accept: accept");
379 return (-1);
380 }
381
382 val = fcntl(fd, F_GETFL, 0);
383 if (val < 0) {
384 uc_logmsg("socket_accept: fcntl(F_GETFL)");
385 goto failed;
386 }
387 if (fcntl(fd, F_SETFL, val & ~O_NONBLOCK) < 0) {
388 uc_logmsg("socket_accept: fcntl(F_SETFL)");
389 goto failed;
390 }
391
392 return (fd);
393
394 failed:
395 if (close(fd) < 0)
396 uc_logmsg("socket_accept: close");
397 return (-1);
398 }
399
400 int
uc_check_msghdr(const struct msghdr * msghdr,size_t size)401 uc_check_msghdr(const struct msghdr *msghdr, size_t size)
402 {
403 if (msghdr->msg_flags & MSG_TRUNC) {
404 uc_logmsgx("msghdr.msg_flags has MSG_TRUNC");
405 return (-1);
406 }
407 if (msghdr->msg_flags & MSG_CTRUNC) {
408 uc_logmsgx("msghdr.msg_flags has MSG_CTRUNC");
409 return (-1);
410 }
411 if (msghdr->msg_controllen < size) {
412 uc_logmsgx("msghdr.msg_controllen %u < %zu",
413 (u_int)msghdr->msg_controllen, size);
414 return (-1);
415 }
416 if (msghdr->msg_controllen > 0 && size == 0) {
417 uc_logmsgx("msghdr.msg_controllen %u > 0",
418 (u_int)msghdr->msg_controllen);
419 return (-1);
420 }
421 return (0);
422 }
423
424 int
uc_check_cmsghdr(const struct cmsghdr * cmsghdr,int type,size_t size)425 uc_check_cmsghdr(const struct cmsghdr *cmsghdr, int type, size_t size)
426 {
427 if (cmsghdr == NULL) {
428 uc_logmsgx("cmsghdr is NULL");
429 return (-1);
430 }
431 if (cmsghdr->cmsg_level != SOL_SOCKET) {
432 uc_logmsgx("cmsghdr.cmsg_level %d != SOL_SOCKET",
433 cmsghdr->cmsg_level);
434 return (-1);
435 }
436 if (cmsghdr->cmsg_type != type) {
437 uc_logmsgx("cmsghdr.cmsg_type %d != %d",
438 cmsghdr->cmsg_type, type);
439 return (-1);
440 }
441 if (cmsghdr->cmsg_len != CMSG_LEN(size)) {
442 uc_logmsgx("cmsghdr.cmsg_len %u != %zu",
443 (u_int)cmsghdr->cmsg_len, CMSG_LEN(size));
444 return (-1);
445 }
446 return (0);
447 }
448
449 static void
uc_msghdr_init_generic(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data)450 uc_msghdr_init_generic(struct msghdr *msghdr, struct iovec *iov, void *cmsg_data)
451 {
452 msghdr->msg_name = NULL;
453 msghdr->msg_namelen = 0;
454 if (uc_cfg.send_data_flag) {
455 iov->iov_base = uc_cfg.server_flag ?
456 uc_cfg.ipc_msg.buf_recv : uc_cfg.ipc_msg.buf_send;
457 iov->iov_len = uc_cfg.ipc_msg.buf_size;
458 msghdr->msg_iov = iov;
459 msghdr->msg_iovlen = 1;
460 } else {
461 msghdr->msg_iov = NULL;
462 msghdr->msg_iovlen = 0;
463 }
464 msghdr->msg_control = cmsg_data;
465 msghdr->msg_flags = 0;
466 }
467
468 void
uc_msghdr_init_server(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data,size_t cmsg_size)469 uc_msghdr_init_server(struct msghdr *msghdr, struct iovec *iov,
470 void *cmsg_data, size_t cmsg_size)
471 {
472 uc_msghdr_init_generic(msghdr, iov, cmsg_data);
473 msghdr->msg_controllen = cmsg_size;
474 uc_dbgmsg("init: data size %zu", msghdr->msg_iov != NULL ?
475 msghdr->msg_iov->iov_len : (size_t)0);
476 uc_dbgmsg("init: msghdr.msg_controllen %u",
477 (u_int)msghdr->msg_controllen);
478 }
479
480 void
uc_msghdr_init_client(struct msghdr * msghdr,struct iovec * iov,void * cmsg_data,size_t cmsg_size,int type,size_t arr_size)481 uc_msghdr_init_client(struct msghdr *msghdr, struct iovec *iov,
482 void *cmsg_data, size_t cmsg_size, int type, size_t arr_size)
483 {
484 struct cmsghdr *cmsghdr;
485
486 uc_msghdr_init_generic(msghdr, iov, cmsg_data);
487 if (cmsg_data != NULL) {
488 if (uc_cfg.send_array_flag)
489 uc_dbgmsg("sending an array");
490 else
491 uc_dbgmsg("sending a scalar");
492 msghdr->msg_controllen = uc_cfg.send_array_flag ?
493 cmsg_size : CMSG_SPACE(0);
494 cmsghdr = CMSG_FIRSTHDR(msghdr);
495 cmsghdr->cmsg_level = SOL_SOCKET;
496 cmsghdr->cmsg_type = type;
497 cmsghdr->cmsg_len = CMSG_LEN(uc_cfg.send_array_flag ? arr_size : 0);
498 } else
499 msghdr->msg_controllen = 0;
500 }
501
502 int
uc_client_fork(void)503 uc_client_fork(void)
504 {
505 int fd1, fd2;
506
507 if (pipe(uc_cfg.sync_fd[SYNC_SERVER]) < 0 ||
508 pipe(uc_cfg.sync_fd[SYNC_CLIENT]) < 0) {
509 uc_logmsg("client_fork: pipe");
510 return (-1);
511 }
512 uc_cfg.client_pid = fork();
513 if (uc_cfg.client_pid == (pid_t)-1) {
514 uc_logmsg("client_fork: fork");
515 return (-1);
516 }
517 if (uc_cfg.client_pid == 0) {
518 uc_cfg.proc_name = "CLIENT";
519 uc_cfg.server_flag = false;
520 fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV];
521 fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND];
522 } else {
523 fd1 = uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND];
524 fd2 = uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV];
525 }
526 if (close(fd1) < 0 || close(fd2) < 0) {
527 uc_logmsg("client_fork: close");
528 return (-1);
529 }
530 return (uc_cfg.client_pid != 0);
531 }
532
533 void
uc_client_exit(int rv)534 uc_client_exit(int rv)
535 {
536 if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_SEND]) < 0 ||
537 close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_RECV]) < 0) {
538 uc_logmsg("client_exit: close");
539 rv = -1;
540 }
541 rv = rv == 0 ? EXIT_SUCCESS : -rv;
542 uc_dbgmsg("exit: code %d", rv);
543 _exit(rv);
544 }
545
546 int
uc_client_wait(void)547 uc_client_wait(void)
548 {
549 int status;
550 pid_t pid;
551
552 uc_dbgmsg("waiting for client");
553
554 if (close(uc_cfg.sync_fd[SYNC_SERVER][SYNC_RECV]) < 0 ||
555 close(uc_cfg.sync_fd[SYNC_CLIENT][SYNC_SEND]) < 0) {
556 uc_logmsg("client_wait: close");
557 return (-1);
558 }
559
560 pid = waitpid(uc_cfg.client_pid, &status, 0);
561 if (pid == (pid_t)-1) {
562 uc_logmsg("client_wait: waitpid");
563 return (-1);
564 }
565
566 if (WIFEXITED(status)) {
567 if (WEXITSTATUS(status) != EXIT_SUCCESS) {
568 uc_logmsgx("client exit status is %d",
569 WEXITSTATUS(status));
570 return (-WEXITSTATUS(status));
571 }
572 } else {
573 if (WIFSIGNALED(status))
574 uc_logmsgx("abnormal termination of client, signal %d%s",
575 WTERMSIG(status), WCOREDUMP(status) ?
576 " (core file generated)" : "");
577 else
578 uc_logmsgx("termination of client, unknown status");
579 return (-1);
580 }
581
582 return (0);
583 }
584
585 int
uc_check_groups(const char * gid_arr_str,const gid_t * gid_arr,const char * gid_num_str,int gid_num,bool all_gids)586 uc_check_groups(const char *gid_arr_str, const gid_t *gid_arr,
587 const char *gid_num_str, int gid_num, bool all_gids)
588 {
589 int i;
590
591 for (i = 0; i < gid_num; ++i)
592 uc_dbgmsg("%s[%d] %lu", gid_arr_str, i, (u_long)gid_arr[i]);
593
594 if (all_gids) {
595 if (gid_num != uc_cfg.proc_cred.gid_num) {
596 uc_logmsgx("%s %d != %d", gid_num_str, gid_num,
597 uc_cfg.proc_cred.gid_num);
598 return (-1);
599 }
600 } else {
601 if (gid_num > uc_cfg.proc_cred.gid_num) {
602 uc_logmsgx("%s %d > %d", gid_num_str, gid_num,
603 uc_cfg.proc_cred.gid_num);
604 return (-1);
605 }
606 }
607 if (memcmp(gid_arr, uc_cfg.proc_cred.gid_arr,
608 gid_num * sizeof(*gid_arr)) != 0) {
609 uc_logmsgx("%s content is wrong", gid_arr_str);
610 for (i = 0; i < gid_num; ++i)
611 if (gid_arr[i] != uc_cfg.proc_cred.gid_arr[i]) {
612 uc_logmsgx("%s[%d] %lu != %lu",
613 gid_arr_str, i, (u_long)gid_arr[i],
614 (u_long)uc_cfg.proc_cred.gid_arr[i]);
615 break;
616 }
617 return (-1);
618 }
619 return (0);
620 }
621
622 int
uc_check_scm_creds_cmsgcred(struct cmsghdr * cmsghdr)623 uc_check_scm_creds_cmsgcred(struct cmsghdr *cmsghdr)
624 {
625 const struct cmsgcred *cmcred;
626 int rc;
627
628 if (uc_check_cmsghdr(cmsghdr, SCM_CREDS, sizeof(struct cmsgcred)) < 0)
629 return (-1);
630
631 cmcred = (struct cmsgcred *)CMSG_DATA(cmsghdr);
632
633 uc_dbgmsg("cmsgcred.cmcred_pid %ld", (long)cmcred->cmcred_pid);
634 uc_dbgmsg("cmsgcred.cmcred_uid %lu", (u_long)cmcred->cmcred_uid);
635 uc_dbgmsg("cmsgcred.cmcred_euid %lu", (u_long)cmcred->cmcred_euid);
636 uc_dbgmsg("cmsgcred.cmcred_gid %lu", (u_long)cmcred->cmcred_gid);
637 uc_dbgmsg("cmsgcred.cmcred_ngroups %d", cmcred->cmcred_ngroups);
638
639 rc = 0;
640
641 if (cmcred->cmcred_pid != uc_cfg.client_pid) {
642 uc_logmsgx("cmsgcred.cmcred_pid %ld != %ld",
643 (long)cmcred->cmcred_pid, (long)uc_cfg.client_pid);
644 rc = -1;
645 }
646 if (cmcred->cmcred_uid != uc_cfg.proc_cred.uid) {
647 uc_logmsgx("cmsgcred.cmcred_uid %lu != %lu",
648 (u_long)cmcred->cmcred_uid, (u_long)uc_cfg.proc_cred.uid);
649 rc = -1;
650 }
651 if (cmcred->cmcred_euid != uc_cfg.proc_cred.euid) {
652 uc_logmsgx("cmsgcred.cmcred_euid %lu != %lu",
653 (u_long)cmcred->cmcred_euid, (u_long)uc_cfg.proc_cred.euid);
654 rc = -1;
655 }
656 if (cmcred->cmcred_gid != uc_cfg.proc_cred.gid) {
657 uc_logmsgx("cmsgcred.cmcred_gid %lu != %lu",
658 (u_long)cmcred->cmcred_gid, (u_long)uc_cfg.proc_cred.gid);
659 rc = -1;
660 }
661 if (cmcred->cmcred_ngroups == 0) {
662 uc_logmsgx("cmsgcred.cmcred_ngroups == 0");
663 rc = -1;
664 }
665 if (cmcred->cmcred_ngroups < 0) {
666 uc_logmsgx("cmsgcred.cmcred_ngroups %d < 0",
667 cmcred->cmcred_ngroups);
668 rc = -1;
669 }
670 if (cmcred->cmcred_ngroups > CMGROUP_MAX) {
671 uc_logmsgx("cmsgcred.cmcred_ngroups %d > %d",
672 cmcred->cmcred_ngroups, CMGROUP_MAX);
673 rc = -1;
674 }
675 if (cmcred->cmcred_groups[0] != uc_cfg.proc_cred.egid) {
676 uc_logmsgx("cmsgcred.cmcred_groups[0] %lu != %lu (EGID)",
677 (u_long)cmcred->cmcred_groups[0], (u_long)uc_cfg.proc_cred.egid);
678 rc = -1;
679 }
680 if (uc_check_groups("cmsgcred.cmcred_groups", cmcred->cmcred_groups,
681 "cmsgcred.cmcred_ngroups", cmcred->cmcred_ngroups, false) < 0)
682 rc = -1;
683 return (rc);
684 }
685
686 int
uc_check_scm_creds_sockcred(struct cmsghdr * cmsghdr)687 uc_check_scm_creds_sockcred(struct cmsghdr *cmsghdr)
688 {
689 const struct sockcred *sc;
690 int rc;
691
692 if (uc_check_cmsghdr(cmsghdr, SCM_CREDS,
693 SOCKCREDSIZE(uc_cfg.proc_cred.gid_num)) < 0)
694 return (-1);
695
696 sc = (struct sockcred *)CMSG_DATA(cmsghdr);
697
698 rc = 0;
699
700 uc_dbgmsg("sockcred.sc_uid %lu", (u_long)sc->sc_uid);
701 uc_dbgmsg("sockcred.sc_euid %lu", (u_long)sc->sc_euid);
702 uc_dbgmsg("sockcred.sc_gid %lu", (u_long)sc->sc_gid);
703 uc_dbgmsg("sockcred.sc_egid %lu", (u_long)sc->sc_egid);
704 uc_dbgmsg("sockcred.sc_ngroups %d", sc->sc_ngroups);
705
706 if (sc->sc_uid != uc_cfg.proc_cred.uid) {
707 uc_logmsgx("sockcred.sc_uid %lu != %lu",
708 (u_long)sc->sc_uid, (u_long)uc_cfg.proc_cred.uid);
709 rc = -1;
710 }
711 if (sc->sc_euid != uc_cfg.proc_cred.euid) {
712 uc_logmsgx("sockcred.sc_euid %lu != %lu",
713 (u_long)sc->sc_euid, (u_long)uc_cfg.proc_cred.euid);
714 rc = -1;
715 }
716 if (sc->sc_gid != uc_cfg.proc_cred.gid) {
717 uc_logmsgx("sockcred.sc_gid %lu != %lu",
718 (u_long)sc->sc_gid, (u_long)uc_cfg.proc_cred.gid);
719 rc = -1;
720 }
721 if (sc->sc_egid != uc_cfg.proc_cred.egid) {
722 uc_logmsgx("sockcred.sc_egid %lu != %lu",
723 (u_long)sc->sc_egid, (u_long)uc_cfg.proc_cred.egid);
724 rc = -1;
725 }
726 if (sc->sc_ngroups == 0) {
727 uc_logmsgx("sockcred.sc_ngroups == 0");
728 rc = -1;
729 }
730 if (sc->sc_ngroups < 0) {
731 uc_logmsgx("sockcred.sc_ngroups %d < 0",
732 sc->sc_ngroups);
733 rc = -1;
734 }
735 if (sc->sc_ngroups != uc_cfg.proc_cred.gid_num) {
736 uc_logmsgx("sockcred.sc_ngroups %d != %u",
737 sc->sc_ngroups, uc_cfg.proc_cred.gid_num);
738 rc = -1;
739 }
740 if (uc_check_groups("sockcred.sc_groups", sc->sc_groups,
741 "sockcred.sc_ngroups", sc->sc_ngroups, true) < 0)
742 rc = -1;
743 return (rc);
744 }
745