11// Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+ // Copyright 2021 Sony Group Corporation
3+ //
24// SPDX-License-Identifier: Apache-2.0
35
46use std:: collections:: BTreeMap ;
@@ -23,39 +25,54 @@ pub enum SeccompCmpOp {
2325 Ne ,
2426}
2527
28+ /// Seccomp argument value length.
29+ #[ derive( Clone , Debug , Deserialize , PartialEq ) ]
30+ #[ serde( rename_all = "lowercase" ) ]
31+ pub enum SeccompCmpArgLen {
32+ /// Argument value length is 4 bytes.
33+ Dword ,
34+ /// Argument value length is 8 bytes.
35+ Qword ,
36+ }
37+
2638/// Condition that syscall must match in order to satisfy a rule.
2739#[ derive( Debug , Deserialize ) ]
2840pub struct SeccompCondition {
2941 pub index : u8 ,
3042 pub op : SeccompCmpOp ,
3143 pub val : u64 ,
44+ #[ serde( rename = "type" ) ]
45+ pub val_len : SeccompCmpArgLen ,
3246}
3347
3448impl SeccompCondition {
35- pub fn to_scmp_type ( & self , arch : & TargetArch , syscall : i32 ) -> scmp_arg_cmp {
36- // For `ioctls` we need to mask upper bits as musl
37- // sets them to 1, but libseccomp explicitly checks that they are 0.
38- // with 0x00000000FFFFFFFF mask upper bits are always 0.
39- let ioctl = match arch {
40- TargetArch :: X86_64 => 16 ,
41- TargetArch :: Aarch64 => 29 ,
42- } ;
49+ pub fn to_scmp_type ( & self ) -> scmp_arg_cmp {
4350 match self . op {
4451 SeccompCmpOp :: Eq => {
45- if syscall == ioctl {
46- scmp_arg_cmp {
52+ // When using EQ libseccomp compares the whole 64 bits. In
53+ // general this is not a problem, but for example we have
54+ // observed musl `ioctl` to leave garbage in the upper bits of
55+ // the `request` argument. There is a GH issue to allow 32bit
56+ // comparisons (see
57+ // https://github.com/seccomp/libseccomp/issues/383) but is not
58+ // merged yet. Until that is available, do a masked comparison
59+ // with the upper 32bits set to 0, so we will compare that `hi32
60+ // & 0x0 == 0`, which is always true. This costs one additional
61+ // instruction, but will be likely be optimized away by the BPF
62+ // JIT.
63+ match self . val_len {
64+ SeccompCmpArgLen :: Dword => scmp_arg_cmp {
4765 arg : self . index as u32 ,
4866 op : scmp_compare:: SCMP_CMP_MASKED_EQ ,
4967 datum_a : 0x00000000FFFFFFFF ,
5068 datum_b : self . val ,
51- }
52- } else {
53- scmp_arg_cmp {
69+ } ,
70+ SeccompCmpArgLen :: Qword => scmp_arg_cmp {
5471 arg : self . index as u32 ,
5572 op : scmp_compare:: SCMP_CMP_EQ ,
5673 datum_a : self . val ,
5774 datum_b : 0 ,
58- }
75+ } ,
5976 }
6077 }
6178 SeccompCmpOp :: Ge => scmp_arg_cmp {
0 commit comments