@@ -195,6 +195,9 @@ use std::convert::TryInto;
195195#[ cfg( feature = "json" ) ]
196196use std:: io:: Read ;
197197
198+ #[ cfg( feature = "seccomp_unotify" ) ]
199+ use std:: os:: fd:: { FromRawFd as _, OwnedFd } ;
200+
198201use std:: collections:: HashMap ;
199202use std:: fmt:: { Display , Formatter } ;
200203use std:: io;
@@ -309,7 +312,8 @@ impl From<JsonFrontendError> for Error {
309312///
310313/// [`BpfProgram`]: type.BpfProgram.html
311314pub fn apply_filter ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
312- apply_filter_with_flags ( bpf_filter, 0 )
315+ apply_filter_with_flags ( bpf_filter, 0 ) ?;
316+ Ok ( ( ) )
313317}
314318
315319/// Apply a BPF filter to the all threads in the process via the TSYNC feature. Please read the
@@ -321,7 +325,28 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<()> {
321325///
322326/// [`BpfProgram`]: type.BpfProgram.html
323327pub fn apply_filter_all_threads ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
324- apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_TSYNC )
328+ let rc = apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_TSYNC ) ?;
329+
330+ if rc > 0 {
331+ return Err ( Error :: ThreadSync ( rc) ) ;
332+ }
333+
334+ Ok ( ( ) )
335+ }
336+
337+ /// Apply a filter with the SECCOMP_FILTER_FLAG_NEW_LISTENER flag.
338+ ///
339+ /// The returned FD can be polled for notifications generated by a rule with the
340+ /// action [SeccompAction::Notify]. See `man 2 seccomp_unotify` for more
341+ /// information.
342+ #[ cfg( feature = "seccomp_unotify" ) ]
343+ pub fn apply_filter_with_notify_fd ( bpf_filter : BpfProgramRef ) -> Result < OwnedFd > {
344+ let rc = apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_NEW_LISTENER ) ?;
345+
346+ // SAFETY: seccomp_unotify documents that it returns a valid FD if the
347+ // syscall is a success.
348+ let fd = unsafe { OwnedFd :: from_raw_fd ( rc as _ ) } ;
349+ Ok ( fd)
325350}
326351
327352/// Apply a BPF filter to the calling thread.
@@ -332,7 +357,7 @@ pub fn apply_filter_all_threads(bpf_filter: BpfProgramRef) -> Result<()> {
332357/// * `flags` - A u64 representing a bitset of seccomp's flags parameter.
333358///
334359/// [`BpfProgram`]: type.BpfProgram.html
335- fn apply_filter_with_flags ( bpf_filter : BpfProgramRef , flags : libc:: c_ulong ) -> Result < ( ) > {
360+ fn apply_filter_with_flags ( bpf_filter : BpfProgramRef , flags : libc:: c_ulong ) -> Result < i64 > {
336361 // If the program is empty, don't install the filter.
337362 if bpf_filter. is_empty ( ) {
338363 return Err ( Error :: EmptyFilter ) ;
@@ -363,16 +388,11 @@ fn apply_filter_with_flags(bpf_filter: BpfProgramRef, flags: libc::c_ulong) -> R
363388 )
364389 } ;
365390
366- #[ allow( clippy:: comparison_chain) ]
367- // Per manpage, if TSYNC fails, retcode is >0 and equals the pid of the thread that caused the
368- // failure. Otherwise, error code is -1 and errno is set.
369391 if rc < 0 {
370- return Err ( Error :: Seccomp ( io:: Error :: last_os_error ( ) ) ) ;
371- } else if rc > 0 {
372- return Err ( Error :: ThreadSync ( rc) ) ;
392+ return Err ( Error :: Seccomp ( std:: io:: Error :: last_os_error ( ) ) ) ;
373393 }
374394
375- Ok ( ( ) )
395+ Ok ( rc )
376396}
377397
378398/// Compile [`BpfProgram`]s from JSON.
0 commit comments