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