@@ -208,6 +208,10 @@ pub use backend::{
208208 SeccompCmpOp , SeccompCondition , SeccompFilter , SeccompRule , TargetArch ,
209209} ;
210210
211+ // Until https://github.com/rust-lang/libc/issues/3342 is fixed, define locally
212+ // From <linux/seccomp.h>
213+ const SECCOMP_SET_MODE_FILTER : libc:: c_int = 1 ;
214+
211215// BPF structure definition for filter array.
212216// See /usr/include/linux/filter.h .
213217#[ repr( C ) ]
@@ -231,6 +235,11 @@ pub enum Error {
231235 EmptyFilter ,
232236 /// System error related to calling `prctl`.
233237 Prctl ( io:: Error ) ,
238+ /// System error related to calling `seccomp` syscall.
239+ Seccomp ( io:: Error ) ,
240+ /// Returned when calling `seccomp` with the thread sync flag (TSYNC) fails. Contains the pid
241+ /// of the thread that caused the failure.
242+ ThreadSync ( libc:: c_long ) ,
234243 /// Json Frontend Error.
235244 #[ cfg( feature = "json" ) ]
236245 JsonFrontend ( JsonFrontendError ) ,
@@ -243,6 +252,8 @@ impl std::error::Error for Error {
243252 match self {
244253 Backend ( error) => Some ( error) ,
245254 Prctl ( error) => Some ( error) ,
255+ Seccomp ( error) => Some ( error) ,
256+ ThreadSync ( _) => None ,
246257 #[ cfg( feature = "json" ) ]
247258 JsonFrontend ( error) => Some ( error) ,
248259 _ => None ,
@@ -264,6 +275,16 @@ impl Display for Error {
264275 Prctl ( errno) => {
265276 write ! ( f, "Error calling `prctl`: {}" , errno)
266277 }
278+ Seccomp ( errno) => {
279+ write ! ( f, "Error calling `seccomp`: {}" , errno)
280+ }
281+ ThreadSync ( pid) => {
282+ write ! (
283+ f,
284+ "Seccomp filter synchronization failed in thread `{}`" ,
285+ pid
286+ )
287+ }
267288 #[ cfg( feature = "json" ) ]
268289 JsonFrontend ( error) => {
269290 write ! ( f, "Json Frontend error: {}" , error)
@@ -292,6 +313,30 @@ impl From<JsonFrontendError> for Error {
292313///
293314/// [`BpfProgram`]: type.BpfProgram.html
294315pub fn apply_filter ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
316+ apply_filter_with_flags ( bpf_filter, 0 )
317+ }
318+
319+ /// Apply a BPF filter to the all threads in the process via the TSYNC feature. Please read the
320+ /// man page for seccomp (`man 2 seccomp`) for more information.
321+ ///
322+ /// # Arguments
323+ ///
324+ /// * `bpf_filter` - A reference to the [`BpfProgram`] to be installed.
325+ ///
326+ /// [`BpfProgram`]: type.BpfProgram.html
327+ pub fn apply_filter_all_threads ( bpf_filter : BpfProgramRef ) -> Result < ( ) > {
328+ apply_filter_with_flags ( bpf_filter, libc:: SECCOMP_FILTER_FLAG_TSYNC )
329+ }
330+
331+ /// Apply a BPF filter to the calling thread.
332+ ///
333+ /// # Arguments
334+ ///
335+ /// * `bpf_filter` - A reference to the [`BpfProgram`] to be installed.
336+ /// * `flags` - A u64 representing a bitset of seccomp's flags parameter.
337+ ///
338+ /// [`BpfProgram`]: type.BpfProgram.html
339+ fn apply_filter_with_flags ( bpf_filter : BpfProgramRef , flags : libc:: c_ulong ) -> Result < ( ) > {
295340 // If the program is empty, don't install the filter.
296341 if bpf_filter. is_empty ( ) {
297342 return Err ( Error :: EmptyFilter ) ;
@@ -314,14 +359,21 @@ pub fn apply_filter(bpf_filter: BpfProgramRef) -> Result<()> {
314359 // Safe because the kernel performs a `copy_from_user` on the filter and leaves the memory
315360 // untouched. We can therefore use a reference to the BpfProgram, without needing ownership.
316361 let rc = unsafe {
317- libc:: prctl (
318- libc:: PR_SET_SECCOMP ,
319- libc:: SECCOMP_MODE_FILTER ,
362+ libc:: syscall (
363+ libc:: SYS_seccomp ,
364+ SECCOMP_SET_MODE_FILTER ,
365+ flags,
320366 bpf_prog_ptr,
321367 )
322368 } ;
323- if rc != 0 {
324- return Err ( Error :: Prctl ( io:: Error :: last_os_error ( ) ) ) ;
369+
370+ #[ allow( clippy:: comparison_chain) ]
371+ // Per manpage, if TSYNC fails, retcode is >0 and equals the pid of the thread that caused the
372+ // failure. Otherwise, error code is -1 and errno is set.
373+ if rc < 0 {
374+ return Err ( Error :: Seccomp ( io:: Error :: last_os_error ( ) ) ) ;
375+ } else if rc > 0 {
376+ return Err ( Error :: ThreadSync ( rc) ) ;
325377 }
326378
327379 Ok ( ( ) )
0 commit comments