1seccomp_unotify(2)            System Calls Manual           seccomp_unotify(2)
2
3
4

NAME

6       seccomp_unotify - Seccomp user-space notification mechanism
7

LIBRARY

9       Standard C library (libc, -lc)
10

SYNOPSIS

12       #include <linux/seccomp.h>
13       #include <linux/filter.h>
14       #include <linux/audit.h>
15
16       int seccomp(unsigned int operation, unsigned int flags, void *args);
17
18       #include <sys/ioctl.h>
19
20       int ioctl(int fd, SECCOMP_IOCTL_NOTIF_RECV,
21                 struct seccomp_notif *req);
22       int ioctl(int fd, SECCOMP_IOCTL_NOTIF_SEND,
23                 struct seccomp_notif_resp *resp);
24       int ioctl(int fd, SECCOMP_IOCTL_NOTIF_ID_VALID, __u64 *id);
25       int ioctl(int fd, SECCOMP_IOCTL_NOTIF_ADDFD,
26                 struct seccomp_notif_addfd *addfd);
27

DESCRIPTION

29       This  page  describes the user-space notification mechanism provided by
30       the Secure Computing (seccomp) facility.  As well as  the  use  of  the
31       SECCOMP_FILTER_FLAG_NEW_LISTENER  flag,  the SECCOMP_RET_USER_NOTIF ac‐
32       tion value, and the SECCOMP_GET_NOTIF_SIZES operation described in sec‐
33       comp(2),  this  mechanism  involves  the  use  of  a  number of related
34       ioctl(2) operations (described below).
35
36   Overview
37       In conventional usage of a seccomp filter, the decision  about  how  to
38       treat  a  system  call  is made by the filter itself.  By contrast, the
39       user-space notification mechanism allows the seccomp filter to delegate
40       the  handling  of  the system call to another user-space process.  Note
41       that this mechanism is explicitly not intended as a method implementing
42       security policy; see NOTES.
43
44       In the discussion that follows, the thread(s) on which the seccomp fil‐
45       ter is installed is (are) referred to as the target,  and  the  process
46       that  is  notified by the user-space notification mechanism is referred
47       to as the supervisor.
48
49       A suitably privileged supervisor can use  the  user-space  notification
50       mechanism to perform actions on behalf of the target.  The advantage of
51       the user-space notification mechanism is that the supervisor will  usu‐
52       ally be able to retrieve information about the target and the performed
53       system call that the seccomp filter itself cannot.  (A  seccomp  filter
54       is limited in the information it can obtain and the actions that it can
55       perform because it is running on a virtual machine inside the kernel.)
56
57       An overview of the steps performed by the target and the supervisor  is
58       as follows:
59
60       (1)  The  target  establishes a seccomp filter in the usual manner, but
61            with two differences:
62
63            •  The seccomp(2) flags argument includes  the  flag  SECCOMP_FIL‐
64               TER_FLAG_NEW_LISTENER.   Consequently,  the return value of the
65               (successful) seccomp(2) call is a new "listening" file descrip‐
66               tor  that can be used to receive notifications.  Only one "lis‐
67               tening" seccomp filter can be installed for a thread.
68
69            •  In cases where it is appropriate, the  seccomp  filter  returns
70               the  action  value  SECCOMP_RET_USER_NOTIF.   This return value
71               will trigger a notification event.
72
73       (2)  In order that the supervisor can obtain  notifications  using  the
74            listening  file  descriptor, (a duplicate of) that file descriptor
75            must be passed from the target to  the  supervisor.   One  way  in
76            which  this could be done is by passing the file descriptor over a
77            UNIX domain socket connection between the target and the  supervi‐
78            sor  (using  the  SCM_RIGHTS  ancillary  message type described in
79            unix(7)).   Another  way  to  do  this  is  through  the  use   of
80            pidfd_getfd(2).
81
82       (3)  The  supervisor  will receive notification events on the listening
83            file descriptor.  These events are returned as structures of  type
84            seccomp_notif.   Because  this  structure  and its size may evolve
85            over kernel versions, the supervisor must first determine the size
86            of this structure using the seccomp(2) SECCOMP_GET_NOTIF_SIZES op‐
87            eration, which returns a structure  of  type  seccomp_notif_sizes.
88            The supervisor allocates a buffer of size seccomp_notif_sizes.sec‐
89            comp_notif bytes to receive notification events.  In  addition,the
90            supervisor   allocates   another   buffer   of   size  seccomp_no‐
91            tif_sizes.seccomp_notif_resp bytes for the response (a struct sec‐
92            comp_notif_resp structure) that it will provide to the kernel (and
93            thus the target).
94
95       (4)  The target then performs its workload, which includes system calls
96            that  will  be  controlled by the seccomp filter.  Whenever one of
97            these  system  calls  causes  the  filter  to  return   the   SEC‐
98            COMP_RET_USER_NOTIF  action  value, the kernel does not (yet) exe‐
99            cute the system call; instead, execution of the target  is  tempo‐
100            rarily  blocked inside the kernel (in a sleep state that is inter‐
101            ruptible by signals) and a notification event is generated on  the
102            listening file descriptor.
103
104       (5)  The  supervisor  can now repeatedly monitor the listening file de‐
105            scriptor for SECCOMP_RET_USER_NOTIF-triggered events.  To do this,
106            the  supervisor  uses the SECCOMP_IOCTL_NOTIF_RECV ioctl(2) opera‐
107            tion to read information about a notification event;  this  opera‐
108            tion  blocks until an event is available.  The operation returns a
109            seccomp_notif structure containing information  about  the  system
110            call  that  is  being  attempted  by the target.  (As described in
111            NOTES, the file descriptor can also be monitored  with  select(2),
112            poll(2), or epoll(7).)
113
114       (6)  The  seccomp_notif  structure  returned  by  the SECCOMP_IOCTL_NO‐
115            TIF_RECV operation includes the same information  (a  seccomp_data
116            structure)  that  was passed to the seccomp filter.  This informa‐
117            tion allows the supervisor to discover the system call number  and
118            the  arguments for the target's system call.  In addition, the no‐
119            tification event contains the ID of the thread that triggered  the
120            notification  and a unique cookie value that is used in subsequent
121            SECCOMP_IOCTL_NOTIF_ID_VALID and  SECCOMP_IOCTL_NOTIF_SEND  opera‐
122            tions.
123
124            The  information  in  the notification can be used to discover the
125            values of pointer arguments for the target's system  call.   (This
126            is  something  that  can't  be done from within a seccomp filter.)
127            One way in which the supervisor can do this is to open the  corre‐
128            sponding  /proc/tid/mem file (see proc(5)) and read bytes from the
129            location that corresponds to one of the  pointer  arguments  whose
130            value is supplied in the notification event.  (The supervisor must
131            be careful to avoid a race condition that  can  occur  when  doing
132            this;  see  the  description  of  the SECCOMP_IOCTL_NOTIF_ID_VALID
133            ioctl(2) operation below.)  In addition, the supervisor can access
134            other  system  information that is visible in user space but which
135            is not accessible from a seccomp filter.
136
137       (7)  Having obtained information as per the previous step, the supervi‐
138            sor  may  then choose to perform an action in response to the tar‐
139            get's system call (which, as noted above, is not executed when the
140            seccomp filter returns the SECCOMP_RET_USER_NOTIF action value).
141
142            One  example  use case here relates to containers.  The target may
143            be located inside a container where it does  not  have  sufficient
144            capabilities  to mount a filesystem in the container's mount name‐
145            space.  However, the supervisor may be a more  privileged  process
146            that does have sufficient capabilities to perform the mount opera‐
147            tion.
148
149       (8)  The supervisor then sends a response to the notification.  The in‐
150            formation  in  this  response is used by the kernel to construct a
151            return value for the target's system call and provide a value that
152            will be assigned to the errno variable of the target.
153
154            The  response  is sent using the SECCOMP_IOCTL_NOTIF_SEND ioctl(2)
155            operation, which is used to transmit a  seccomp_notif_resp  struc‐
156            ture  to  the kernel.  This structure includes a cookie value that
157            the supervisor obtained in the seccomp_notif structure returned by
158            the  SECCOMP_IOCTL_NOTIF_RECV operation.  This cookie value allows
159            the kernel to associate the response with the target.  This struc‐
160            ture must include the cookie value that the supervisor obtained in
161            the seccomp_notif  structure  returned  by  the  SECCOMP_IOCTL_NO‐
162            TIF_RECV  operation; the cookie allows the kernel to associate the
163            response with the target.
164
165       (9)  Once the notification has been sent, the system call in the target
166            thread  unblocks,  returning  the information that was provided by
167            the supervisor in the notification response.
168
169       As a variation on the last two steps, the supervisor  can  send  a  re‐
170       sponse that tells the kernel that it should execute the target thread's
171       system call; see the  discussion  of  SECCOMP_USER_NOTIF_FLAG_CONTINUE,
172       below.
173

