Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/ktrace_test.c
39536 views
1
/*-
2
* Copyright (c) 2015 John Baldwin <[email protected]>
3
* Copyright (c) 2023 The FreeBSD Foundation
4
*
5
* This software was developed by Jake Freeland <[email protected]>
6
* under sponsorship from the FreeBSD Foundation.
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/param.h>
31
#include <sys/capsicum.h>
32
#include <sys/cpuset.h>
33
#include <sys/ktrace.h>
34
#include <sys/mman.h>
35
#include <sys/socket.h>
36
#include <sys/syscall.h>
37
#include <sys/sysent.h>
38
#include <sys/time.h>
39
#include <sys/uio.h>
40
#include <sys/user.h>
41
#include <sys/wait.h>
42
43
#include <machine/sysarch.h>
44
#include <netinet/in.h>
45
46
#include <atf-c.h>
47
#include <capsicum_helpers.h>
48
#include <errno.h>
49
#include <fcntl.h>
50
#include <netdb.h>
51
#include <signal.h>
52
#include <sysdecode.h>
53
54
/*
55
* A variant of ATF_REQUIRE that is suitable for use in child
56
* processes. This only works if the parent process is tripped up by
57
* the early exit and fails some requirement itself.
58
*/
59
#define CHILD_REQUIRE(exp) do { \
60
if (!(exp)) \
61
child_fail_require(__FILE__, __LINE__, \
62
#exp " not met\n"); \
63
} while (0)
64
#define CHILD_REQUIRE_EQ(actual, expected) do { \
65
__typeof__(expected) _e = expected; \
66
__typeof__(actual) _a = actual; \
67
if (_e != _a) \
68
child_fail_require(__FILE__, __LINE__, #actual \
69
" (%jd) == " #expected " (%jd) not met\n", \
70
(intmax_t)_a, (intmax_t)_e); \
71
} while (0)
72
73
static __dead2 void
74
child_fail_require(const char *file, int line, const char *fmt, ...)
75
{
76
va_list ap;
77
char buf[1024];
78
79
/* Use write() not fprintf() to avoid possible duplicate output. */
80
snprintf(buf, sizeof(buf), "%s:%d: ", file, line);
81
write(STDERR_FILENO, buf, strlen(buf));
82
va_start(ap, fmt);
83
vsnprintf(buf, sizeof(buf), fmt, ap);
84
write(STDERR_FILENO, buf, strlen(buf));
85
va_end(ap);
86
87
_exit(32);
88
}
89
90
static void *
91
xmalloc(size_t size)
92
{
93
void *p;
94
95
p = malloc(size);
96
ATF_REQUIRE(p != NULL);
97
return (p);
98
}
99
100
/*
101
* Determine sysdecode ABI based on proc's ABI in sv_flags.
102
*/
103
static enum sysdecode_abi
104
syscallabi(u_int sv_flags)
105
{
106
switch (sv_flags & SV_ABI_MASK) {
107
case SV_ABI_FREEBSD:
108
return (SYSDECODE_ABI_FREEBSD);
109
case SV_ABI_LINUX:
110
#ifdef __LP64__
111
if ((sv_flags & SV_ILP32) != 0)
112
return (SYSDECODE_ABI_LINUX32);
113
#endif
114
return (SYSDECODE_ABI_LINUX);
115
}
116
return (SYSDECODE_ABI_UNKNOWN);
117
}
118
119
static int
120
trace_child(int cpid, int facility, int status)
121
{
122
int error, fd;
123
124
ATF_REQUIRE((fd = open("ktrace.out",
125
O_RDONLY | O_CREAT | O_TRUNC, 0600)) != -1);
126
ATF_REQUIRE_MSG(ktrace("ktrace.out", KTROP_SET, facility, cpid) != -1,
127
"ktrace failed: %s", strerror(errno));
128
/* Notify child that we've starting tracing. */
129
ATF_REQUIRE(kill(cpid, SIGUSR1) != -1);
130
/* Wait for child to raise violation and exit. */
131
ATF_REQUIRE(waitpid(cpid, &error, 0) != -1);
132
ATF_REQUIRE(WIFEXITED(error));
133
ATF_REQUIRE_EQ(WEXITSTATUS(error), status);
134
return (fd);
135
}
136
137
/*
138
* Start tracing capability violations and notify child that it can execute.
139
* Return @numv capability violations from child in @v.
140
*/
141
static void
142
cap_trace_child(pid_t cpid, struct ktr_cap_fail *v, int numv)
143
{
144
struct ktr_header header;
145
ssize_t n;
146
int fd;
147
148
fd = trace_child(cpid, KTRFAC_CAPFAIL, 0);
149
150
/* Read ktrace header and ensure violation occurred. */
151
for (int i = 0; i < numv; ++i) {
152
ATF_REQUIRE((n = read(fd, &header, sizeof(header))) != -1);
153
ATF_REQUIRE_EQ(n, sizeof(header));
154
ATF_REQUIRE_EQ(header.ktr_len, sizeof(*v));
155
ATF_REQUIRE_EQ(header.ktr_pid, cpid);
156
/* Read the capability violation. */
157
ATF_REQUIRE((n = read(fd, v + i,
158
sizeof(*v))) != -1);
159
ATF_REQUIRE_EQ(n, sizeof(*v));
160
}
161
ATF_REQUIRE(close(fd) != -1);
162
}
163
164
/*
165
* Test if ktrace will record an operation that is done with
166
* insufficient rights.
167
*/
168
ATF_TC_WITHOUT_HEAD(ktrace__cap_not_capable);
169
ATF_TC_BODY(ktrace__cap_not_capable, tc)
170
{
171
struct ktr_cap_fail violation;
172
cap_rights_t rights;
173
sigset_t set = { };
174
pid_t pid;
175
int error;
176
177
/* Block SIGUSR1 so child does not terminate. */
178
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
179
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
180
181
ATF_REQUIRE((pid = fork()) != -1);
182
if (pid == 0) {
183
/* Limit fd rights to CAP_READ. */
184
cap_rights_init(&rights, CAP_READ);
185
CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1);
186
CHILD_REQUIRE(caph_enter() != -1);
187
/* Wait until ktrace has started. */
188
CHILD_REQUIRE(sigwait(&set, &error) != -1);
189
CHILD_REQUIRE_EQ(error, SIGUSR1);
190
/* Write without CAP_WRITE. */
191
CHILD_REQUIRE(write(STDIN_FILENO, &pid, sizeof(pid)) == -1);
192
CHILD_REQUIRE_EQ(errno, ENOTCAPABLE);
193
exit(0);
194
}
195
196
cap_trace_child(pid, &violation, 1);
197
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NOTCAPABLE);
198
ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed,
199
CAP_WRITE));
200
}
201
202
/*
203
* Test if ktrace will record an attempt to increase rights.
204
*/
205
ATF_TC_WITHOUT_HEAD(ktrace__cap_increase_rights);
206
ATF_TC_BODY(ktrace__cap_increase_rights, tc)
207
{
208
struct ktr_cap_fail violation;
209
cap_rights_t rights;
210
sigset_t set = { };
211
pid_t pid;
212
int error;
213
214
/* Block SIGUSR1 so child does not terminate. */
215
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
216
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
217
218
ATF_REQUIRE((pid = fork()) != -1);
219
if (pid == 0) {
220
/* Limit fd rights to CAP_READ. */
221
cap_rights_init(&rights, CAP_READ);
222
CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) != -1);
223
CHILD_REQUIRE(caph_enter() != -1);
224
/* Wait until ktrace has started. */
225
CHILD_REQUIRE(sigwait(&set, &error) != -1);
226
CHILD_REQUIRE_EQ(error, SIGUSR1);
227
/* Increase fd rights to include CAP_WRITE. */
228
cap_rights_set(&rights, CAP_WRITE);
229
CHILD_REQUIRE(caph_rights_limit(STDIN_FILENO, &rights) == -1);
230
CHILD_REQUIRE_EQ(errno, ENOTCAPABLE);
231
exit(0);
232
}
233
234
cap_trace_child(pid, &violation, 1);
235
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_INCREASE);
236
ATF_REQUIRE(cap_rights_is_set(&violation.cap_data.cap_needed,
237
CAP_WRITE));
238
}
239
240
/*
241
* Test if disallowed syscalls are reported as capability violations.
242
*/
243
ATF_TC_WITHOUT_HEAD(ktrace__cap_syscall);
244
ATF_TC_BODY(ktrace__cap_syscall, tc)
245
{
246
struct kinfo_file kinf;
247
struct ktr_cap_fail violation[2];
248
sigset_t set = { };
249
pid_t pid;
250
int error;
251
252
/* Block SIGUSR1 so child does not terminate. */
253
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
254
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
255
256
ATF_REQUIRE((pid = fork()) != -1);
257
if (pid == 0) {
258
/* Wait until ktrace has started. */
259
CHILD_REQUIRE(sigwait(&set, &error) != -1);
260
CHILD_REQUIRE_EQ(error, SIGUSR1);
261
/* chdir() is not permitted in capability mode. */
262
CHILD_REQUIRE(chdir(".") != -1);
263
kinf.kf_structsize = sizeof(struct kinfo_file);
264
/*
265
* fcntl() is permitted in capability mode,
266
* but the F_KINFO cmd is not.
267
*/
268
CHILD_REQUIRE(fcntl(STDIN_FILENO, F_KINFO, &kinf) != -1);
269
exit(0);
270
}
271
272
cap_trace_child(pid, violation, 2);
273
ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_SYSCALL);
274
error = syscallabi(violation[0].cap_svflags);
275
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code),
276
"chdir");
277
278
ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_SYSCALL);
279
error = syscallabi(violation[1].cap_svflags);
280
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code),
281
"fcntl");
282
ATF_REQUIRE_EQ(violation[1].cap_data.cap_int, F_KINFO);
283
}
284
285
/*
286
* Test if sending a signal to another process is reported as
287
* a signal violation.
288
*/
289
ATF_TC_WITHOUT_HEAD(ktrace__cap_signal);
290
ATF_TC_BODY(ktrace__cap_signal, tc)
291
{
292
struct ktr_cap_fail violation;
293
sigset_t set = { };
294
pid_t pid;
295
int error;
296
297
/* Block SIGUSR1 so child does not terminate. */
298
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
299
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
300
301
ATF_REQUIRE((pid = fork()) != -1);
302
if (pid == 0) {
303
/* Wait until ktrace has started. */
304
CHILD_REQUIRE(sigwait(&set, &error) != -1);
305
CHILD_REQUIRE_EQ(error, SIGUSR1);
306
/*
307
* Signals may only be sent to ourself. Sending signals
308
* to other processes is not allowed in capability mode.
309
*/
310
CHILD_REQUIRE(kill(getppid(), SIGCONT) != -1);
311
exit(0);
312
}
313
314
cap_trace_child(pid, &violation, 1);
315
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SIGNAL);
316
error = syscallabi(violation.cap_svflags);
317
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code),
318
"kill");
319
ATF_REQUIRE_EQ(violation.cap_data.cap_int, SIGCONT);
320
}
321
322
/*
323
* Test if opening a socket with a restricted protocol is reported
324
* as a protocol violation.
325
*/
326
ATF_TC(ktrace__cap_proto);
327
ATF_TC_HEAD(ktrace__cap_proto, tc)
328
{
329
atf_tc_set_md_var(tc, "require.user", "root");
330
}
331
ATF_TC_BODY(ktrace__cap_proto, tc)
332
{
333
struct ktr_cap_fail violation;
334
sigset_t set = { };
335
pid_t pid;
336
int error;
337
338
/* Block SIGUSR1 so child does not terminate. */
339
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
340
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
341
342
ATF_REQUIRE((pid = fork()) != -1);
343
if (pid == 0) {
344
/* Wait until ktrace has started. */
345
CHILD_REQUIRE(sigwait(&set, &error) != -1);
346
CHILD_REQUIRE_EQ(error, SIGUSR1);
347
/*
348
* Certain protocols may not be used in capability mode.
349
* ICMP's raw-protocol interface is not allowed.
350
*/
351
CHILD_REQUIRE(close(socket(AF_INET, SOCK_RAW,
352
IPPROTO_ICMP)) != -1);
353
exit(0);
354
}
355
356
cap_trace_child(pid, &violation, 1);
357
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_PROTO);
358
error = syscallabi(violation.cap_svflags);
359
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code),
360
"socket");
361
ATF_REQUIRE_EQ(violation.cap_data.cap_int, IPPROTO_ICMP);
362
}
363
364
/*
365
* Test if sending data to an address using a socket is
366
* reported as a sockaddr violation.
367
*/
368
ATF_TC_WITHOUT_HEAD(ktrace__cap_sockaddr);
369
ATF_TC_BODY(ktrace__cap_sockaddr, tc)
370
{
371
struct sockaddr_in addr = { }, *saddr;
372
struct ktr_cap_fail violation;
373
sigset_t set = { };
374
pid_t pid;
375
int error, sfd;
376
377
/* Block SIGUSR1 so child does not terminate. */
378
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
379
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
380
381
ATF_REQUIRE((sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1);
382
addr.sin_family = AF_INET;
383
addr.sin_port = htons(5000);
384
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
385
ATF_REQUIRE(bind(sfd, (const struct sockaddr *)&addr,
386
sizeof(addr)) != -1);
387
388
ATF_REQUIRE((pid = fork()) != -1);
389
if (pid == 0) {
390
/* Wait until ktrace has started. */
391
CHILD_REQUIRE(sigwait(&set, &error) != -1);
392
CHILD_REQUIRE_EQ(error, SIGUSR1);
393
/*
394
* Sending data to an address is not permitted.
395
* In this case, sending data to @addr causes a
396
* violation.
397
*/
398
CHILD_REQUIRE(sendto(sfd, NULL, 0, 0,
399
(const struct sockaddr *)&addr, sizeof(addr)) != -1);
400
exit(0);
401
}
402
403
cap_trace_child(pid, &violation, 1);
404
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_SOCKADDR);
405
error = syscallabi(violation.cap_svflags);
406
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code),
407
"sendto");
408
saddr = (struct sockaddr_in *)&violation.cap_data.cap_sockaddr;
409
ATF_REQUIRE_EQ(saddr->sin_family, AF_INET);
410
ATF_REQUIRE_EQ(saddr->sin_port, htons(5000));
411
ATF_REQUIRE_EQ(saddr->sin_addr.s_addr, htonl(INADDR_LOOPBACK));
412
close(sfd);
413
}
414
415
/*
416
* Test if openat() with AT_FDCWD and absolute path are reported
417
* as namei violations.
418
*/
419
ATF_TC_WITHOUT_HEAD(ktrace__cap_namei);
420
ATF_TC_BODY(ktrace__cap_namei, tc)
421
{
422
struct ktr_cap_fail violation[2];
423
sigset_t set = { };
424
pid_t pid;
425
int error;
426
427
/* Block SIGUSR1 so child does not terminate. */
428
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
429
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
430
431
ATF_REQUIRE((pid = fork()) != -1);
432
if (pid == 0) {
433
/* Wait until ktrace has started. */
434
CHILD_REQUIRE(sigwait(&set, &error) != -1);
435
CHILD_REQUIRE_EQ(error, SIGUSR1);
436
/*
437
* The AT_FDCWD file descriptor has not been opened
438
* and will be inaccessible in capability mode.
439
*/
440
CHILD_REQUIRE(close(openat(AT_FDCWD, "ktrace.out",
441
O_RDONLY | O_CREAT)) != -1);
442
/*
443
* Absolute paths are inaccessible in capability mode.
444
*/
445
CHILD_REQUIRE(close(openat(-1, "/", O_RDONLY)) != -1);
446
exit(0);
447
}
448
449
cap_trace_child(pid, violation, 2);
450
ATF_REQUIRE_EQ(violation[0].cap_type, CAPFAIL_NAMEI);
451
error = syscallabi(violation[0].cap_svflags);
452
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[0].cap_code),
453
"openat");
454
ATF_REQUIRE_STREQ(violation[0].cap_data.cap_path, "AT_FDCWD");
455
456
ATF_REQUIRE_EQ(violation[1].cap_type, CAPFAIL_NAMEI);
457
error = syscallabi(violation[1].cap_svflags);
458
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation[1].cap_code),
459
"openat");
460
ATF_REQUIRE_STREQ(violation[1].cap_data.cap_path, "/");
461
}
462
463
/*
464
* Test if changing another process's cpu set is recorded as
465
* a cpuset violation.
466
*/
467
ATF_TC_WITHOUT_HEAD(ktrace__cap_cpuset);
468
ATF_TC_BODY(ktrace__cap_cpuset, tc)
469
{
470
struct ktr_cap_fail violation;
471
cpuset_t cpuset_mask = { };
472
sigset_t set = { };
473
pid_t pid;
474
int error;
475
476
/* Block SIGUSR1 so child does not terminate. */
477
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
478
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
479
480
ATF_REQUIRE((pid = fork()) != -1);
481
if (pid == 0) {
482
/* Wait until ktrace has started. */
483
CHILD_REQUIRE(sigwait(&set, &error) != -1);
484
CHILD_REQUIRE_EQ(error, SIGUSR1);
485
/*
486
* Set cpu 0 affinity for parent process.
487
* Other process's cpu sets are restricted in capability
488
* mode, so this will raise a violation.
489
*/
490
CPU_SET(0, &cpuset_mask);
491
CHILD_REQUIRE(cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID,
492
getppid(), sizeof(cpuset_mask), &cpuset_mask) != -1);
493
exit(0);
494
}
495
496
cap_trace_child(pid, &violation, 1);
497
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_CPUSET);
498
error = syscallabi(violation.cap_svflags);
499
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code),
500
"cpuset_setaffinity");
501
}
502
503
ATF_TC_WITHOUT_HEAD(ktrace__cap_shm_open);
504
ATF_TC_BODY(ktrace__cap_shm_open, tc)
505
{
506
struct ktr_cap_fail violation;
507
sigset_t set = { };
508
pid_t pid;
509
int error;
510
511
/* Block SIGUSR1 so child does not terminate. */
512
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
513
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
514
515
ATF_REQUIRE((pid = fork()) != -1);
516
if (pid == 0) {
517
/* Wait until ktrace has started. */
518
CHILD_REQUIRE(sigwait(&set, &error) != -1);
519
CHILD_REQUIRE_EQ(error, SIGUSR1);
520
521
CHILD_REQUIRE(shm_open("/ktrace_shm", O_RDWR | O_CREAT,
522
0600) != -1);
523
CHILD_REQUIRE(shm_unlink("/ktrace_shm") != -1);
524
exit(0);
525
}
526
527
cap_trace_child(pid, &violation, 1);
528
ATF_REQUIRE_EQ(violation.cap_type, CAPFAIL_NAMEI);
529
error = syscallabi(violation.cap_svflags);
530
ATF_REQUIRE_STREQ(sysdecode_syscallname(error, violation.cap_code),
531
"shm_open2");
532
ATF_REQUIRE_STREQ(violation.cap_data.cap_path, "/ktrace_shm");
533
}
534
535
/*
536
* Make sure that ktrace is disabled upon exec of a setuid binary.
537
*/
538
ATF_TC(ktrace__setuid_exec);
539
ATF_TC_HEAD(ktrace__setuid_exec, tc)
540
{
541
atf_tc_set_md_var(tc, "require.user", "unprivileged");
542
}
543
ATF_TC_BODY(ktrace__setuid_exec, tc)
544
{
545
struct ktr_header header;
546
struct ktr_syscall *syscall;
547
sigset_t set = { };
548
off_t off, off1;
549
ssize_t n;
550
pid_t pid;
551
int error, fd;
552
553
/* Block SIGUSR1 so child does not terminate. */
554
ATF_REQUIRE(sigaddset(&set, SIGUSR1) != -1);
555
ATF_REQUIRE(sigprocmask(SIG_BLOCK, &set, NULL) != -1);
556
557
ATF_REQUIRE((pid = fork()) != -1);
558
if (pid == 0) {
559
/* Wait until ktrace has started. */
560
CHILD_REQUIRE(sigwait(&set, &error) != -1);
561
CHILD_REQUIRE_EQ(error, SIGUSR1);
562
563
execve("/usr/bin/su", (char *[]){ "su", "whoami", NULL }, NULL);
564
_exit(0);
565
}
566
567
fd = trace_child(pid, KTRFAC_SYSCALL, 1);
568
569
n = read(fd, &header, sizeof(header));
570
ATF_REQUIRE(n >= 0);
571
ATF_REQUIRE_EQ((size_t)n, sizeof(header));
572
ATF_REQUIRE_EQ(header.ktr_pid, pid);
573
ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall));
574
575
syscall = xmalloc(header.ktr_len);
576
n = read(fd, syscall, header.ktr_len);
577
ATF_REQUIRE(n >= 0);
578
ATF_REQUIRE_EQ(n, header.ktr_len);
579
if (syscall->ktr_code == SYS_sigwait) {
580
free(syscall);
581
582
/* Skip the sigwait() syscall. */
583
n = read(fd, &header, sizeof(header));
584
ATF_REQUIRE(n >= 0);
585
ATF_REQUIRE_EQ((size_t)n, sizeof(header));
586
ATF_REQUIRE_EQ(header.ktr_pid, pid);
587
ATF_REQUIRE(header.ktr_len >= (int)sizeof(*syscall));
588
589
syscall = xmalloc(header.ktr_len);
590
n = read(fd, syscall, header.ktr_len);
591
ATF_REQUIRE(n >= 0);
592
ATF_REQUIRE_EQ(n, header.ktr_len);
593
}
594
ATF_REQUIRE_EQ(syscall->ktr_code, SYS_execve);
595
free(syscall);
596
597
/* su is setuid root, so this should have been the last entry. */
598
off = lseek(fd, 0, SEEK_CUR);
599
ATF_REQUIRE(off != -1);
600
off1 = lseek(fd, 0, SEEK_END);
601
ATF_REQUIRE(off1 != -1);
602
ATF_REQUIRE_EQ(off, off1);
603
604
ATF_REQUIRE(close(fd) == 0);
605
}
606
607
ATF_TP_ADD_TCS(tp)
608
{
609
ATF_TP_ADD_TC(tp, ktrace__cap_not_capable);
610
ATF_TP_ADD_TC(tp, ktrace__cap_increase_rights);
611
ATF_TP_ADD_TC(tp, ktrace__cap_syscall);
612
ATF_TP_ADD_TC(tp, ktrace__cap_signal);
613
ATF_TP_ADD_TC(tp, ktrace__cap_proto);
614
ATF_TP_ADD_TC(tp, ktrace__cap_sockaddr);
615
ATF_TP_ADD_TC(tp, ktrace__cap_namei);
616
ATF_TP_ADD_TC(tp, ktrace__cap_cpuset);
617
ATF_TP_ADD_TC(tp, ktrace__cap_shm_open);
618
ATF_TP_ADD_TC(tp, ktrace__setuid_exec);
619
return (atf_no_error());
620
}
621
622