seccomp_unotify.2: A cookie check is also required after reading target's memory
[man-pages.git] / man2 / seccomp_unotify.2
blob89c0192a3072a88820a03e58f4107ab1da761cea
1 .\" Copyright (C) 2020 Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" %%%LICENSE_START(VERBATIM)
4 .\" Permission is granted to make and distribute verbatim copies of this
5 .\" manual provided the copyright notice and this permission notice are
6 .\" preserved on all copies.
7 .\"
8 .\" Permission is granted to copy and distribute modified versions of this
9 .\" manual under the conditions for verbatim copying, provided that the
10 .\" entire resulting derived work is distributed under the terms of a
11 .\" permission notice identical to this one.
12 .\"
13 .\" Since the Linux kernel and libraries are constantly changing, this
14 .\" manual page may be incorrect or out-of-date.  The author(s) assume no
15 .\" responsibility for errors or omissions, or for damages resulting from
16 .\" the use of the information contained herein.  The author(s) may not
17 .\" have taken the same level of care in the production of this manual,
18 .\" which is licensed free of charge, as they might when working
19 .\" professionally.
20 .\"
21 .\" Formatted or processed versions of this manual, if unaccompanied by
22 .\" the source, must acknowledge the copyright and authors of this work.
23 .\" %%%LICENSE_END
24 .\"
25 .TH SECCOMP_UNOTIFY 2 2020-10-01 "Linux" "Linux Programmer's Manual"
26 .SH NAME
27 seccomp_unotify \- Seccomp user-space notification mechanism
28 .SH SYNOPSIS
29 .nf
30 .B #include <linux/seccomp.h>
31 .B #include <linux/filter.h>
32 .B #include <linux/audit.h>
33 .PP
34 .BI "int seccomp(unsigned int " operation ", unsigned int " flags \
35 ", void *" args );
36 .PP
37 .B #include <sys/ioctl.h>
38 .PP
39 .BI "int ioctl(int " fd ", SECCOMP_IOCTL_NOTIF_RECV,"
40 .BI "          struct seccomp_notif *" req );
41 .BI "int ioctl(int " fd ", SECCOMP_IOCTL_NOTIF_SEND,"
42 .BI "          struct seccomp_notif_resp *" resp );
43 .BI "int ioctl(int " fd ", SECCOMP_IOCTL_NOTIF_ID_VALID, __u64 *" id );
44 .fi
45 .SH DESCRIPTION
46 This page describes the user-space notification mechanism provided by the
47 Secure Computing (seccomp) facility.
48 As well as the use of the
49 .B SECCOMP_FILTER_FLAG_NEW_LISTENER
50 flag, the
51 .BR SECCOMP_RET_USER_NOTIF
52 action value, and the
53 .B SECCOMP_GET_NOTIF_SIZES
54 operation described in
55 .BR seccomp (2),
56 this mechanism involves the use of a number of related
57 .BR ioctl (2)
58 operations (described below).
59 .\"
60 .SS Overview
61 In conventional usage of a seccomp filter,
62 the decision about how to treat a system call is made by the filter itself.
63 By contrast, the user-space notification mechanism allows
64 the seccomp filter to delegate
65 the handling of the system call to another user-space process.
66 Note that this mechanism is explicitly
67 .B not
68 intended as a method implementing security policy; see NOTES.
69 .PP
70 In the discussion that follows,
71 the thread(s) on which the seccomp filter is installed is (are)
72 referred to as the
73 .IR target ,
74 and the process that is notified by the user-space notification
75 mechanism is referred to as the
76 .IR supervisor .
77 .PP
78 A suitably privileged supervisor can use the user-space notification
79 mechanism to perform actions on behalf of the target.
80 The advantage of the user-space notification mechanism is that
81 the supervisor will
82 usually be able to retrieve information about the target and the
83 performed system call that the seccomp filter itself cannot.
84 (A seccomp filter is limited in the information it can obtain and
85 the actions that it can perform because it
86 is running on a virtual machine inside the kernel.)
87 .PP
88 An overview of the steps performed by the target and the supervisor
89 is as follows:
90 .\"-------------------------------------
91 .IP 1. 3
92 The target establishes a seccomp filter in the usual manner,
93 but with two differences:
94 .RS
95 .IP \(bu 2
96 The
97 .BR seccomp (2)
98 .I flags
99 argument includes the flag
100 .BR SECCOMP_FILTER_FLAG_NEW_LISTENER .
101 Consequently, the return value of the (successful)
102 .BR seccomp (2)
103 call is a new "listening"
104 file descriptor that can be used to receive notifications.
105 Only one "listening" seccomp filter can be installed for a thread.
106 .\" FIXME
107 .\" Is the last sentence above correct?
109 .\" Kees Cook (25 Oct 2020) notes:
111 .\" I like this limitation, but I expect that it'll need to change in the
112 .\" future. Even with LSMs, we see the need for arbitrary stacking, and the
113 .\" idea of there being only 1 supervisor will eventually break down. Right
114 .\" now there is only 1 because only container managers are using this
115 .\" feature. But if some daemon starts using it to isolate some thread,
116 .\" suddenly it might break if a container manager is trying to listen to it
117 .\" too, etc. I expect it won't be needed soon, but I do think it'll change.
119 .IP \(bu
120 In cases where it is appropriate, the seccomp filter returns the action value
121 .BR SECCOMP_RET_USER_NOTIF .
122 This return value will trigger a notification event.
124 .\"-------------------------------------
125 .IP 2.
126 In order that the supervisor can obtain notifications
127 using the listening file descriptor,
128 (a duplicate of) that file descriptor must be passed from
129 the target to the supervisor.
130 One way in which this could be done is by passing the file descriptor
131 over a UNIX domain socket connection between the target and the supervisor
132 (using the
133 .BR SCM_RIGHTS
134 ancillary message type described in
135 .BR unix (7)).
136 .\" Jann Horn:
137 .\"     Instead of using unix domain sockets to send the fd to the
138 .\"     parent, I think you could also use clone3() with
139 .\"     flags==CLONE_FILES|SIGCHLD, dup2() the seccomp fd to an fd
140 .\"     that was reserved in the parent, call unshare(CLONE_FILES)
141 .\"     in the child after setting up the seccomp fd, and wake
142 .\"     up the parent with something like pthread_cond_signal()?
143 .\"     I'm not sure whether that'd look better or worse in the
144 .\"     end though, so maybe just ignore this comment.
145 .\"-------------------------------------
146 .IP 3.
147 The supervisor will receive notification events
148 on the listening file descriptor.
149 These events are returned as structures of type
150 .IR seccomp_notif .
151 Because this structure and its size may evolve over kernel versions,
152 the supervisor must first determine the size of this structure
153 using the
154 .BR seccomp (2)
155 .B SECCOMP_GET_NOTIF_SIZES
156 operation, which returns a structure of type
157 .IR seccomp_notif_sizes .
158 The supervisor allocates a buffer of size
159 .I seccomp_notif_sizes.seccomp_notif
160 bytes to receive notification events.
161 In addition,the supervisor allocates another buffer of size
162 .I seccomp_notif_sizes.seccomp_notif_resp
163 bytes for the response (a
164 .I struct seccomp_notif_resp
165 structure)
166 that it will provide to the kernel (and thus the target).
167 .\"-------------------------------------
168 .IP 4.
169 The target then performs its workload,
170 which includes system calls that will be controlled by the seccomp filter.
171 Whenever one of these system calls causes the filter to return the
172 .B SECCOMP_RET_USER_NOTIF
173 action value, the kernel does
174 .I not
175 (yet) execute the system call;
176 instead, execution of the target is temporarily blocked inside
177 the kernel (in a sleep state that is interruptible by signals)
178 and a notification event is generated on the listening file descriptor.
179 .\"-------------------------------------
180 .IP 5.
181 The supervisor can now repeatedly monitor the
182 listening file descriptor for
183 .BR SECCOMP_RET_USER_NOTIF -triggered
184 events.
185 To do this, the supervisor uses the
186 .B SECCOMP_IOCTL_NOTIF_RECV
187 .BR ioctl (2)
188 operation to read information about a notification event;
189 this operation blocks until an event is available.
190 The operation returns a
191 .I seccomp_notif
192 structure containing information about the system call
193 that is being attempted by the target.
194 .\"-------------------------------------
195 .IP 6.
197 .I seccomp_notif
198 structure returned by the
199 .B SECCOMP_IOCTL_NOTIF_RECV
200 operation includes the same information (a
201 .I seccomp_data
202 structure) that was passed to the seccomp filter.
203 This information allows the supervisor to discover the system call number and
204 the arguments for the target's system call.
205 In addition, the notification event contains the ID of the thread
206 that triggered the notification and a unique cookie value that
207 is used in subsequent
208 .B SECCOMP_IOCTL_NOTIF_ID_VALID
210 .B SECCOMP_IOCTL_NOTIF_SEND
211 operations.
213 The information in the notification can be used to discover the
214 values of pointer arguments for the target's system call.
215 (This is something that can't be done from within a seccomp filter.)
216 One way in which the supervisor can do this is to open the corresponding
217 .I /proc/[tid]/mem
218 file (see
219 .BR proc (5))
220 and read bytes from the location that corresponds to one of
221 the pointer arguments whose value is supplied in the notification event.
222 .\" Tycho Andersen mentioned that there are alternatives to /proc/PID/mem,
223 .\" such as ptrace() and /proc/PID/map_files
224 (The supervisor must be careful to avoid
225 a race condition that can occur when doing this;
226 see the description of the
227 .BR SECCOMP_IOCTL_NOTIF_ID_VALID
228 .BR ioctl (2)
229 operation below.)
230 In addition,
231 the supervisor can access other system information that is visible
232 in user space but which is not accessible from a seccomp filter.
233 .\"-------------------------------------
234 .IP 7.
235 Having obtained information as per the previous step,
236 the supervisor may then choose to perform an action in response
237 to the target's system call
238 (which, as noted above, is not executed when the seccomp filter returns the
239 .B SECCOMP_RET_USER_NOTIF
240 action value).
242 One example use case here relates to containers.
243 The target may be located inside a container where
244 it does not have sufficient capabilities to mount a filesystem
245 in the container's mount namespace.
246 However, the supervisor may be a more privileged process that
247 does have sufficient capabilities to perform the mount operation.
248 .\"-------------------------------------
249 .IP 8.
250 The supervisor then sends a response to the notification.
251 The information in this response is used by the kernel to construct
252 a return value for the target's system call and provide
253 a value that will be assigned to the
254 .I errno
255 variable of the target.
257 The response is sent using the
258 .B SECCOMP_IOCTL_NOTIF_SEND
259 .BR ioctl (2)
260 operation, which is used to transmit a
261 .I seccomp_notif_resp
262 structure to the kernel.
263 This structure includes a cookie value that the supervisor obtained in the
264 .I seccomp_notif
265 structure returned by the
266 .B SECCOMP_IOCTL_NOTIF_RECV
267 operation.
268 This cookie value allows the kernel to associate the response with the
269 target.
270 This structure must include the cookie value that the supervisor
271 obtained in the
272 .I seccomp_notif
273 structure returned by the
274 .B SECCOMP_IOCTL_NOTIF_RECV
275 operation;
276 the cookie allows the kernel to associate the response with the target.
277 .\"-------------------------------------
278 .IP 9.
279 Once the notification has been sent,
280 the system call in the target thread unblocks,
281 returning the information that was provided by the supervisor
282 in the notification response.
283 .\"-------------------------------------
285 As a variation on the last two steps,
286 the supervisor can send a response that tells the kernel that it
287 should execute the target thread's system call; see the discussion of
288 .BR SECCOMP_USER_NOTIF_FLAG_CONTINUE ,
289 below.
291 .SS ioctl(2) operations
292 The following
293 .BR ioctl (2)
294 operations are provided to support seccomp user-space notification.
295 For each of these operations, the first (file descriptor) argument of
296 .BR ioctl (2)
297 is the listening file descriptor returned by a call to
298 .BR seccomp (2)
299 with the
300 .BR SECCOMP_FILTER_FLAG_NEW_LISTENER
301 flag.
303 .BR SECCOMP_IOCTL_NOTIF_RECV " (since Linux 5.0)"
304 This operation is used to obtain a user-space
305 notification event.
306 If no such event is currently pending,
307 the operation blocks until an event occurs.
308 The third
309 .BR ioctl (2)
310 argument is a pointer to a structure of the following form
311 which contains information about the event.
312 This structure must be zeroed out before the call.
314 .in +4n
316 struct seccomp_notif {
317     __u64  id;              /* Cookie */
318     __u32  pid;             /* TID of target thread */
319     __u32  flags;           /* Currently unused (0) */
320     struct seccomp_data data;   /* See seccomp(2) */
325 The fields in this structure are as follows:
328 .I id
329 This is a cookie for the notification.
330 Each such cookie is guaranteed to be unique for the corresponding
331 seccomp filter.
333 .IP \(bu 2
334 The cookie can be used with the
335 .B SECCOMP_IOCTL_NOTIF_ID_VALID
336 .BR ioctl (2)
337 operation described below.
338 .IP \(bu
339 When returning a notification response to the kernel,
340 the supervisor must include the cookie value in the
341 .IR seccomp_notif_resp
342 structure that is specified as the argument of the
343 .BR SECCOMP_IOCTL_NOTIF_SEND
344 operation.
347 .I pid
348 This is the thread ID of the target thread that triggered
349 the notification event.
351 .I flags
352 This is a bit mask of flags providing further information on the event.
353 In the current implementation, this field is always zero.
355 .I data
356 This is a
357 .I seccomp_data
358 structure containing information about the system call that
359 triggered the notification.
360 This is the same structure that is passed to the seccomp filter.
362 .BR seccomp (2)
363 for details of this structure.
366 On success, this operation returns 0; on failure, \-1 is returned, and
367 .I errno
368 is set to indicate the cause of the error.
369 This operation can fail with the following errors:
372 .BR EINVAL " (since Linux 5.5)"
373 .\" commit 2882d53c9c6f3b8311d225062522f03772cf0179
375 .I seccomp_notif
376 structure that was passed to the call contained nonzero fields.
378 .B ENOENT
379 The target thread was killed by a signal as the notification information
380 was being generated,
381 or the target's (blocked) system call was interrupted by a signal handler.
383 .\" FIXME
384 .\" From my experiments,
385 .\" it appears that if a SECCOMP_IOCTL_NOTIF_RECV is done after
386 .\" the target thread terminates, then the ioctl() simply
387 .\" blocks (rather than returning an error to indicate that the
388 .\" target no longer exists).
390 .\" I found that surprising, and it required some contortions in
391 .\" the example program.  It was not possible to code my SIGCHLD
392 .\" handler (which reaps the zombie when the worker/target
393 .\" terminates) to simply set a flag checked in the main
394 .\" handleNotifications() loop, since this created an
395 .\" unavoidable race where the child might terminate just after
396 .\" I had checked the flag, but before I blocked (forever!) in the
397 .\" SECCOMP_IOCTL_NOTIF_RECV operation. Instead, I had to code
398 .\" the signal handler to simply call _exit(2) in order to
399 .\" terminate the parent process (the supervisor).
401 .\" Is this expected behavior? It seems to me rather
402 .\" desirable that SECCOMP_IOCTL_NOTIF_RECV should give an error
403 .\" if the target has terminated.
405 .\" Jann posted a patch to rectify this, but there was no response
406 .\" (Lore link: https://bit.ly/3jvUBxk) to his question about fixing
407 .\" this issue. (I've tried building with the patch, but encountered
408 .\" an issue with the target process entering D state after a signal.)
410 .\" For now, this behavior is documented in BUGS.
412 .\" Kees Cook commented: Let's change [this] ASAP!
414 .BR SECCOMP_IOCTL_NOTIF_ID_VALID " (since Linux 5.0)"
415 This operation can be used to check that a notification ID
416 returned by an earlier
417 .B SECCOMP_IOCTL_NOTIF_RECV
418 operation is still valid
419 (i.e., that the target still exists and its system call
420 is still blocked waiting for a response).
422 The third
423 .BR ioctl (2)
424 argument is a pointer to the cookie
425 .RI ( id )
426 returned by the
427 .B SECCOMP_IOCTL_NOTIF_RECV
428 operation.
430 This operation is necessary to avoid race conditions that can occur when the
431 .I pid
432 returned by the
433 .B SECCOMP_IOCTL_NOTIF_RECV
434 operation terminates, and that process ID is reused by another process.
435 An example of this kind of race is the following
437 .IP 1. 3
438 A notification is generated on the listening file descriptor.
439 The returned
440 .I seccomp_notif
441 contains the TID of the target thread (in the
442 .I pid
443 field of the structure).
444 .IP 2.
445 The target terminates.
446 .IP 3.
447 Another thread or process is created on the system that by chance reuses the
448 TID that was freed when the target terminated.
449 .IP 4.
450 The supervisor
451 .BR open (2)s
453 .IR /proc/[tid]/mem
454 file for the TID obtained in step 1, with the intention of (say)
455 inspecting the memory location(s) that containing the argument(s) of
456 the system call that triggered the notification in step 1.
459 In the above scenario, the risk is that the supervisor may try
460 to access the memory of a process other than the target.
461 This race can be avoided by following the call to
462 .BR open (2)
463 with a
464 .B SECCOMP_IOCTL_NOTIF_ID_VALID
465 operation to verify that the process that generated the notification
466 is still alive.
467 (Note that if the target terminates after the latter step,
468 a subsequent
469 .BR read (2)
470 from the file descriptor may return 0, indicating end of file.)
471 .\" Jann Horn:
472 .\"     the PID can be reused, but the /proc/$pid directory is
473 .\"     internally not associated with the numeric PID, but,
474 .\"     conceptually speaking, with a specific incarnation of the
475 .\"     PID, or something like that.  (Actually, it is associated
476 .\"     with the "struct pid", which is not reused, instead of the
477 .\"     numeric PID.
479 See NOTES for a discussion of other cases where
480 .B SECCOMP_IOCTL_NOTIF_ID_VALID
481 checks must be performed.
483 On success (i.e., the notification ID is still valid),
484 this operation returns 0.
485 On failure (i.e., the notification ID is no longer valid),
486 \-1 is returned, and
487 .I errno
488 is set to
489 .BR ENOENT .
491 .BR SECCOMP_IOCTL_NOTIF_SEND " (since Linux 5.0)"
492 This operation is used to send a notification response back to the kernel.
493 The third
494 .BR ioctl (2)
495 argument of this structure is a pointer to a structure of the following form:
497 .in +4n
499 struct seccomp_notif_resp {
500     __u64 id;               /* Cookie value */
501     __s64 val;              /* Success return value */
502     __s32 error;            /* 0 (success) or negative
503                                error number */
504     __u32 flags;            /* See below */
509 The fields of this structure are as follows:
512 .I id
513 This is the cookie value that was obtained using the
514 .B SECCOMP_IOCTL_NOTIF_RECV
515 operation.
516 This cookie value allows the kernel to correctly associate this response
517 with the system call that triggered the user-space notification.
519 .I val
520 This is the value that will be used for a spoofed
521 success return for the target's system call; see below.
523 .I error
524 This is the value that will be used as the error number
525 .RI ( errno )
526 for a spoofed error return for the target's system call; see below.
528 .I flags
529 This is a bit mask that includes zero or more of the following flags:
532 .BR SECCOMP_USER_NOTIF_FLAG_CONTINUE " (since Linux 5.5)"
533 Tell the kernel to execute the target's system call.
534 .\" commit fb3c5386b382d4097476ce9647260fc89b34afdb
538 Two kinds of response are possible:
540 .IP \(bu 2
541 A response to the kernel telling it to execute the
542 target's system call.
543 In this case, the
544 .I flags
545 field includes
546 .B SECCOMP_USER_NOTIF_FLAG_CONTINUE
547 and the
548 .I error
550 .I val
551 fields must be zero.
553 This kind of response can be useful in cases where the supervisor needs
554 to do deeper analysis of the target's system call than is possible
555 from a seccomp filter (e.g., examining the values of pointer arguments),
556 and, having decided that the system call does not require emulation
557 by the supervisor, the supervisor wants the system call to
558 be executed normally in the target.
561 .B SECCOMP_USER_NOTIF_FLAG_CONTINUE
562 flag should be used with caution; see NOTES.
563 .IP \(bu
564 A spoofed return value for the target's system call.
565 In this case, the kernel does not execute the target's system call,
566 instead causing the system call to return a spoofed value as specified by
567 fields of the
568 .I seccomp_notif_resp
569 structure.
570 The supervisor should set the fields of this structure as follows:
572 .IP + 3
573 .I flags
574 does not contain
575 .BR SECCOMP_USER_NOTIF_FLAG_CONTINUE .
576 .IP +
577 .I error
578 is set either to 0 for a spoofed "success" return or to a negative
579 error number for a spoofed "failure" return.
580 In the former case, the kernel causes the target's system call
581 to return the value specified in the
582 .I val
583 field.
584 In the later case, the kernel causes the target's system call
585 to return \-1, and
586 .I errno
587 is assigned the negated
588 .I error
589 value.
590 .IP +
591 .I val
592 is set to a value that will be used as the return value for a spoofed
593 "success" return for the target's system call.
594 The value in this field is ignored if the
595 .I error
596 field contains a nonzero value.
597 .\" FIXME
598 .\" Kees Cook suggested:
600 .\" Strictly speaking, this is architecture specific, but
601 .\" all architectures do it this way. Should seccomp enforce
602 .\" val == 0 when err != 0 ?
606 On success, this operation returns 0; on failure, \-1 is returned, and
607 .I errno
608 is set to indicate the cause of the error.
609 This operation can fail with the following errors:
612 .B EINPROGRESS
613 A response to this notification has already been sent.
615 .B EINVAL
616 An invalid value was specified in the
617 .I flags field.
620 .B EINVAL
622 .I flags
623 field contained
624 .BR SECCOMP_USER_NOTIF_FLAG_CONTINUE ,
625 and the
626 .I error
628 .I val
629 field was not zero.
631 .B ENOENT
632 The blocked system call in the target
633 has been interrupted by a signal handler
634 or the target has terminated.
635 .\" Jann Horn notes:
636 .\"     you could also get this [ENOENT] if a response has already
637 .\"     been sent, instead of EINPROGRESS - the only difference is
638 .\"     whether the target thread has picked up the response yet
640 .SH NOTES
641 One example use case for the user-space notification
642 mechanism is to allow a container manager
643 (a process which is typically running with more privilege than
644 the processes inside the container)
645 to mount block devices or create device nodes for the container.
646 The mount use case provides an example of where the
647 .BR SECCOMP_USER_NOTIF_FLAG_CONTINUE
648 .BR ioctl (2)
649 operation is useful.
650 Upon receiving a notification for the
651 .BR mount (2)
652 system call, the container manager (the "supervisor") can distinguish
653 a request to mount a block filesystem
654 (which would not be possible for a "target" process inside the container)
655 and mount that file system.
656 If, on the other hand, the container manager detects that the operation
657 could be performed by the process inside the container
658 (e.g., a mount of a
659 .BR tmpfs (5)
660 filesystem), it can notify the kernel that the target process's
661 .BR mount (2)
662 system call can continue.
664 .SS select()/poll()/epoll semantics
665 The file descriptor returned when
666 .BR seccomp (2)
667 is employed with the
668 .B SECCOMP_FILTER_FLAG_NEW_LISTENER
669 flag can be monitored using
670 .BR poll (2),
671 .BR epoll (7),
673 .BR select (2).
674 These interfaces indicate that the file descriptor is ready as follows:
675 .IP \(bu 2
676 When a notification is pending,
677 these interfaces indicate that the file descriptor is readable.
678 Following such an indication, a subsequent
679 .B SECCOMP_IOCTL_NOTIF_RECV
680 .BR ioctl (2)
681 will not block, returning either information about a notification
682 or else failing with the error
683 .B EINTR
684 if the target has been killed by a signal or its system call
685 has been interrupted by a signal handler.
686 .IP \(bu
687 After the notification has been received (i.e., by the
688 .B SECCOMP_IOCTL_NOTIF_RECV
689 .BR ioctl (2)
690 operation), these interfaces indicate that the file descriptor is writable,
691 meaning that a notification response can be sent using the
692 .B SECCOMP_IOCTL_NOTIF_SEND
693 .BR ioctl (2)
694 operation.
695 .IP \(bu
696 After the last thread using the filter has terminated and been reaped using
697 .BR waitpid (2)
698 (or similar),
699 the file descriptor indicates an end-of-file condition (readable in
700 .BR select (2);
701 .BR POLLHUP / EPOLLHUP
703 .BR poll (2)/
704 .BR epoll_wait (2)).
705 .SS Design goals; use of SECCOMP_USER_NOTIF_FLAG_CONTINUE
706 The intent of the user-space notification feature is
707 to allow system calls to be performed on behalf of the target.
708 The target's system call should either be handled by the supervisor or
709 allowed to continue normally in the kernel (where standard security
710 policies will be applied).
712 .BR "Note well" :
713 this mechanism must not be used to make security policy decisions
714 about the system call,
715 which would be inherently race-prone for reasons described next.
718 .B SECCOMP_USER_NOTIF_FLAG_CONTINUE
719 flag must be used with caution.
720 If set by the supervisor, the target's system call will continue.
721 However, there is a time-of-check, time-of-use race here,
722 since an attacker could exploit the interval of time where the target is
723 blocked waiting on the "continue" response to do things such as
724 rewriting the system call arguments.
726 Note furthermore that a user-space notifier can be bypassed if
727 the existing filters allow the use of
728 .BR seccomp (2)
730 .BR prctl (2)
731 to install a filter that returns an action value with a higher precedence than
732 .B SECCOMP_RET_USER_NOTIF
733 (see
734 .BR seccomp (2)).
736 It should thus be absolutely clear that the
737 seccomp user-space notification mechanism
738 .B can not
739 be used to implement a security policy!
740 It should only ever be used in scenarios where a more privileged process
741 supervises the system calls of a lesser privileged target to
742 get around kernel-enforced security restrictions when
743 the supervisor deems this safe.
744 In other words,
745 in order to continue a system call, the supervisor should be sure that
746 another security mechanism or the kernel itself will sufficiently block
747 the system call if its arguments are rewritten to something unsafe.
749 .SS Caveats regarding the use of /proc/[tid]/mem
750 The discussion above noted the need to use the
751 .BR SECCOMP_IOCTL_NOTIF_ID_VALID
752 .BR ioctl (2)
753 when opening the
754 .IR /proc/[tid]/mem
755 file of the target
756 to avoid the possibility of accessing the memory of the wrong process
757 in the event that the target terminates and its ID
758 is recycled by another (unrelated) thread.
759 However, the use of this
760 .BR ioctl (2)
761 operation is also necessary in other situations,
762 as explained in the following paragraphs.
764 Consider the following scenario, where the supervisor
765 tries to read the pathname argument of a target's blocked
766 .BR mount (2)
767 system call:
768 .IP \(bu 2
769 From one of its functions
770 .RI ( func() ),
771 the target calls
772 .BR mount (2),
773 which triggers a user-space notification and causes the target to block.
774 .IP \(bu
775 The supervisor receives the notification, opens
776 .IR /proc/[tid]/mem ,
777 and (successfully) performs the
778 .BR SECCOMP_IOCTL_NOTIF_ID_VALID
779 check.
780 .IP \(bu
781 The target receives a signal, which causes the
782 .BR mount (2)
783 to abort.
784 .IP \(bu
785 The signal handler executes in the target, and returns.
786 .IP \(bu
787 Upon return from the handler, the execution of
788 .I func()
789 resumes, and it returns (and perhaps other functions are called,
790 overwriting the memory that had been used for the stack frame of
791 .IR func() ).
792 .IP \(bu
793 Using the address provided in the notification information,
794 the supervisor reads from the target's memory location that used to
795 contain the pathname.
796 .IP \(bu
797 The supervisor now calls
798 .BR mount (2)
799 with some arbitrary bytes obtained in the previous step.
801 The conclusion from the above scenario is this:
802 since the target's blocked system call may be interrupted by a signal handler,
803 the supervisor must be written to expect that the
804 target may abandon its system call at
805 .B any
806 time;
807 in such an event, any information that the supervisor obtained from
808 the target's memory must be considered invalid.
810 To prevent such scenarios,
811 every read from the target's memory must be separated from use of
812 the bytes so obtained by a
813 .BR SECCOMP_IOCTL_NOTIF_ID_VALID
814 check.
815 In the above example, the check would be placed between the two final steps.
816 An example of such a check is shown in EXAMPLES.
818 Following on from the above, it should be clear that
819 a write by the supervisor into the target's memory can
820 .B never
821 be considered safe.
823 .SS Interaction with SA_RESTART signal handlers
824 Consider the following scenario:
825 .IP \(bu 2
826 The target process has used
827 .BR sigaction (2)
828 to install a signal handler with the
829 .B SA_RESTART
830 flag.
831 .IP \(bu
832 The target has made a system call that triggered a seccomp
833 user-space notification and the target is currently blocked
834 until the supervisor sends a notification response.
835 .IP \(bu
836 A signal is delivered to the target and the signal handler is executed.
837 .IP \(bu
838 When (if) the supervisor attempts to send a notification response, the
839 .B SECCOMP_IOCTL_NOTIF_SEND
840 .BR ioctl (2))
841 operation will fail with the
842 .BR ENOENT
843 error.
845 In this scenario, the kernel will restart the target's system call.
846 Consequently, the supervisor will receive another user-space notification.
847 Thus, depending on how many times the blocked system call
848 is interrupted by a signal handler,
849 the supervisor may receive multiple notifications for
850 the same instance of a system call in the target.
852 One oddity is that system call restarting as described in this scenario
853 will occur even for the blocking system calls listed in
854 .BR signal (7)
855 that would
856 .B never
857 normally be restarted by the
858 .BR SA_RESTART
859 flag.
860 .\" FIXME
861 .\" About the above, Kees Cook commented:
863 .\" Does this need fixing? I imagine the correct behavior for this case
864 .\" would be a response to _SEND of EINPROGRESS and the target would see
865 .\" EINTR normally?
867 .\" I mean, it's not like seccomp doesn't already expose weirdness with
868 .\" syscall restarts. Not even arm64 compat agrees[3] with arm32 in this
869 .\" regard. :(
871 .\" FIXME
872 .\" Michael Kerrisk:
873 .\" I wonder about the effect of this oddity for system calls that
874 .\" are normally nonrestartable because they have timeouts. My
875 .\" understanding is that the kernel doesn't restart those system
876 .\" calls because it's impossible for the kernel to restart the call
877 .\" with the right timeout value. I wonder what happens when those
878 .\" system calls are restarted in the scenario we're discussing.)
879 .SH BUGS
880 If a
881 .BR SECCOMP_IOCTL_NOTIF_RECV
882 .BR ioctl (2)
883 operation
884 .\" or a poll/epoll/select
885 is performed after the target terminates, then the
886 .BR ioctl (2)
887 call simply blocks (rather than returning an error to indicate that the
888 target no longer exists).
889 .\" FIXME
890 .\" Comment from Kees Cook:
892 .\" I want this fixed. It caused me no end of pain when building the
893 .\" selftests, and ended up spawning my implementing a global test timeout
894 .\" in kselftest. :P Before the usage counter refactor, there was no sane
895 .\" way to deal with this, but now I think we're close.
897 .SH EXAMPLES
898 The (somewhat contrived) program shown below demonstrates the use of
899 the interfaces described in this page.
900 The program creates a child process that serves as the "target" process.
901 The child process installs a seccomp filter that returns the
902 .B SECCOMP_RET_USER_NOTIF
903 action value if a call is made to
904 .BR mkdir (2).
905 The child process then calls
906 .BR mkdir (2)
907 once for each of the supplied command-line arguments,
908 and reports the result returned by the call.
909 After processing all arguments, the child process terminates.
911 The parent process acts as the supervisor, listening for the notifications
912 that are generated when the target process calls
913 .BR mkdir (2).
914 When such a notification occurs,
915 the supervisor examines the memory of the target process (using
916 .IR /proc/[pid]/mem )
917 to discover the pathname argument that was supplied to the
918 .BR mkdir (2)
919 call, and performs one of the following actions:
920 .IP \(bu 2
921 If the pathname begins with the prefix "/tmp/",
922 then the supervisor attempts to create the specified directory,
923 and then spoofs a return for the target process based on the return
924 value of the supervisor's
925 .BR mkdir (2)
926 call.
927 In the event that that call succeeds,
928 the spoofed success return value is the length of the pathname.
929 .IP \(bu
930 If the pathname begins with "./" (i.e., it is a relative pathname),
931 the supervisor sends a
932 .B SECCOMP_USER_NOTIF_FLAG_CONTINUE
933 response to the kernel to say that the kernel should execute
934 the target process's
935 .BR mkdir (2)
936 call.
937 .IP \(bu
938 If the pathname begins with some other prefix,
939 the supervisor spoofs an error return for the target process,
940 so that the target process's
941 .BR mkdir (2)
942 call appears to fail with the error
943 .BR EOPNOTSUPP
944 ("Operation not supported").
945 Additionally, if the specified pathname is exactly "/bye",
946 then the supervisor terminates.
948 This program can be used to demonstrate various aspects of the
949 behavior of the seccomp user-space notification mechanism.
950 To help aid such demonstrations,
951 the program logs various messages to show the operation
952 of the target process (lines prefixed "T:") and the supervisor
953 (indented lines prefixed "S:").
955 In the following example, the target attempts to create the directory
956 .IR /tmp/x .
957 Upon receiving the notification, the supervisor creates the directory on the
958 target's behalf,
959 and spoofs a success return to be received by the target process's
960 .BR mkdir (2)
961 call.
963 .in +4n
965 $ \fB./seccomp_unotify /tmp/x\fP
966 T: PID = 23168
968 T: about to mkdir("/tmp/x")
969         S: got notification (ID 0x17445c4a0f4e0e3c) for PID 23168
970         S: executing: mkdir("/tmp/x", 0700)
971         S: success! spoofed return = 6
972         S: sending response (flags = 0; val = 6; error = 0)
973 T: SUCCESS: mkdir(2) returned 6
975 T: terminating
976         S: target has terminated; bye
980 In the above output, note that the spoofed return value seen by the target
981 process is 6 (the length of the pathname
982 .IR /tmp/x ),
983 whereas a normal
984 .BR mkdir (2)
985 call returns 0 on success.
987 In the next example, the target attempts to create a directory using the
988 relative pathname
989 .IR ./sub .
990 Since this pathname starts with "./",
991 the supervisor sends a
992 .B SECCOMP_USER_NOTIF_FLAG_CONTINUE
993 response to the kernel,
994 and the kernel then (successfully) executes the target process's
995 .BR mkdir (2)
996 call.
998 .in +4n
1000 $ \fB./seccomp_unotify ./sub\fP
1001 T: PID = 23204
1003 T: about to mkdir("./sub")
1004         S: got notification (ID 0xddb16abe25b4c12) for PID 23204
1005         S: target can execute system call
1006         S: sending response (flags = 0x1; val = 0; error = 0)
1007 T: SUCCESS: mkdir(2) returned 0
1009 T: terminating
1010         S: target has terminated; bye
1014 If the target process attempts to create a directory with
1015 a pathname that doesn't start with "." and doesn't begin with the prefix
1016 "/tmp/", then the supervisor spoofs an error return
1017 .RB ( EOPNOTSUPP ,
1018 "Operation not  supported")
1019 for the target's
1020 .BR mkdir (2)
1021 call (which is not executed):
1023 .in +4n
1025 $ \fB./seccomp_unotify /xxx\fP
1026 T: PID = 23178
1028 T: about to mkdir("/xxx")
1029         S: got notification (ID 0xe7dc095d1c524e80) for PID 23178
1030         S: spoofing error response (Operation not supported)
1031         S: sending response (flags = 0; val = 0; error = \-95)
1032 T: ERROR: mkdir(2): Operation not supported
1034 T: terminating
1035         S: target has terminated; bye
1039 In the next example,
1040 the target process attempts to create a directory with the pathname
1041 .BR /tmp/nosuchdir/b .
1042 Upon receiving the notification,
1043 the supervisor attempts to create that directory, but the
1044 .BR mkdir (2)
1045 call fails because the directory
1046 .BR /tmp/nosuchdir
1047 does not exist.
1048 Consequently, the supervisor spoofs an error return that passes the error
1049 that it received back to the target process's
1050 .BR mkdir (2)
1051 call.
1053 .in +4n
1055 $ \fB./seccomp_unotify /tmp/nosuchdir/b\fP
1056 T: PID = 23199
1058 T: about to mkdir("/tmp/nosuchdir/b")
1059         S: got notification (ID 0x8744454293506046) for PID 23199
1060         S: executing: mkdir("/tmp/nosuchdir/b", 0700)
1061         S: failure! (errno = 2; No such file or directory)
1062         S: sending response (flags = 0; val = 0; error = \-2)
1063 T: ERROR: mkdir(2): No such file or directory
1065 T: terminating
1066         S: target has terminated; bye
1070 If the supervisor receives a notification and sees that the
1071 argument of the target's
1072 .BR mkdir (2)
1073 is the string "/bye", then (as well as spoofing an
1074 .B EOPNOTSUPP
1075 error), the supervisor terminates.
1076 If the target process subsequently executes another
1077 .BR mkdir (2)
1078 that triggers its seccomp filter to return the
1079 .B SECCOMP_RET_USER_NOTIF
1080 action value, then the kernel causes the target process's system call to
1081 fail with the error
1082 .B ENOSYS
1083 ("Function not implemented").
1084 This is demonstrated by the following example:
1086 .in +4n
1088 $ \fB./seccomp_unotify /bye /tmp/y\fP
1089 T: PID = 23185
1091 T: about to mkdir("/bye")
1092         S: got notification (ID 0xa81236b1d2f7b0f4) for PID 23185
1093         S: spoofing error response (Operation not supported)
1094         S: sending response (flags = 0; val = 0; error = \-95)
1095         S: terminating **********
1096 T: ERROR: mkdir(2): Operation not supported
1098 T: about to mkdir("/tmp/y")
1099 T: ERROR: mkdir(2): Function not implemented
1101 T: terminating
1105 .SS Program source
1107 #define _GNU_SOURCE
1108 #include <errno.h>
1109 #include <fcntl.h>
1110 #include <limits.h>
1111 #include <linux/audit.h>
1112 #include <linux/filter.h>
1113 #include <linux/seccomp.h>
1114 #include <signal.h>
1115 #include <stdbool.h>
1116 #include <stddef.h>
1117 #include <stdint.h>
1118 #include <stdio.h>
1119 #include <stdlib.h>
1120 #include <sys/socket.h>
1121 #include <sys/ioctl.h>
1122 #include <sys/prctl.h>
1123 #include <sys/stat.h>
1124 #include <sys/types.h>
1125 #include <sys/un.h>
1126 #include <sys/syscall.h>
1127 #include <unistd.h>
1129 #define errExit(msg)    do { perror(msg); exit(EXIT_FAILURE); \e
1130                         } while (0)
1132 /* Send the file descriptor \(aqfd\(aq over the connected UNIX domain socket
1133    \(aqsockfd\(aq. Returns 0 on success, or \-1 on error. */
1135 static int
1136 sendfd(int sockfd, int fd)
1138     struct msghdr msgh;
1139     struct iovec iov;
1140     int data;
1141     struct cmsghdr *cmsgp;
1143     /* Allocate a char array of suitable size to hold the ancillary data.
1144        However, since this buffer is in reality a \(aqstruct cmsghdr\(aq, use a
1145        union to ensure that it is suitably aligned. */
1146     union {
1147         char   buf[CMSG_SPACE(sizeof(int))];
1148                         /* Space large enough to hold an \(aqint\(aq */
1149         struct cmsghdr align;
1150     } controlMsg;
1152     /* The \(aqmsg_name\(aq field can be used to specify the address of the
1153        destination socket when sending a datagram. However, we do not
1154        need to use this field because \(aqsockfd\(aq is a connected socket. */
1156     msgh.msg_name = NULL;
1157     msgh.msg_namelen = 0;
1159     /* On Linux, we must transmit at least one byte of real data in
1160        order to send ancillary data. We transmit an arbitrary integer
1161        whose value is ignored by recvfd(). */
1163     msgh.msg_iov = &iov;
1164     msgh.msg_iovlen = 1;
1165     iov.iov_base = &data;
1166     iov.iov_len = sizeof(int);
1167     data = 12345;
1169     /* Set \(aqmsghdr\(aq fields that describe ancillary data */
1171     msgh.msg_control = controlMsg.buf;
1172     msgh.msg_controllen = sizeof(controlMsg.buf);
1174     /* Set up ancillary data describing file descriptor to send */
1176     cmsgp = CMSG_FIRSTHDR(&msgh);
1177     cmsgp\->cmsg_level = SOL_SOCKET;
1178     cmsgp\->cmsg_type = SCM_RIGHTS;
1179     cmsgp\->cmsg_len = CMSG_LEN(sizeof(int));
1180     memcpy(CMSG_DATA(cmsgp), &fd, sizeof(int));
1182     /* Send real plus ancillary data */
1184     if (sendmsg(sockfd, &msgh, 0) == \-1)
1185         return \-1;
1187     return 0;
1190 /* Receive a file descriptor on a connected UNIX domain socket. Returns
1191    the received file descriptor on success, or \-1 on error. */
1193 static int
1194 recvfd(int sockfd)
1196     struct msghdr msgh;
1197     struct iovec iov;
1198     int data, fd;
1199     ssize_t nr;
1201     /* Allocate a char buffer for the ancillary data. See the comments
1202        in sendfd() */
1203     union {
1204         char   buf[CMSG_SPACE(sizeof(int))];
1205         struct cmsghdr align;
1206     } controlMsg;
1207     struct cmsghdr *cmsgp;
1209     /* The \(aqmsg_name\(aq field can be used to obtain the address of the
1210        sending socket. However, we do not need this information. */
1212     msgh.msg_name = NULL;
1213     msgh.msg_namelen = 0;
1215     /* Specify buffer for receiving real data */
1217     msgh.msg_iov = &iov;
1218     msgh.msg_iovlen = 1;
1219     iov.iov_base = &data;       /* Real data is an \(aqint\(aq */
1220     iov.iov_len = sizeof(int);
1222     /* Set \(aqmsghdr\(aq fields that describe ancillary data */
1224     msgh.msg_control = controlMsg.buf;
1225     msgh.msg_controllen = sizeof(controlMsg.buf);
1227     /* Receive real plus ancillary data; real data is ignored */
1229     nr = recvmsg(sockfd, &msgh, 0);
1230     if (nr == \-1)
1231         return \-1;
1233     cmsgp = CMSG_FIRSTHDR(&msgh);
1235     /* Check the validity of the \(aqcmsghdr\(aq */
1237     if (cmsgp == NULL ||
1238             cmsgp\->cmsg_len != CMSG_LEN(sizeof(int)) ||
1239             cmsgp\->cmsg_level != SOL_SOCKET ||
1240             cmsgp\->cmsg_type != SCM_RIGHTS) {
1241         errno = EINVAL;
1242         return \-1;
1243     }
1245     /* Return the received file descriptor to our caller */
1247     memcpy(&fd, CMSG_DATA(cmsgp), sizeof(int));
1248     return fd;
1251 static void
1252 sigchldHandler(int sig)
1254     char msg[] = "\etS: target has terminated; bye\en";
1256     write(STDOUT_FILENO, msg, sizeof(msg) - 1);
1257     _exit(EXIT_SUCCESS);
1260 static int
1261 seccomp(unsigned int operation, unsigned int flags, void *args)
1263     return syscall(__NR_seccomp, operation, flags, args);
1266 /* The following is the x86\-64\-specific BPF boilerplate code for checking
1267    that the BPF program is running on the right architecture + ABI. At
1268    completion of these instructions, the accumulator contains the system
1269    call number. */
1271 /* For the x32 ABI, all system call numbers have bit 30 set */
1273 #define X32_SYSCALL_BIT         0x40000000
1275 #define X86_64_CHECK_ARCH_AND_LOAD_SYSCALL_NR \e
1276         BPF_STMT(BPF_LD | BPF_W | BPF_ABS, \e
1277                 (offsetof(struct seccomp_data, arch))), \e
1278         BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 2), \e
1279         BPF_STMT(BPF_LD | BPF_W | BPF_ABS, \e
1280                  (offsetof(struct seccomp_data, nr))), \e
1281         BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, X32_SYSCALL_BIT, 0, 1), \e
1282         BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS)
1284 /* installNotifyFilter() installs a seccomp filter that generates
1285    user\-space notifications (SECCOMP_RET_USER_NOTIF) when the process
1286    calls mkdir(2); the filter allows all other system calls.
1288    The function return value is a file descriptor from which the
1289    user\-space notifications can be fetched. */
1291 static int
1292 installNotifyFilter(void)
1294     struct sock_filter filter[] = {
1295         X86_64_CHECK_ARCH_AND_LOAD_SYSCALL_NR,
1297         /* mkdir() triggers notification to user\-space supervisor */
1299         BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mkdir, 0, 1),
1300         BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_USER_NOTIF),
1302         /* Every other system call is allowed */
1304         BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
1305     };
1307     struct sock_fprog prog = {
1308         .len = sizeof(filter) / sizeof(filter[0]),
1309         .filter = filter,
1310     };
1312     /* Install the filter with the SECCOMP_FILTER_FLAG_NEW_LISTENER flag;
1313        as a result, seccomp() returns a notification file descriptor. */
1315     int notifyFd = seccomp(SECCOMP_SET_MODE_FILTER,
1316                            SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
1317     if (notifyFd == \-1)
1318         errExit("seccomp\-install\-notify\-filter");
1320     return notifyFd;
1323 /* Close a pair of sockets created by socketpair() */
1325 static void
1326 closeSocketPair(int sockPair[2])
1328     if (close(sockPair[0]) == \-1)
1329         errExit("closeSocketPair\-close\-0");
1330     if (close(sockPair[1]) == \-1)
1331         errExit("closeSocketPair\-close\-1");
1334 /* Implementation of the target process; create a child process that:
1336    (1) installs a seccomp filter with the
1337        SECCOMP_FILTER_FLAG_NEW_LISTENER flag;
1338    (2) writes the seccomp notification file descriptor returned from
1339        the previous step onto the UNIX domain socket, \(aqsockPair[0]\(aq;
1340    (3) calls mkdir(2) for each element of \(aqargv\(aq.
1342    The function return value in the parent is the PID of the child
1343    process; the child does not return from this function. */
1345 static pid_t
1346 targetProcess(int sockPair[2], char *argv[])
1348     pid_t targetPid = fork();
1349     if (targetPid == \-1)
1350         errExit("fork");
1352     if (targetPid > 0)          /* In parent, return PID of child */
1353         return targetPid;
1355     /* Child falls through to here */
1357     printf("T: PID = %ld\en", (long) getpid());
1359     /* Install seccomp filter(s) */
1361     if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
1362         errExit("prctl");
1364     int notifyFd = installNotifyFilter();
1366     /* Pass the notification file descriptor to the tracing process over
1367        a UNIX domain socket */
1369     if (sendfd(sockPair[0], notifyFd) == \-1)
1370         errExit("sendfd");
1372     /* Notification and socket FDs are no longer needed in target */
1374     if (close(notifyFd) == \-1)
1375         errExit("close\-target\-notify\-fd");
1377     closeSocketPair(sockPair);
1379     /* Perform a mkdir() call for each of the command\-line arguments */
1381     for (char **ap = argv; *ap != NULL; ap++) {
1382         printf("\enT: about to mkdir(\e"%s\e")\en", *ap);
1384         int s = mkdir(*ap, 0700);
1385         if (s == \-1)
1386             perror("T: ERROR: mkdir(2)");
1387         else
1388             printf("T: SUCCESS: mkdir(2) returned %d\en", s);
1389     }
1391     printf("\enT: terminating\en");
1392     exit(EXIT_SUCCESS);
1395 /* Check that the notification ID provided by a SECCOMP_IOCTL_NOTIF_RECV
1396    operation is still valid. It will no longer be valid if the target
1397    process has terminated or is no longer blocked in the system call that
1398    generated the notification (because it was interrupted by a signal).
1400    This operation can be used when doing such things as accessing
1401    /proc/PID files in the target process in order to avoid TOCTOU race
1402    conditions where the PID that is returned by SECCOMP_IOCTL_NOTIF_RECV
1403    terminates and is reused by another process. */
1405 static bool
1406 notificationIdIsValid(int notifyFd, uint64_t id)
1408     if (ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) == \-1) {
1409         perror("\etS: notification ID check failed!!!\en");
1410         return false;
1411     }
1413     return true;
1416 /* Access the memory of the target process in order to fetch the
1417    pathname referred to by the system call argument \(aqargNum\(aq in
1418    \(aqreq\->data.args[]\(aq.  The pathname is returned in \(aqpath\(aq,
1419    a buffer of \(aqlen\(aq bytes allocated by the caller.
1421    Returns true if the fetched pathname is correctly formed
1422    (i.e., has a terminating null byte) and the notification ID
1423    is still valid, and false otherwise. */
1425 static bool
1426 getTargetPathname(struct seccomp_notif *req, int notifyFd,
1427                   int argNum, char *path, size_t len)
1429     char procMemPath[PATH_MAX];
1431     snprintf(procMemPath, sizeof(procMemPath), "/proc/%d/mem", req\->pid);
1433     int procMemFd = open(procMemPath, O_RDONLY | O_CLOEXEC);
1434     if (procMemFd == \-1)
1435         errExit("Supervisor: open");
1437     /* Check that the process whose info we are accessing is still alive
1438        and blocked in the system call that caused the notification.
1439        If the SECCOMP_IOCTL_NOTIF_ID_VALID operation (performed in
1440        notificationIdIsValid()) succeeded, we know that the /proc/PID/mem
1441        file descriptor that we opened corresponded to the process for
1442        which we received a notification. If that process subsequently
1443        terminates, then read() on that file descriptor will return
1444        0 (EOF). */
1446     if (!notificationIdIsValid(notifyFd, req\->id))
1447         return false;
1449     /* Read bytes at the location containing the pathname argument */
1451     ssize_t nread = pread(procMemFd, path, len, req\->data.args[argNum]);
1452     if (nread == \-1)
1453         errExit("Supervisor: pread");
1455     if (nread == 0) {
1456         fprintf(stderr, "\etS: pread() of /proc/PID/mem "
1457                 "returned 0 (EOF)\en");
1458         exit(EXIT_FAILURE);
1459     }
1461     if (close(procMemFd) == \-1)
1462         errExit("Supervisor: close\-/proc/PID/mem");
1464     /* Once again check that the notification ID is still valid. The
1465        case we are particularly concerned about here is that just
1466        before we fetched the pathname, the target\(aqs blocked system
1467        call was interrupted by a signal handler, and after the handler
1468        returned, the target carried on execution (past the interrupted
1469        system call). In that case, we have no guarantees about what we
1470        are reading, since the target\(aqs memory may have been arbitrarily
1471        changed by subsequent operations. */
1473     if (!notificationIdIsValid(notifyFd, req\->id))
1474         return false;
1476     /* Even if the target\(aqs system call was not interrupted by a signal,
1477        we have no guarantees about what was in the memory of the target
1478        process. (The memory may have been modified by another thread, or
1479        even by an external attacking process.) We therefore treat the
1480        buffer returned by pread() as untrusted input. The buffer should
1481        be terminated by a null byte; if not, then we will trigger an
1482        error for the target process. */
1484     if (strnlen(path, nread) < nread)
1485         return true;
1487     return false;
1490 /* Handle notifications that arrive via the SECCOMP_RET_USER_NOTIF file
1491    descriptor, \(aqnotifyFd\(aq. */
1493 static void
1494 handleNotifications(int notifyFd)
1496     struct seccomp_notif_sizes sizes;
1497     char path[PATH_MAX];
1499     /* Discover the sizes of the structures that are used to receive
1500        notifications and send notification responses, and allocate
1501        buffers of those sizes. */
1503     if (seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes) == \-1)
1504         errExit("\etS: seccomp\-SECCOMP_GET_NOTIF_SIZES");
1506     struct seccomp_notif *req = malloc(sizes.seccomp_notif);
1507     if (req == NULL)
1508         errExit("\etS: malloc");
1510     /* When allocating the response buffer, we must allow for the fact
1511        that the user\-space binary may have been built with user\-space
1512        headers where \(aqstruct seccomp_notif_resp\(aq is bigger than the
1513        response buffer expected by the (older) kernel. Therefore, we
1514        allocate a buffer that is the maximum of the two sizes. This
1515        ensures that if the supervisor places bytes into the response
1516        structure that are past the response size that the kernel expects,
1517        then the supervisor is not touching an invalid memory location. */
1519     size_t resp_size = sizes.seccomp_notif_resp;
1520     if (sizeof(struct seccomp_notif_resp) > resp_size)
1521         resp_size = sizeof(struct seccomp_notif_resp);
1523     struct seccomp_notif_resp *resp = malloc(resp_size);
1524     if (resp == NULL)
1525         errExit("\etS: malloc");
1527     /* Loop handling notifications */
1529     for (;;) {
1530         /* Wait for next notification, returning info in \(aq*req\(aq */
1532         memset(req, 0, sizes.seccomp_notif);
1533         if (ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_RECV, req) == \-1) {
1534             if (errno == EINTR)
1535                 continue;
1536             errExit("\etS: ioctl\-SECCOMP_IOCTL_NOTIF_RECV");
1537         }
1539         printf("\etS: got notification (ID %#llx) for PID %d\en",
1540                 req\->id, req\->pid);
1542         /* The only system call that can generate a notification event
1543            is mkdir(2). Nevertheless, we check that the notified system
1544            call is indeed mkdir() as kind of future\-proofing of this
1545            code in case the seccomp filter is later modified to
1546            generate notifications for other system calls. */
1548         if (req\->data.nr != __NR_mkdir) {
1549             printf("\etS: notification contained unexpected "
1550                     "system call number; bye!!!\en");
1551             exit(EXIT_FAILURE);
1552         }
1554         bool pathOK = getTargetPathname(req, notifyFd, 0, path,
1555                                         sizeof(path));
1557         /* Prepopulate some fields of the response */
1559         resp\->id = req\->id;     /* Response includes notification ID */
1560         resp\->flags = 0;
1561         resp\->val = 0;
1563         /* If getTargetPathname() failed, trigger an EINVAL error
1564            response (sending this response may yield an error if the
1565            failure occurred because the notification ID was no longer
1566            valid); if the directory is in /tmp, then create it on behalf
1567            of the supervisor; if the pathname starts with \(aq.\(aq, tell the
1568            kernel to let the target process execute the mkdir();
1569            otherwise, give an error for a directory pathname in any other
1570            location. */
1572         if (!pathOK) {
1573             resp->error = -EINVAL;
1574             printf("\etS: spoofing error for invalid pathname (%s)\en",
1575                     strerror(-resp->error));
1576         } else if (strncmp(path, "/tmp/", strlen("/tmp/")) == 0) {
1577             printf("\etS: executing: mkdir(\e"%s\e", %#llo)\en",
1578                     path, req\->data.args[1]);
1580             if (mkdir(path, req\->data.args[1]) == 0) {
1581                 resp\->error = 0;            /* "Success" */
1582                 resp\->val = strlen(path);   /* Used as return value of
1583                                                mkdir() in target */
1584                 printf("\etS: success! spoofed return = %lld\en",
1585                         resp\->val);
1586             } else {
1588                 /* If mkdir() failed in the supervisor, pass the error
1589                    back to the target */
1591                 resp\->error = \-errno;
1592                 printf("\etS: failure! (errno = %d; %s)\en", errno,
1593                         strerror(errno));
1594             }
1595         } else if (strncmp(path, "./", strlen("./")) == 0) {
1596             resp\->error = resp\->val = 0;
1597             resp\->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
1598             printf("\etS: target can execute system call\en");
1599         } else {
1600             resp\->error = \-EOPNOTSUPP;
1601             printf("\etS: spoofing error response (%s)\en",
1602                     strerror(\-resp\->error));
1603         }
1605         /* Send a response to the notification */
1607         printf("\etS: sending response "
1608                 "(flags = %#x; val = %lld; error = %d)\en",
1609                 resp\->flags, resp\->val, resp\->error);
1611         if (ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_SEND, resp) == \-1) {
1612             if (errno == ENOENT)
1613                 printf("\etS: response failed with ENOENT; "
1614                         "perhaps target process\(aqs syscall was "
1615                         "interrupted by a signal?\en");
1616             else
1617                 perror("ioctl\-SECCOMP_IOCTL_NOTIF_SEND");
1618         }
1620         /* If the pathname is just "/bye", then the supervisor
1621            terminates. This allows us to see what happens if the
1622            target process makes further calls to mkdir(2). */
1624         if (strcmp(path, "/bye") == 0) {
1625             printf("\etS: terminating **********\en");
1626             exit(EXIT_FAILURE);
1627         }
1628     }
1631 /* Implementation of the supervisor process:
1633    (1) obtains the notification file descriptor from \(aqsockPair[1]\(aq
1634    (2) handles notifications that arrive on that file descriptor. */
1636 static void
1637 supervisor(int sockPair[2])
1639     int notifyFd = recvfd(sockPair[1]);
1640     if (notifyFd == \-1)
1641         errExit("recvfd");
1643     closeSocketPair(sockPair);  /* We no longer need the socket pair */
1645     handleNotifications(notifyFd);
1649 main(int argc, char *argv[])
1651     int sockPair[2];
1653     setbuf(stdout, NULL);
1655     if (argc < 2) {
1656         fprintf(stderr, "At least one pathname argument is required\en");
1657         exit(EXIT_FAILURE);
1658     }
1660     /* Create a UNIX domain socket that is used to pass the seccomp
1661        notification file descriptor from the target process to the
1662        supervisor process. */
1664     if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockPair) == \-1)
1665         errExit("socketpair");
1667     /* Create a child process\-\-the "target"\-\-that installs seccomp
1668        filtering. The target process writes the seccomp notification
1669        file descriptor onto \(aqsockPair[0]\(aq and then calls mkdir(2) for
1670        each directory in the command\-line arguments. */
1672     (void) targetProcess(sockPair, &argv[optind]);
1674     /* Catch SIGCHLD when the target terminates, so that the
1675        supervisor can also terminate. */
1677     struct sigaction sa;
1678     sa.sa_handler = sigchldHandler;
1679     sa.sa_flags = 0;
1680     sigemptyset(&sa.sa_mask);
1681     if (sigaction(SIGCHLD, &sa, NULL) == \-1)
1682         errExit("sigaction");
1684     supervisor(sockPair);
1686     exit(EXIT_SUCCESS);
1689 .SH SEE ALSO
1690 .BR ioctl (2),
1691 .BR pidfd_open (2),
1692 .BR pidfd_getfd (2),
1693 .BR seccomp (2)
1695 A further example program can be found in the kernel source file
1696 .IR samples/seccomp/user-trap.c .