IOCTL OPERATIONS

175       The  following  ioctl(2)  operations are supported by the seccomp user-
176       space notification file descriptor.  For each of these operations,  the
177       first  (file descriptor) argument of ioctl(2) is the listening file de‐
178       scriptor returned  by  a  call  to  seccomp(2)  with  the  SECCOMP_FIL‐
179       TER_FLAG_NEW_LISTENER flag.
180
181   SECCOMP_IOCTL_NOTIF_RECV
182       The  SECCOMP_IOCTL_NOTIF_RECV  operation (available since Linux 5.0) is
183       used to obtain a user-space notification event.  If no  such  event  is
184       currently  pending,  the  operation  blocks until an event occurs.  The
185       third ioctl(2) argument is a pointer to a structure  of  the  following
186       form  which  contains information about the event.  This structure must
187       be zeroed out before the call.
188
189           struct seccomp_notif {
190               __u64  id;              /* Cookie */
191               __u32  pid;             /* TID of target thread */
192               __u32  flags;           /* Currently unused (0) */
193               struct seccomp_data data;   /* See seccomp(2) */
194           };
195
196       The fields in this structure are as follows:
197
198       id     This is a cookie for the  notification.   Each  such  cookie  is
199              guaranteed to be unique for the corresponding seccomp filter.
200
201              •  The  cookie can be used with the SECCOMP_IOCTL_NOTIF_ID_VALID
202                 ioctl(2) operation described below.
203
204              •  When returning a notification response to the kernel, the su‐
205                 pervisor  must  include  the  cookie value in the seccomp_no‐
206                 tif_resp structure that is specified as the argument  of  the
207                 SECCOMP_IOCTL_NOTIF_SEND operation.
208
209       pid    This  is  the  thread ID of the target thread that triggered the
210              notification event.
211
212       flags  This is a bit mask of flags providing further information on the
213              event.   In  the  current  implementation,  this field is always
214              zero.
215
216       data   This is a seccomp_data structure  containing  information  about
217              the  system  call  that triggered the notification.  This is the
218              same structure that is passed to the seccomp filter.   See  sec‐
219              comp(2) for details of this structure.
220
221       On  success,  this operation returns 0; on failure, -1 is returned, and
222       errno is set to indicate the cause of the error.   This  operation  can
223       fail with the following errors:
224
225       EINVAL (since Linux 5.5)
226              The  seccomp_notif  structure  that  was passed to the call con‐
227              tained nonzero fields.
228
229       ENOENT The target thread was killed by a signal as the notification in‐
230              formation  was being generated, or the target's (blocked) system
231              call was interrupted by a signal handler.
232
233   SECCOMP_IOCTL_NOTIF_ID_VALID
234       The SECCOMP_IOCTL_NOTIF_ID_VALID operation (available since Linux  5.0)
235       is  used  to  check  that a notification ID returned by an earlier SEC‐
236       COMP_IOCTL_NOTIF_RECV operation is still valid (i.e., that  the  target
237       still  exists  and  its  system call is still blocked waiting for a re‐
238       sponse).
239
240       The third ioctl(2) argument is a pointer to the cookie (id) returned by
241       the SECCOMP_IOCTL_NOTIF_RECV operation.
242
243       This  operation  is  necessary  to avoid race conditions that can occur
244       when the pid returned by the SECCOMP_IOCTL_NOTIF_RECV operation  termi‐
245       nates, and that process ID is reused by another process.  An example of
246       this kind of race is the following
247
248       (1)  A notification is generated on the listening file descriptor.  The
249            returned  seccomp_notif  contains the TID of the target thread (in
250            the pid field of the structure).
251
252       (2)  The target terminates.
253
254       (3)  Another thread or process is created on the system that by  chance
255            reuses the TID that was freed when the target terminated.
256
257       (4)  The  supervisor  open(2)s  the  /proc/tid/mem file for the TID ob‐
258            tained in step 1, with the intention of (say) inspecting the  mem‐
259            ory location(s) that containing the argument(s) of the system call
260            that triggered the notification in step 1.
261
262       In the above scenario, the risk is that the supervisor may try  to  ac‐
263       cess  the  memory of a process other than the target.  This race can be
264       avoided by following the  call  to  open(2)  with  a  SECCOMP_IOCTL_NO‐
265       TIF_ID_VALID  operation  to  verify that the process that generated the
266       notification is still alive.  (Note that if the target terminates after
267       the  latter step, a subsequent read(2) from the file descriptor may re‐
268       turn 0, indicating end of file.)
269
270       See NOTES for a  discussion  of  other  cases  where  SECCOMP_IOCTL_NO‐
271       TIF_ID_VALID checks must be performed.
272
273       On  success  (i.e., the notification ID is still valid), this operation
274       returns 0.  On failure (i.e., the notification ID is no longer  valid),
275       -1 is returned, and errno is set to ENOENT.
276
277   SECCOMP_IOCTL_NOTIF_SEND
278       The  SECCOMP_IOCTL_NOTIF_SEND  operation (available since Linux 5.0) is
279       used to send a notification response back to  the  kernel.   The  third
280       ioctl(2)  argument of this structure is a pointer to a structure of the
281       following form:
282
283           struct seccomp_notif_resp {
284               __u64 id;           /* Cookie value */
285               __s64 val;          /* Success return value */
286               __s32 error;        /* 0 (success) or negative error number */
287               __u32 flags;        /* See below */
288           };
289
290       The fields of this structure are as follows:
291
292       id     This is the cookie  value  that  was  obtained  using  the  SEC‐
293              COMP_IOCTL_NOTIF_RECV  operation.   This cookie value allows the
294              kernel to correctly associate this response with the system call
295              that triggered the user-space notification.
296
297       val    This is the value that will be used for a spoofed success return
298              for the target's system call; see below.
299
300       error  This is the value that will be used as the error number  (errno)
301              for a spoofed error return for the target's system call; see be‐
302              low.
303
304       flags  This is a bit mask that includes zero or more of  the  following
305              flags:
306
307              SECCOMP_USER_NOTIF_FLAG_CONTINUE (since Linux 5.5)
308                     Tell the kernel to execute the target's system call.
309
310       Two kinds of response are possible:
311
312       •  A  response  to the kernel telling it to execute the target's system
313          call.  In this  case,  the  flags  field  includes  SECCOMP_USER_NO‐
314          TIF_FLAG_CONTINUE and the error and val fields must be zero.
315
316          This  kind  of  response can be useful in cases where the supervisor
317          needs to do deeper analysis of the target's system call than is pos‐
318          sible  from  a seccomp filter (e.g., examining the values of pointer
319          arguments), and, having decided that the system call  does  not  re‐
320          quire  emulation  by the supervisor, the supervisor wants the system
321          call to be executed normally in the target.
322
323          The SECCOMP_USER_NOTIF_FLAG_CONTINUE flag should be used  with  cau‐
324          tion; see NOTES.
325
326       •  A  spoofed return value for the target's system call.  In this case,
327          the kernel does not execute the target's system call, instead  caus‐
328          ing the system call to return a spoofed value as specified by fields
329          of the seccomp_notif_resp structure.  The supervisor should set  the
330          fields of this structure as follows:
331
332          +  flags does not contain SECCOMP_USER_NOTIF_FLAG_CONTINUE.
333
334          +  error  is  set either to 0 for a spoofed "success" return or to a
335             negative error number for a spoofed  "failure"  return.   In  the
336             former case, the kernel causes the target's system call to return
337             the value specified in the val field.  In the  latter  case,  the
338             kernel causes the target's system call to return -1, and errno is
339             assigned the negated error value.
340
341          +  val is set to a value that will be used as the return value for a
342             spoofed "success" return for the target's system call.  The value
343             in this field is ignored if the error field  contains  a  nonzero
344             value.
345
346       On  success,  this operation returns 0; on failure, -1 is returned, and
347       errno is set to indicate the cause of the error.   This  operation  can
348       fail with the following errors:
349
350       EINPROGRESS
351              A response to this notification has already been sent.
352
353       EINVAL An invalid value was specified in the flags field.
354
355       EINVAL The  flags field contained SECCOMP_USER_NOTIF_FLAG_CONTINUE, and
356              the error or val field was not zero.
357
358       ENOENT The blocked system call in the target has been interrupted by  a
359              signal handler or the target has terminated.
360
361   SECCOMP_IOCTL_NOTIF_ADDFD
362       The SECCOMP_IOCTL_NOTIF_ADDFD operation (available since Linux 5.9) al‐
363       lows the supervisor to install a file descriptor into the target's file
364       descriptor  table.   Much like the use of SCM_RIGHTS messages described
365       in unix(7), this operation is semantically equivalent to duplicating  a
366       file  descriptor  from  the supervisor's file descriptor table into the
367       target's file descriptor table.
368
369       The SECCOMP_IOCTL_NOTIF_ADDFD operation permits the supervisor to  emu‐
370       late  a target system call (such as socket(2) or openat(2)) that gener‐
371       ates a file descriptor.  The supervisor can  perform  the  system  call
372       that  generates  the file descriptor (and associated open file descrip‐
373       tion) and then use this operation to allocate a  file  descriptor  that
374       refers to the same open file description in the target.  (For an expla‐
375       nation of open file descriptions, see open(2).)
376
377       Once this operation has been performed, the supervisor  can  close  its
378       copy of the file descriptor.
379
380       In  the  target,  the  received  file descriptor is subject to the same
381       Linux Security Module (LSM) checks as are applied to a file  descriptor
382       that  is  received in an SCM_RIGHTS ancillary message.  If the file de‐
383       scriptor refers to a socket, it inherits the cgroup version  1  network
384       controller settings (classid and netprioidx) of the target.
385
386       The  third ioctl(2) argument is a pointer to a structure of the follow‐
387       ing form:
388
389           struct seccomp_notif_addfd {
390               __u64 id;           /* Cookie value */
391               __u32 flags;        /* Flags */
392               __u32 srcfd;        /* Local file descriptor number */
393               __u32 newfd;        /* 0 or desired file descriptor
394                                      number in target */
395               __u32 newfd_flags;  /* Flags to set on target file
396                                      descriptor */
397           };
398
399       The fields in this structure are as follows:
400
401       id     This field should be set to the notification ID  (cookie  value)
402              that was obtained via SECCOMP_IOCTL_NOTIF_RECV.
403
404       flags  This  field  is  a bit mask of flags that modify the behavior of
405              the operation.  Currently, only one flag is supported:
406
407              SECCOMP_ADDFD_FLAG_SETFD
408                     When allocating the file descriptor in  the  target,  use
409                     the file descriptor number specified in the newfd field.
410
411              SECCOMP_ADDFD_FLAG_SEND (since Linux 5.14)
412                     Perform  the equivalent of SECCOMP_IOCTL_NOTIF_ADDFD plus
413                     SECCOMP_IOCTL_NOTIF_SEND as an atomic operation.  On suc‐
414                     cessful  invocation, the target process's errno will be 0
415                     and the return value will be the file  descriptor  number
416                     that was allocated in the target.  If allocating the file
417                     descriptor in the target fails, the target's system  call
418                     continues  to  be  blocked until a successful response is
419                     sent.
420
421       srcfd  This field should be set to the number of the file descriptor in
422              the supervisor that is to be duplicated.
423
424       newfd  This  field determines which file descriptor number is allocated
425              in the target.  If the  SECCOMP_ADDFD_FLAG_SETFD  flag  is  set,
426              then this field specifies which file descriptor number should be
427              allocated.  If this file descriptor number is  already  open  in
428              the target, it is atomically closed and reused.  If the descrip‐
429              tor duplication fails due to an LSM check, or if srcfd is not  a
430              valid  file  descriptor,  the  file descriptor newfd will not be
431              closed in the target process.
432
433              If the SECCOMP_ADDFD_FLAG_SETFD flag it not set, then this field
434              must  be  0, and the kernel allocates the lowest unused file de‐
435              scriptor number in the target.
436
437       newfd_flags
438              This field is a bit mask specifying flags that should be set  on
439              the  file  descriptor  that  is  received in the target process.
440              Currently, only the following flag is implemented:
441
442              O_CLOEXEC
443                     Set the close-on-exec flag on the received file  descrip‐
444                     tor.
445
446       On  success, this ioctl(2) call returns the number of the file descrip‐
447       tor that was allocated in the target.  Assuming that the emulated  sys‐
448       tem  call  is one that returns a file descriptor as its function result
449       (e.g.,  socket(2)),  this  value  can  be  used  as  the  return  value
450       (resp.val)  that  is supplied in the response that is subsequently sent
451       with the SECCOMP_IOCTL_NOTIF_SEND operation.
452
453       On error, -1 is returned and errno is set to indicate the cause of  the
454       error.
455
456       This operation can fail with the following errors:
457
458       EBADF  Allocating  the  file  descriptor  in the target would cause the
459              target's RLIMIT_NOFILE limit to be exceeded (see getrlimit(2)).
460
461       EBUSY  If the flag SECCOMP_IOCTL_NOTIF_SEND is used, this means the op‐
462              eration  can't proceed until other SECCOMP_IOCTL_NOTIF_ADDFD re‐
463              quests are processed.
464
465       EINPROGRESS
466              The user-space notification specified in the id field exists but
467              has  not yet been fetched (by a SECCOMP_IOCTL_NOTIF_RECV) or has
468              already been responded to (by a SECCOMP_IOCTL_NOTIF_SEND).
469
470       EINVAL An invalid flag was specified in the flags or newfd_flags field,
471              or  the  newfd field is nonzero and the SECCOMP_ADDFD_FLAG_SETFD
472              flag was not specified in the flags field.
473
474       EMFILE The file descriptor number specified in newfd exceeds the  limit
475              specified in /proc/sys/fs/nr_open.
476
477       ENOENT The  blocked system call in the target has been interrupted by a
478              signal handler or the target has terminated.
479
480       Here is some sample code (with error handling omitted)  that  uses  the
481       SECCOMP_ADDFD_FLAG_SETFD  operation  (here,  to  emulate a call to ope‐
482       nat(2)):
483
484           int fd, removeFd;
485
486           fd = openat(req->data.args[0], path, req->data.args[2],
487                           req->data.args[3]);
488
489           struct seccomp_notif_addfd addfd;
490           addfd.id = req->id; /* Cookie from SECCOMP_IOCTL_NOTIF_RECV */
491           addfd.srcfd = fd;
492           addfd.newfd = 0;
493           addfd.flags = 0;
494           addfd.newfd_flags = O_CLOEXEC;
495
496           targetFd = ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_ADDFD, &addfd);
497
498           close(fd);          /* No longer needed in supervisor */
499
500           struct seccomp_notif_resp *resp;
501               /* Code to allocate 'resp' omitted */
502           resp->id = req->id;
503           resp->error = 0;        /* "Success" */
504           resp->val = targetFd;
505           resp->flags = 0;
506           ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_SEND, resp);
507

