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