@@ -196,6 +196,9 @@ use std::convert::TryInto;
196
196
#[ cfg( feature = "json" ) ]
197
197
use std:: io:: Read ;
198
198
199
+ #[ cfg( feature = "seccomp_unotify" ) ]
200
+ use std:: os:: fd:: { FromRawFd as _, OwnedFd } ;
201
+
199
202
use std:: collections:: HashMap ;
200
203
use std:: fmt:: { Display , Formatter } ;
201
204
use std:: io;
@@ -310,7 +313,8 @@ impl From<JsonFrontendError> for Error {
310
313
///
311
314
/// [`BpfProgram`]: type.BpfProgram.html
312
315
pub 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 ( ( ) )
314
318
}
315
319
316
320
/// 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<()> {
322
326
///
323
327
/// [`BpfProgram`]: type.BpfProgram.html
324
328
pub 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)
326
351
}
327
352
328
353
/// Apply a BPF filter to the calling thread.
@@ -333,7 +358,7 @@ pub fn apply_filter_all_threads(bpf_filter: BpfProgramRef) -> Result<()> {
333
358
/// * `flags` - A u64 representing a bitset of seccomp's flags parameter.
334
359
///
335
360
/// [`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 > {
337
362
// If the program is empty, don't install the filter.
338
363
if bpf_filter. is_empty ( ) {
339
364
return Err ( Error :: EmptyFilter ) ;
@@ -364,16 +389,11 @@ fn apply_filter_with_flags(bpf_filter: BpfProgramRef, flags: libc::c_ulong) -> R
364
389
)
365
390
} ;
366
391
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.
370
392
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 ( ) ) ) ;
374
394
}
375
395
376
- Ok ( ( ) )
396
+ Ok ( rc )
377
397
}
378
398
379
399
/// Compile [`BpfProgram`]s from JSON.
0 commit comments