NOTES

509       One example use case for the user-space notification  mechanism  is  to
510       allow  a  container  manager (a process which is typically running with
511       more privilege than the processes inside the container) to mount  block
512       devices  or  create device nodes for the container.  The mount use case
513       provides  an  example  of  where  the  SECCOMP_USER_NOTIF_FLAG_CONTINUE
514       ioctl(2)  operation  is  useful.  Upon receiving a notification for the
515       mount(2) system call, the container manager (the "supervisor") can dis‐
516       tinguish a request to mount a block filesystem (which would not be pos‐
517       sible for a "target" process inside the container) and mount that  file
518       system.   If, on the other hand, the container manager detects that the
519       operation could be performed by the process inside the container (e.g.,
520       a  mount  of  a tmpfs(5) filesystem), it can notify the kernel that the
521       target process's mount(2) system call can continue.
522
523   select()/poll()/epoll semantics
524       The file descriptor returned when seccomp(2) is employed with the  SEC‐
525       COMP_FILTER_FLAG_NEW_LISTENER  flag  can  be  monitored  using poll(2),
526       epoll(7), and select(2).  These interfaces indicate that the  file  de‐
527       scriptor is ready as follows:
528
529       •  When  a  notification is pending, these interfaces indicate that the
530          file descriptor is readable.  Following such an indication, a subse‐
531          quent  SECCOMP_IOCTL_NOTIF_RECV  ioctl(2)  will not block, returning
532          either information about a notification or else failing with the er‐
533          ror  EINTR  if  the target has been killed by a signal or its system
534          call has been interrupted by a signal handler.
535
536       •  After  the  notification  has  been  received  (i.e.,  by  the  SEC‐
537          COMP_IOCTL_NOTIF_RECV ioctl(2) operation), these interfaces indicate
538          that the file descriptor is writable, meaning  that  a  notification
539          response can be sent using the SECCOMP_IOCTL_NOTIF_SEND ioctl(2) op‐
540          eration.
541
542       •  After the last thread using  the  filter  has  terminated  and  been
543          reaped  using waitpid(2) (or similar), the file descriptor indicates
544          an end-of-file condition (readable in select(2); POLLHUP/EPOLLHUP in
545          poll(2)/ epoll_wait(2)).
546
547   Design goals; use of SECCOMP_USER_NOTIF_FLAG_CONTINUE
548       The  intent  of  the user-space notification feature is to allow system
549       calls to be performed on behalf of the  target.   The  target's  system
550       call  should either be handled by the supervisor or allowed to continue
551       normally in the kernel (where standard security policies  will  be  ap‐
552       plied).
553
554       Note  well: this mechanism must not be used to make security policy de‐
555       cisions about the system call, which would be inherently race-prone for
556       reasons described next.
557
558       The  SECCOMP_USER_NOTIF_FLAG_CONTINUE  flag  must be used with caution.
559       If set by the supervisor, the target's system call will continue.  How‐
560       ever,  there  is  a  time-of-check, time-of-use race here, since an at‐
561       tacker could exploit the interval of time where the target  is  blocked
562       waiting  on  the "continue" response to do things such as rewriting the
563       system call arguments.
564
565       Note furthermore that a user-space notifier can be bypassed if the  ex‐
566       isting  filters  allow  the  use of seccomp(2) or prctl(2) to install a
567       filter that returns an action value with a higher precedence than  SEC‐
568       COMP_RET_USER_NOTIF (see seccomp(2)).
569
570       It  should thus be absolutely clear that the seccomp user-space notifi‐
571       cation mechanism can not be used to implement a  security  policy!   It
572       should  only  ever be used in scenarios where a more privileged process
573       supervises the system calls of a lesser privileged target to get around
574       kernel-enforced  security  restrictions  when the supervisor deems this
575       safe.  In other words, in order to continue a system call, the supervi‐
576       sor should be sure that another security mechanism or the kernel itself
577       will sufficiently block the system call if its arguments are  rewritten
578       to something unsafe.
579
580   Caveats regarding the use of /proc/tid/mem
581       The  discussion  above  noted  the  need  to  use the SECCOMP_IOCTL_NO‐
582       TIF_ID_VALID ioctl(2) when opening the /proc/tid/mem file of the target
583       to  avoid  the possibility of accessing the memory of the wrong process
584       in the event that the target terminates and its ID is recycled  by  an‐
585       other  (unrelated) thread.  However, the use of this ioctl(2) operation
586       is also necessary in other situations, as explained  in  the  following
587       paragraphs.
588
589       Consider the following scenario, where the supervisor tries to read the
590       pathname argument of a target's blocked mount(2) system call:
591
592       (1)  From one of its functions (func()),  the  target  calls  mount(2),
593            which  triggers a user-space notification and causes the target to
594            block.
595
596       (2)  The supervisor receives the notification, opens /proc/tid/mem, and
597            (successfully) performs the SECCOMP_IOCTL_NOTIF_ID_VALID check.
598
599       (3)  The target receives a signal, which causes the mount(2) to abort.
600
601       (4)  The signal handler executes in the target, and returns.
602
603       (5)  Upon return from the handler, the execution of func() resumes, and
604            it returns (and perhaps other functions  are  called,  overwriting
605            the memory that had been used for the stack frame of func()).
606
607       (6)  Using  the  address  provided in the notification information, the
608            supervisor reads from the target's memory location  that  used  to
609            contain the pathname.
610
611       (7)  The  supervisor  now  calls mount(2) with some arbitrary bytes ob‐
612            tained in the previous step.
613
614       The conclusion from the above scenario  is  this:  since  the  target's
615       blocked  system call may be interrupted by a signal handler, the super‐
616       visor must be written to expect that the target may abandon its  system
617       call at any time; in such an event, any information that the supervisor
618       obtained from the target's memory must be considered invalid.
619
620       To prevent such scenarios, every read from the target's memory must  be
621       separated  from  use  of  the  bytes so obtained by a SECCOMP_IOCTL_NO‐
622       TIF_ID_VALID check.  In the above example, the check  would  be  placed
623       between  the  two  final steps.  An example of such a check is shown in
624       EXAMPLES.
625
626       Following on from the above, it should be clear that a write by the su‐
627       pervisor into the target's memory can never be considered safe.
628
629   Caveats regarding blocking system calls
630       Suppose  that  the  target  performs  a blocking system call (e.g., ac‐
631       cept(2)) that the supervisor should handle.  The supervisor might  then
632       in turn execute the same blocking system call.
633
634       In  this  scenario, it is important to note that if the target's system
635       call is now interrupted by a signal, the supervisor is not informed  of
636       this.   If the supervisor does not take suitable steps to actively dis‐
637       cover that the target's system call has been canceled,  various  diffi‐
638       culties  can  occur.   Taking  the example of accept(2), the supervisor
639       might remain blocked in its accept(2) holding a port  number  that  the
640       target  (which,  after  the interruption by the signal handler, perhaps
641       closed  its listening socket) might expect to be able  to  reuse  in  a
642       bind(2) call.
643
644       Therefore,  when  the  supervisor  wishes  to emulate a blocking system
645       call, it must do so in such a way that it gets informed if the target's
646       system  call  is  interrupted by a signal handler.  For example, if the
647       supervisor itself executes the same blocking system call, then it could
648       employ a separate thread that uses the SECCOMP_IOCTL_NOTIF_ID_VALID op‐
649       eration to check if the target is still blocked  in  its  system  call.
650       Alternatively,  in  the  accept(2)  example,  the  supervisor might use
651       poll(2) to monitor both the notification file descriptor (so as to dis‐
652       cover  when  the  target's accept(2) call has been interrupted) and the
653       listening file descriptor (so as to know when a  connection  is  avail‐
654       able).
655
656       If  the  target's  system call is interrupted, the supervisor must take
657       care to release resources (e.g., file descriptors) that it acquired  on
658       behalf of the target.
659
660   Interaction with SA_RESTART signal handlers
661       Consider the following scenario:
662
663       (1)  The  target process has used sigaction(2) to install a signal han‐
664            dler with the SA_RESTART flag.
665
666       (2)  The target has made a system call that triggered a  seccomp  user-
667            space  notification  and the target is currently blocked until the
668            supervisor sends a notification response.
669
670       (3)  A signal is delivered to the target and the signal handler is exe‐
671            cuted.
672
673       (4)  When (if) the supervisor attempts to send a notification response,
674            the SECCOMP_IOCTL_NOTIF_SEND ioctl(2)) operation  will  fail  with
675            the ENOENT error.
676
677       In  this  scenario,  the  kernel will restart the target's system call.
678       Consequently, the supervisor will receive another user-space  notifica‐
679       tion.  Thus, depending on how many times the blocked system call is in‐
680       terrupted by a signal handler, the supervisor may receive multiple  no‐
681       tifications for the same instance of a system call in the target.
682
683       One oddity is that system call restarting as described in this scenario
684       will occur even for the blocking system calls listed in signal(7)  that
685       would never normally be restarted by the SA_RESTART flag.
686
687       Furthermore, if the supervisor response is a file descriptor added with
688       SECCOMP_IOCTL_NOTIF_ADDFD, then the flag SECCOMP_ADDFD_FLAG_SEND can be
689       used  to atomically add the file descriptor and return that value, mak‐
690       ing sure no file descriptors are inadvertently leaked into the target.
691

