@@ -196,6 +196,9 @@ use std::convert::TryInto;
196196#[ cfg( feature = "json" ) ]
197197use std:: io:: Read ;
198198
199+ #[ cfg( feature = "seccomp_unotify" ) ]
200+ use std:: os:: fd:: { FromRawFd as _, OwnedFd } ;
201+
199202use std:: collections:: HashMap ;
200203use std:: fmt:: { Display , Formatter } ;
201204use std:: io;
@@ -310,7 +313,8 @@ impl From<JsonFrontendError> for Error {
310313///
311314/// [`BpfProgram`]: type.BpfProgram.html
312315pub fn apply_filter ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
313- apply_filter_with_flags ( bpf_filter, 0 )
316+ apply_filter_with_flags ( bpf_filter, 0 ) ?;
317+ Ok ( ( ) )
314318}
315319
316320/// Apply a BPF filter to the all threads in the process via the TSYNC feature. Please read the
@@ -322,7 +326,28 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<()> {
322326///
323327/// [`BpfProgram`]: type.BpfProgram.html
324328pub fn apply_filter_all_threads ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
325- apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_TSYNC )
329+ let rc = apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_TSYNC ) ?;
330+
331+ if rc > 0 {
332+ return Err ( Error :: ThreadSync ( rc) ) ;
333+ }
334+
335+ Ok ( ( ) )
336+ }
337+
338+ /// Apply a filter with the SECCOMP_FILTER_FLAG_NEW_LISTENER flag.
339+ ///
340+ /// The returned FD can be polled for notifications generated by a rule with the
341+ /// action [SeccompAction::Notify]. See `man 2 seccomp_unotify` for more
342+ /// information.
343+ #[ cfg( feature = "seccomp_unotify" ) ]
344+ pub fn apply_filter_with_notify_fd ( bpf_filter : BpfProgramRef ) -> Result < OwnedFd > {
345+ let rc = apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_NEW_LISTENER ) ?;
346+
347+ // SAFETY: seccomp_unotify documents that it returns a valid FD if the
348+ // syscall is a success.
349+ let fd = unsafe { OwnedFd :: from_raw_fd ( rc as _ ) } ;
350+ Ok ( fd)
326351}
327352
328353/// Apply a BPF filter to the calling thread.
@@ -333,7 +358,7 @@ pub fn apply_filter_all_threads(bpf_filter: BpfProgramRef) -> Result<()> {
333358/// * `flags` - A u64 representing a bitset of seccomp's flags parameter.
334359///
335360/// [`BpfProgram`]: type.BpfProgram.html
336- fn apply_filter_with_flags ( bpf_filter : BpfProgramRef , flags : libc:: c_ulong ) -> Result < ( ) > {
361+ fn apply_filter_with_flags ( bpf_filter : BpfProgramRef , flags : libc:: c_ulong ) -> Result < i64 > {
337362 // If the program is empty, don't install the filter.
338363 if bpf_filter. is_empty ( ) {
339364 return Err ( Error :: EmptyFilter ) ;
@@ -364,16 +389,11 @@ fn apply_filter_with_flags(bpf_filter: BpfProgramRef, flags: libc::c_ulong) -> R
364389 )
365390 } ;
366391
367- #[ allow( clippy:: comparison_chain) ]
368- // Per manpage, if TSYNC fails, retcode is >0 and equals the pid of the thread that caused the
369- // failure. Otherwise, error code is -1 and errno is set.
370392 if rc < 0 {
371- return Err ( Error :: Seccomp ( io:: Error :: last_os_error ( ) ) ) ;
372- } else if rc > 0 {
373- return Err ( Error :: ThreadSync ( rc) ) ;
393+ return Err ( Error :: Seccomp ( std:: io:: Error :: last_os_error ( ) ) ) ;
374394 }
375395
376- Ok ( ( ) )
396+ Ok ( rc )
377397}
378398
379399/// Compile [`BpfProgram`]s from JSON.
0 commit comments