BUGS

693       If a SECCOMP_IOCTL_NOTIF_RECV ioctl(2) operation is performed after the
694       target  terminates,  then  the ioctl(2) call simply blocks (rather than
695       returning an error to indicate that the target no longer exists).
696

EXAMPLES

698       The (somewhat contrived) program shown below demonstrates  the  use  of
699       the  interfaces  described  in  this page.  The program creates a child
700       process that serves as the "target" process.   The  child  process  in‐
701       stalls  a seccomp filter that returns the SECCOMP_RET_USER_NOTIF action
702       value if a call is made to mkdir(2).   The  child  process  then  calls
703       mkdir(2)  once for each of the supplied command-line arguments, and re‐
704       ports the result returned by the call.  After processing all arguments,
705       the child process terminates.
706
707       The  parent process acts as the supervisor, listening for the notifica‐
708       tions that are generated when the target process calls mkdir(2).   When
709       such  a  notification occurs, the supervisor examines the memory of the
710       target process (using /proc/pid/mem) to discover the pathname  argument
711       that was supplied to the mkdir(2) call, and performs one of the follow‐
712       ing actions:
713
714       •  If the pathname begins with the prefix "/tmp/", then the  supervisor
715          attempts to create the specified directory, and then spoofs a return
716          for the target process based on the return value of the supervisor's
717          mkdir(2)  call.   In  the event that that call succeeds, the spoofed
718          success return value is the length of the pathname.
719
720       •  If the pathname begins with "./" (i.e., it is a relative  pathname),
721          the  supervisor sends a SECCOMP_USER_NOTIF_FLAG_CONTINUE response to
722          the kernel  to  say  that  the  kernel  should  execute  the  target
723          process's mkdir(2) call.
724
725       •  If the pathname begins with some other prefix, the supervisor spoofs
726          an error return for the target process, so that the target process's
727          mkdir(2)  call appears to fail with the error EOPNOTSUPP ("Operation
728          not supported").  Additionally, if the specified pathname is exactly
729          "/bye", then the supervisor terminates.
730
731       This program can be used to demonstrate various aspects of the behavior
732       of the seccomp user-space notification mechanism.   To  help  aid  such
733       demonstrations, the program logs various messages to show the operation
734       of the target process (lines prefixed "T:")  and  the  supervisor  (in‐
735       dented lines prefixed "S:").
736
737       In  the  following example, the target attempts to create the directory
738       /tmp/x.  Upon receiving the notification, the  supervisor  creates  the
739       directory on the target's behalf, and spoofs a success return to be re‐
740       ceived by the target process's mkdir(2) call.
741
742           $ ./seccomp_unotify /tmp/x
743           T: PID = 23168
744
745           T: about to mkdir("/tmp/x")
746                   S: got notification (ID 0x17445c4a0f4e0e3c) for PID 23168
747                   S: executing: mkdir("/tmp/x", 0700)
748                   S: success! spoofed return = 6
749                   S: sending response (flags = 0; val = 6; error = 0)
750           T: SUCCESS: mkdir(2) returned 6
751
752           T: terminating
753                   S: target has terminated; bye
754
755       In the above output, note that the spoofed return  value  seen  by  the
756       target process is 6 (the length of the pathname /tmp/x), whereas a nor‐
757       mal mkdir(2) call returns 0 on success.
758
759       In the next example, the target attempts to create  a  directory  using
760       the relative pathname ./sub.  Since this pathname starts with "./", the
761       supervisor sends a  SECCOMP_USER_NOTIF_FLAG_CONTINUE  response  to  the
762       kernel,   and  the  kernel  then  (successfully)  executes  the  target
763       process's mkdir(2) call.
764
765           $ ./seccomp_unotify ./sub
766           T: PID = 23204
767
768           T: about to mkdir("./sub")
769                   S: got notification (ID 0xddb16abe25b4c12) for PID 23204
770                   S: target can execute system call
771                   S: sending response (flags = 0x1; val = 0; error = 0)
772           T: SUCCESS: mkdir(2) returned 0
773
774           T: terminating
775                   S: target has terminated; bye
776
777       If the target process attempts to create a directory  with  a  pathname
778       that  doesn't start with "." and doesn't begin with the prefix "/tmp/",
779       then the supervisor spoofs an error return (EOPNOTSUPP, "Operation  not
780       supported") for the target's mkdir(2) call (which is not executed):
781
782           $ ./seccomp_unotify /xxx
783           T: PID = 23178
784
785           T: about to mkdir("/xxx")
786                   S: got notification (ID 0xe7dc095d1c524e80) for PID 23178
787                   S: spoofing error response (Operation not supported)
788                   S: sending response (flags = 0; val = 0; error = -95)
789           T: ERROR: mkdir(2): Operation not supported
790
791           T: terminating
792                   S: target has terminated; bye
793
794       In  the next example, the target process attempts to create a directory
795       with the pathname /tmp/nosuchdir/b.  Upon receiving  the  notification,
796       the supervisor attempts to create that directory, but the mkdir(2) call
797       fails because the directory  /tmp/nosuchdir  does  not  exist.   Conse‐
798       quently,  the  supervisor  spoofs an error return that passes the error
799       that it received back to the target process's mkdir(2) call.
800
801           $ ./seccomp_unotify /tmp/nosuchdir/b
802           T: PID = 23199
803
804           T: about to mkdir("/tmp/nosuchdir/b")
805                   S: got notification (ID 0x8744454293506046) for PID 23199
806                   S: executing: mkdir("/tmp/nosuchdir/b", 0700)
807                   S: failure! (errno = 2; No such file or directory)
808                   S: sending response (flags = 0; val = 0; error = -2)
809           T: ERROR: mkdir(2): No such file or directory
810
811           T: terminating
812                   S: target has terminated; bye
813
814       If the supervisor receives a notification and sees that the argument of
815       the  target's  mkdir(2) is the string "/bye", then (as well as spoofing
816       an EOPNOTSUPP error), the supervisor terminates.  If the target process
817       subsequently executes another mkdir(2) that triggers its seccomp filter
818       to return the SECCOMP_RET_USER_NOTIF  action  value,  then  the  kernel
819       causes  the  target process's system call to fail with the error ENOSYS
820       ("Function not implemented").  This is demonstrated  by  the  following
821       example:
822
823           $ ./seccomp_unotify /bye /tmp/y
824           T: PID = 23185
825
826           T: about to mkdir("/bye")
827                   S: got notification (ID 0xa81236b1d2f7b0f4) for PID 23185
828                   S: spoofing error response (Operation not supported)
829                   S: sending response (flags = 0; val = 0; error = -95)
830                   S: terminating **********
831           T: ERROR: mkdir(2): Operation not supported
832
833           T: about to mkdir("/tmp/y")
834           T: ERROR: mkdir(2): Function not implemented
835
836           T: terminating
837
838   Program source
839       #define _GNU_SOURCE
840       #include <err.h>
841       #include <errno.h>
842       #include <fcntl.h>
843       #include <limits.h>
844       #include <linux/audit.h>
845       #include <linux/filter.h>
846       #include <linux/seccomp.h>
847       #include <signal.h>
848       #include <stdbool.h>
849       #include <stddef.h>
850       #include <stdint.h>
851       #include <stdio.h>
852       #include <stdlib.h>
853       #include <string.h>
854       #include <sys/ioctl.h>
855       #include <sys/prctl.h>
856       #include <sys/socket.h>
857       #include <sys/stat.h>
858       #include <sys/syscall.h>
859       #include <sys/types.h>
860       #include <sys/un.h>
861       #include <unistd.h>
862
863       #define ARRAY_SIZE(arr)  (sizeof(arr) / sizeof((arr)[0]))
864
865       /* Send the file descriptor 'fd' over the connected UNIX domain socket
866          'sockfd'. Returns 0 on success, or -1 on error. */
867
868       static int
869       sendfd(int sockfd, int fd)
870       {
871           int             data;
872           struct iovec    iov;
873           struct msghdr   msgh;
874           struct cmsghdr  *cmsgp;
875
876           /* Allocate a char array of suitable size to hold the ancillary data.
877              However, since this buffer is in reality a 'struct cmsghdr', use a
878              union to ensure that it is suitably aligned. */
879           union {
880               char   buf[CMSG_SPACE(sizeof(int))];
881                               /* Space large enough to hold an 'int' */
882               struct cmsghdr align;
883           } controlMsg;
884
885           /* The 'msg_name' field can be used to specify the address of the
886              destination socket when sending a datagram. However, we do not
887              need to use this field because 'sockfd' is a connected socket. */
888
889           msgh.msg_name = NULL;
890           msgh.msg_namelen = 0;
891
892           /* On Linux, we must transmit at least one byte of real data in
893              order to send ancillary data. We transmit an arbitrary integer
894              whose value is ignored by recvfd(). */
895
896           msgh.msg_iov = &iov;
897           msgh.msg_iovlen = 1;
898           iov.iov_base = &data;
899           iov.iov_len = sizeof(int);
900           data = 12345;
901
902           /* Set 'msghdr' fields that describe ancillary data */
903
904           msgh.msg_control = controlMsg.buf;
905           msgh.msg_controllen = sizeof(controlMsg.buf);
906
907           /* Set up ancillary data describing file descriptor to send */
908
909           cmsgp = CMSG_FIRSTHDR(&msgh);
910           cmsgp->cmsg_level = SOL_SOCKET;
911           cmsgp->cmsg_type = SCM_RIGHTS;
912           cmsgp->cmsg_len = CMSG_LEN(sizeof(int));
913           memcpy(CMSG_DATA(cmsgp), &fd, sizeof(int));
914
915           /* Send real plus ancillary data */
916
917           if (sendmsg(sockfd, &msgh, 0) == -1)
918               return -1;
919
920           return 0;
921       }
922
923       /* Receive a file descriptor on a connected UNIX domain socket. Returns
924          the received file descriptor on success, or -1 on error. */
925
926       static int
927       recvfd(int sockfd)
928       {
929           int            data, fd;
930           ssize_t        nr;
931           struct iovec   iov;
932           struct msghdr  msgh;
933
934           /* Allocate a char buffer for the ancillary data. See the comments
935              in sendfd() */
936           union {
937               char   buf[CMSG_SPACE(sizeof(int))];
938               struct cmsghdr align;
939           } controlMsg;
940           struct cmsghdr *cmsgp;
941
942           /* The 'msg_name' field can be used to obtain the address of the
943              sending socket. However, we do not need this information. */
944
945           msgh.msg_name = NULL;
946           msgh.msg_namelen = 0;
947
948           /* Specify buffer for receiving real data */
949
950           msgh.msg_iov = &iov;
951           msgh.msg_iovlen = 1;
952           iov.iov_base = &data;       /* Real data is an 'int' */
953           iov.iov_len = sizeof(int);
954
955           /* Set 'msghdr' fields that describe ancillary data */
956
957           msgh.msg_control = controlMsg.buf;
958           msgh.msg_controllen = sizeof(controlMsg.buf);
959
960           /* Receive real plus ancillary data; real data is ignored */
961
962           nr = recvmsg(sockfd, &msgh, 0);
963           if (nr == -1)
964               return -1;
965
966           cmsgp = CMSG_FIRSTHDR(&msgh);
967
968           /* Check the validity of the 'cmsghdr' */
969
970           if (cmsgp == NULL
971               || cmsgp->cmsg_len != CMSG_LEN(sizeof(int))
972               || cmsgp->cmsg_level != SOL_SOCKET
973               || cmsgp->cmsg_type != SCM_RIGHTS)
974           {
975               errno = EINVAL;
976               return -1;
977           }
978
979           /* Return the received file descriptor to our caller */
980
981           memcpy(&fd, CMSG_DATA(cmsgp), sizeof(int));
982           return fd;
983       }
984
985       static void
986       sigchldHandler(int sig)
987       {
988           char msg[] = "\tS: target has terminated; bye\n";
989
990           write(STDOUT_FILENO, msg, sizeof(msg) - 1);
991           _exit(EXIT_SUCCESS);
992       }
993
994       static int
995       seccomp(unsigned int operation, unsigned int flags, void *args)
996       {
997           return syscall(SYS_seccomp, operation, flags, args);
998       }
999
1000       /* The following is the x86-64-specific BPF boilerplate code for checking
1001          that the BPF program is running on the right architecture + ABI. At
1002          completion of these instructions, the accumulator contains the system
1003          call number. */
1004
1005       /* For the x32 ABI, all system call numbers have bit 30 set */
1006
1007       #define X32_SYSCALL_BIT         0x40000000
1008
1009       #define X86_64_CHECK_ARCH_AND_LOAD_SYSCALL_NR \
1010               BPF_STMT(BPF_LD | BPF_W | BPF_ABS, \
1011                        (offsetof(struct seccomp_data, arch))), \
1012               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_X86_64, 0, 2), \
1013               BPF_STMT(BPF_LD | BPF_W | BPF_ABS, \
1014                        (offsetof(struct seccomp_data, nr))), \
1015               BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, X32_SYSCALL_BIT, 0, 1), \
1016               BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL_PROCESS)
1017
1018       /* installNotifyFilter() installs a seccomp filter that generates
1019          user-space notifications (SECCOMP_RET_USER_NOTIF) when the process
1020          calls mkdir(2); the filter allows all other system calls.
1021
1022          The function return value is a file descriptor from which the
1023          user-space notifications can be fetched. */
1024
1025       static int
1026       installNotifyFilter(void)
1027       {
1028           int notifyFd;
1029
1030           struct sock_filter filter[] = {
1031               X86_64_CHECK_ARCH_AND_LOAD_SYSCALL_NR,
1032
1033               /* mkdir() triggers notification to user-space supervisor */
1034
1035               BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_mkdir, 0, 1),
1036               BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_USER_NOTIF),
1037
1038               /* Every other system call is allowed */
1039
1040               BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
1041           };
1042
1043           struct sock_fprog prog = {
1044               .len = ARRAY_SIZE(filter),
1045               .filter = filter,
1046           };
1047
1048           /* Install the filter with the SECCOMP_FILTER_FLAG_NEW_LISTENER flag;
1049              as a result, seccomp() returns a notification file descriptor. */
1050
1051           notifyFd = seccomp(SECCOMP_SET_MODE_FILTER,
1052                              SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
1053           if (notifyFd == -1)
1054               err(EXIT_FAILURE, "seccomp-install-notify-filter");
1055
1056           return notifyFd;
1057       }
1058
1059       /* Close a pair of sockets created by socketpair() */
1060
1061       static void
1062       closeSocketPair(int sockPair[2])
1063       {
1064           if (close(sockPair[0]) == -1)
1065               err(EXIT_FAILURE, "closeSocketPair-close-0");
1066           if (close(sockPair[1]) == -1)
1067               err(EXIT_FAILURE, "closeSocketPair-close-1");
1068       }
1069
1070       /* Implementation of the target process; create a child process that:
1071
1072          (1) installs a seccomp filter with the
1073              SECCOMP_FILTER_FLAG_NEW_LISTENER flag;
1074          (2) writes the seccomp notification file descriptor returned from
1075              the previous step onto the UNIX domain socket, 'sockPair[0]';
1076          (3) calls mkdir(2) for each element of 'argv'.
1077
1078          The function return value in the parent is the PID of the child
1079          process; the child does not return from this function. */
1080
1081       static pid_t
1082       targetProcess(int sockPair[2], char *argv[])
1083       {
1084           int    notifyFd, s;
1085           pid_t  targetPid;
1086
1087           targetPid = fork();
1088
1089           if (targetPid == -1)
1090               err(EXIT_FAILURE, "fork");
1091
1092           if (targetPid > 0)          /* In parent, return PID of child */
1093               return targetPid;
1094
1095           /* Child falls through to here */
1096
1097           printf("T: PID = %ld\n", (long) getpid());
1098
1099           /* Install seccomp filter(s) */
1100
1101           if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
1102               err(EXIT_FAILURE, "prctl");
1103
1104           notifyFd = installNotifyFilter();
1105
1106           /* Pass the notification file descriptor to the tracing process over
1107              a UNIX domain socket */
1108
1109           if (sendfd(sockPair[0], notifyFd) == -1)
1110               err(EXIT_FAILURE, "sendfd");
1111
1112           /* Notification and socket FDs are no longer needed in target */
1113
1114           if (close(notifyFd) == -1)
1115               err(EXIT_FAILURE, "close-target-notify-fd");
1116
1117           closeSocketPair(sockPair);
1118
1119           /* Perform a mkdir() call for each of the command-line arguments */
1120
1121           for (char **ap = argv; *ap != NULL; ap++) {
1122               printf("\nT: about to mkdir(\"%s\")\n", *ap);
1123
1124               s = mkdir(*ap, 0700);
1125               if (s == -1)
1126                   perror("T: ERROR: mkdir(2)");
1127               else
1128                   printf("T: SUCCESS: mkdir(2) returned %d\n", s);
1129           }
1130
1131           printf("\nT: terminating\n");
1132           exit(EXIT_SUCCESS);
1133       }
1134
1135       /* Check that the notification ID provided by a SECCOMP_IOCTL_NOTIF_RECV
1136          operation is still valid. It will no longer be valid if the target
1137          process has terminated or is no longer blocked in the system call that
1138          generated the notification (because it was interrupted by a signal).
1139
1140          This operation can be used when doing such things as accessing
1141          /proc/PID files in the target process in order to avoid TOCTOU race
1142          conditions where the PID that is returned by SECCOMP_IOCTL_NOTIF_RECV
1143          terminates and is reused by another process. */
1144
1145       static bool
1146       cookieIsValid(int notifyFd, uint64_t id)
1147       {
1148           return ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_ID_VALID, &id) == 0;
1149       }
1150
1151       /* Access the memory of the target process in order to fetch the
1152          pathname referred to by the system call argument 'argNum' in
1153          'req->data.args[]'.  The pathname is returned in 'path',
1154          a buffer of 'len' bytes allocated by the caller.
1155
1156          Returns true if the pathname is successfully fetched, and false
1157          otherwise. For possible causes of failure, see the comments below. */
1158
1159       static bool
1160       getTargetPathname(struct seccomp_notif *req, int notifyFd,
1161                         int argNum, char *path, size_t len)
1162       {
1163           int      procMemFd;
1164           char     procMemPath[PATH_MAX];
1165           ssize_t  nread;
1166
1167           snprintf(procMemPath, sizeof(procMemPath), "/proc/%d/mem", req->pid);
1168
1169           procMemFd = open(procMemPath, O_RDONLY | O_CLOEXEC);
1170           if (procMemFd == -1)
1171               return false;
1172
1173           /* Check that the process whose info we are accessing is still alive
1174              and blocked in the system call that caused the notification.
1175              If the SECCOMP_IOCTL_NOTIF_ID_VALID operation (performed in
1176              cookieIsValid()) succeeded, we know that the /proc/PID/mem file
1177              descriptor that we opened corresponded to the process for which we
1178              received a notification. If that process subsequently terminates,
1179              then read() on that file descriptor will return 0 (EOF). */
1180
1181           if (!cookieIsValid(notifyFd, req->id)) {
1182               close(procMemFd);
1183               return false;
1184           }
1185
1186           /* Read bytes at the location containing the pathname argument */
1187
1188           nread = pread(procMemFd, path, len, req->data.args[argNum]);
1189
1190           close(procMemFd);
1191
1192           if (nread <= 0)
1193               return false;
1194
1195           /* Once again check that the notification ID is still valid. The
1196              case we are particularly concerned about here is that just
1197              before we fetched the pathname, the target's blocked system
1198              call was interrupted by a signal handler, and after the handler
1199              returned, the target carried on execution (past the interrupted
1200              system call). In that case, we have no guarantees about what we
1201              are reading, since the target's memory may have been arbitrarily
1202              changed by subsequent operations. */
1203
1204           if (!cookieIsValid(notifyFd, req->id)) {
1205               perror("\tS: notification ID check failed!!!");
1206               return false;
1207           }
1208
1209           /* Even if the target's system call was not interrupted by a signal,
1210              we have no guarantees about what was in the memory of the target
1211              process. (The memory may have been modified by another thread, or
1212              even by an external attacking process.) We therefore treat the
1213              buffer returned by pread() as untrusted input. The buffer should
1214              contain a terminating null byte; if not, then we will trigger an
1215              error for the target process. */
1216
1217           if (strnlen(path, nread) < nread)
1218               return true;
1219
1220           return false;
1221       }
1222
1223       /* Allocate buffers for the seccomp user-space notification request and
1224          response structures. It is the caller's responsibility to free the
1225          buffers returned via 'req' and 'resp'. */
1226
1227       static void
1228       allocSeccompNotifBuffers(struct seccomp_notif **req,
1229                                struct seccomp_notif_resp **resp,
1230                                struct seccomp_notif_sizes *sizes)
1231       {
1232           size_t  resp_size;
1233
1234           /* Discover the sizes of the structures that are used to receive
1235              notifications and send notification responses, and allocate
1236              buffers of those sizes. */
1237
1238           if (seccomp(SECCOMP_GET_NOTIF_SIZES, 0, sizes) == -1)
1239               err(EXIT_FAILURE, "seccomp-SECCOMP_GET_NOTIF_SIZES");
1240
1241           *req = malloc(sizes->seccomp_notif);
1242           if (*req == NULL)
1243               err(EXIT_FAILURE, "malloc-seccomp_notif");
1244
1245           /* When allocating the response buffer, we must allow for the fact
1246              that the user-space binary may have been built with user-space
1247              headers where 'struct seccomp_notif_resp' is bigger than the
1248              response buffer expected by the (older) kernel. Therefore, we
1249              allocate a buffer that is the maximum of the two sizes. This
1250              ensures that if the supervisor places bytes into the response
1251              structure that are past the response size that the kernel expects,
1252              then the supervisor is not touching an invalid memory location. */
1253
1254           resp_size = sizes->seccomp_notif_resp;
1255           if (sizeof(struct seccomp_notif_resp) > resp_size)
1256               resp_size = sizeof(struct seccomp_notif_resp);
1257
1258           *resp = malloc(resp_size);
1259           if (*resp == NULL)
1260               err(EXIT_FAILURE, "malloc-seccomp_notif_resp");
1261
1262       }
1263
1264       /* Handle notifications that arrive via the SECCOMP_RET_USER_NOTIF file
1265          descriptor, 'notifyFd'. */
1266
1267       static void
1268       handleNotifications(int notifyFd)
1269       {
1270           bool                        pathOK;
1271           char                        path[PATH_MAX];
1272           struct seccomp_notif        *req;
1273           struct seccomp_notif_resp   *resp;
1274           struct seccomp_notif_sizes  sizes;
1275
1276           allocSeccompNotifBuffers(&req, &resp, &sizes);
1277
1278           /* Loop handling notifications */
1279
1280           for (;;) {
1281
1282               /* Wait for next notification, returning info in '*req' */
1283
1284               memset(req, 0, sizes.seccomp_notif);
1285               if (ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_RECV, req) == -1) {
1286                   if (errno == EINTR)
1287                       continue;
1288                   err(EXIT_FAILURE, "\tS: ioctl-SECCOMP_IOCTL_NOTIF_RECV");
1289               }
1290
1291               printf("\tS: got notification (ID %#llx) for PID %d\n",
1292                      req->id, req->pid);
1293
1294               /* The only system call that can generate a notification event
1295                  is mkdir(2). Nevertheless, we check that the notified system
1296                  call is indeed mkdir() as kind of future-proofing of this
1297                  code in case the seccomp filter is later modified to
1298                  generate notifications for other system calls. */
1299
1300               if (req->data.nr != SYS_mkdir) {
1301                   printf("\tS: notification contained unexpected "
1302                          "system call number; bye!!!\n");
1303                   exit(EXIT_FAILURE);
1304               }
1305
1306               pathOK = getTargetPathname(req, notifyFd, 0, path, sizeof(path));
1307
1308               /* Prepopulate some fields of the response */
1309
1310               resp->id = req->id;     /* Response includes notification ID */
1311               resp->flags = 0;
1312               resp->val = 0;
1313
1314               /* If getTargetPathname() failed, trigger an EINVAL error
1315                  response (sending this response may yield an error if the
1316                  failure occurred because the notification ID was no longer
1317                  valid); if the directory is in /tmp, then create it on behalf
1318                  of the supervisor; if the pathname starts with '.', tell the
1319                  kernel to let the target process execute the mkdir();
1320                  otherwise, give an error for a directory pathname in any other
1321                  location. */
1322
1323               if (!pathOK) {
1324                   resp->error = -EINVAL;
1325                   printf("\tS: spoofing error for invalid pathname (%s)\n",
1326                          strerror(-resp->error));
1327               } else if (strncmp(path, "/tmp/", strlen("/tmp/")) == 0) {
1328                   printf("\tS: executing: mkdir(\"%s\", %#llo)\n",
1329                          path, req->data.args[1]);
1330
1331                   if (mkdir(path, req->data.args[1]) == 0) {
1332                       resp->error = 0;            /* "Success" */
1333                       resp->val = strlen(path);   /* Used as return value of
1334                                                      mkdir() in target */
1335                       printf("\tS: success! spoofed return = %lld\n",
1336                              resp->val);
1337                   } else {
1338
1339                       /* If mkdir() failed in the supervisor, pass the error
1340                          back to the target */
1341
1342                       resp->error = -errno;
1343                       printf("\tS: failure! (errno = %d; %s)\n", errno,
1344                              strerror(errno));
1345                   }
1346               } else if (strncmp(path, "./", strlen("./")) == 0) {
1347                   resp->error = resp->val = 0;
1348                   resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
1349                   printf("\tS: target can execute system call\n");
1350               } else {
1351                   resp->error = -EOPNOTSUPP;
1352                   printf("\tS: spoofing error response (%s)\n",
1353                          strerror(-resp->error));
1354               }
1355
1356               /* Send a response to the notification */
1357
1358               printf("\tS: sending response "
1359                      "(flags = %#x; val = %lld; error = %d)\n",
1360                      resp->flags, resp->val, resp->error);
1361
1362               if (ioctl(notifyFd, SECCOMP_IOCTL_NOTIF_SEND, resp) == -1) {
1363                   if (errno == ENOENT)
1364                       printf("\tS: response failed with ENOENT; "
1365                              "perhaps target process's syscall was "
1366                              "interrupted by a signal?\n");
1367                   else
1368                       perror("ioctl-SECCOMP_IOCTL_NOTIF_SEND");
1369               }
1370
1371               /* If the pathname is just "/bye", then the supervisor breaks out
1372                  of the loop and terminates. This allows us to see what happens
1373                  if the target process makes further calls to mkdir(2). */
1374
1375               if (strcmp(path, "/bye") == 0)
1376                   break;
1377           }
1378
1379           free(req);
1380           free(resp);
1381           printf("\tS: terminating **********\n");
1382           exit(EXIT_FAILURE);
1383       }
1384
1385       /* Implementation of the supervisor process:
1386
1387          (1) obtains the notification file descriptor from 'sockPair[1]'
1388          (2) handles notifications that arrive on that file descriptor. */
1389
1390       static void
1391       supervisor(int sockPair[2])
1392       {
1393           int notifyFd;
1394
1395           notifyFd = recvfd(sockPair[1]);
1396
1397           if (notifyFd == -1)
1398               err(EXIT_FAILURE, "recvfd");
1399
1400           closeSocketPair(sockPair);  /* We no longer need the socket pair */
1401
1402           handleNotifications(notifyFd);
1403       }
1404
1405       int
1406       main(int argc, char *argv[])
1407       {
1408           int               sockPair[2];
1409           struct sigaction  sa;
1410
1411           setbuf(stdout, NULL);
1412
1413           if (argc < 2) {
1414               fprintf(stderr, "At least one pathname argument is required\n");
1415               exit(EXIT_FAILURE);
1416           }
1417
1418           /* Create a UNIX domain socket that is used to pass the seccomp
1419              notification file descriptor from the target process to the
1420              supervisor process. */
1421
1422           if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockPair) == -1)
1423               err(EXIT_FAILURE, "socketpair");
1424
1425           /* Create a child process--the "target"--that installs seccomp
1426              filtering. The target process writes the seccomp notification
1427              file descriptor onto 'sockPair[0]' and then calls mkdir(2) for
1428              each directory in the command-line arguments. */
1429
1430           (void) targetProcess(sockPair, &argv[optind]);
1431
1432           /* Catch SIGCHLD when the target terminates, so that the
1433              supervisor can also terminate. */
1434
1435           sa.sa_handler = sigchldHandler;
1436           sa.sa_flags = 0;
1437           sigemptyset(&sa.sa_mask);
1438           if (sigaction(SIGCHLD, &sa, NULL) == -1)
1439               err(EXIT_FAILURE, "sigaction");
1440
1441           supervisor(sockPair);
1442
1443           exit(EXIT_SUCCESS);
1444       }
1445

SEE ALSO

1447       ioctl(2), pidfd_getfd(2), pidfd_open(2), seccomp(2)
1448
1449       A  further  example program can be found in the kernel source file sam‐
1450       ples/seccomp/user-trap.c.
1451
1452
1453
1454Linux man-pages 6.04              2023-04-03                seccomp_unotify(2)
Impressum