github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/plugin/rpcplugin/sandbox/seccomp_linux_test.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package sandbox 5 6 import ( 7 "encoding/binary" 8 "syscall" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 "golang.org/x/net/bpf" 14 ) 15 16 func seccompData(nr int32, arch uint32, ip uint64, args ...uint64) []byte { 17 var buf [64]byte 18 binary.BigEndian.PutUint32(buf[0:], uint32(nr)) 19 binary.BigEndian.PutUint32(buf[4:], arch) 20 binary.BigEndian.PutUint64(buf[8:], ip) 21 for i := 0; i < 6 && i < len(args); i++ { 22 binary.BigEndian.PutUint64(buf[16+i*8:], args[i]) 23 } 24 return buf[:] 25 } 26 27 func TestSeccompFilter(t *testing.T) { 28 for name, tc := range map[string]struct { 29 Filter []bpf.Instruction 30 Data []byte 31 Expected bool 32 }{ 33 "Allowed": { 34 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 35 {Syscall: syscall.SYS_READ}, 36 {Syscall: syscall.SYS_WRITE}, 37 }), 38 Data: seccompData(syscall.SYS_READ, 0xf00, 0), 39 Expected: true, 40 }, 41 "AllFail": { 42 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 43 { 44 Syscall: syscall.SYS_READ, 45 Any: []SeccompConditions{ 46 {All: []SeccompCondition{ 47 &SeccompArgHasAnyBit{Arg: 0, Mask: 2}, 48 &SeccompArgHasAnyBit{Arg: 1, Mask: 2}, 49 &SeccompArgHasAnyBit{Arg: 2, Mask: 2}, 50 &SeccompArgHasAnyBit{Arg: 3, Mask: 2}, 51 }}, 52 }, 53 }, 54 {Syscall: syscall.SYS_WRITE}, 55 }), 56 Data: seccompData(syscall.SYS_READ, 0xf00, 0, 1, 2, 3, 4), 57 Expected: false, 58 }, 59 "AllPass": { 60 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 61 { 62 Syscall: syscall.SYS_READ, 63 Any: []SeccompConditions{ 64 {All: []SeccompCondition{ 65 &SeccompArgHasAnyBit{Arg: 0, Mask: 7}, 66 &SeccompArgHasAnyBit{Arg: 1, Mask: 7}, 67 &SeccompArgHasAnyBit{Arg: 2, Mask: 7}, 68 &SeccompArgHasAnyBit{Arg: 3, Mask: 7}, 69 }}, 70 }, 71 }, 72 {Syscall: syscall.SYS_WRITE}, 73 }), 74 Data: seccompData(syscall.SYS_READ, 0xf00, 0, 1, 2, 3, 4), 75 Expected: true, 76 }, 77 "AnyFail": { 78 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 79 { 80 Syscall: syscall.SYS_READ, 81 Any: []SeccompConditions{ 82 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 0, Mask: 8}}}, 83 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 1, Mask: 8}}}, 84 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 2, Mask: 8}}}, 85 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 3, Mask: 8}}}, 86 }, 87 }, 88 {Syscall: syscall.SYS_WRITE}, 89 }), 90 Data: seccompData(syscall.SYS_READ, 0xf00, 0, 1, 2, 3, 4), 91 Expected: false, 92 }, 93 "AnyPass": { 94 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 95 { 96 Syscall: syscall.SYS_READ, 97 Any: []SeccompConditions{ 98 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 0, Mask: 2}}}, 99 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 1, Mask: 2}}}, 100 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 2, Mask: 2}}}, 101 {All: []SeccompCondition{&SeccompArgHasAnyBit{Arg: 3, Mask: 2}}}, 102 }, 103 }, 104 {Syscall: syscall.SYS_WRITE}, 105 }), 106 Data: seccompData(syscall.SYS_READ, 0xf00, 0, 1, 2, 3, 4), 107 Expected: true, 108 }, 109 "BadArch": { 110 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 111 {Syscall: syscall.SYS_READ}, 112 {Syscall: syscall.SYS_WRITE}, 113 }), 114 Data: seccompData(syscall.SYS_MOUNT, 0xf01, 0), 115 Expected: false, 116 }, 117 "BadSyscall": { 118 Filter: SeccompFilter(0xf00, []SeccompSyscall{ 119 {Syscall: syscall.SYS_READ}, 120 {Syscall: syscall.SYS_WRITE}, 121 }), 122 Data: seccompData(syscall.SYS_MOUNT, 0xf00, 0), 123 Expected: false, 124 }, 125 } { 126 t.Run(name, func(t *testing.T) { 127 vm, err := bpf.NewVM(tc.Filter) 128 require.NoError(t, err) 129 result, err := vm.Run(tc.Data) 130 require.NoError(t, err) 131 if tc.Expected { 132 assert.Equal(t, SECCOMP_RET_ALLOW, result) 133 } else { 134 assert.Equal(t, int(SECCOMP_RET_ERRNO|syscall.EPERM), result) 135 } 136 }) 137 } 138 } 139 140 func TestSeccompFilter_Conditions(t *testing.T) { 141 for name, tc := range map[string]struct { 142 Condition SeccompCondition 143 Args []uint64 144 Expected bool 145 }{ 146 "ArgHasAnyBitFail": { 147 Condition: SeccompArgHasAnyBit{Arg: 0, Mask: 0x0004}, 148 Args: []uint64{0x0400008000}, 149 Expected: false, 150 }, 151 "ArgHasAnyBitPass1": { 152 Condition: SeccompArgHasAnyBit{Arg: 0, Mask: 0x400000004}, 153 Args: []uint64{0x8000008004}, 154 Expected: true, 155 }, 156 "ArgHasAnyBitPass2": { 157 Condition: SeccompArgHasAnyBit{Arg: 0, Mask: 0x400000004}, 158 Args: []uint64{0x8400008000}, 159 Expected: true, 160 }, 161 "ArgHasNoBitsFail1": { 162 Condition: SeccompArgHasNoBits{Arg: 0, Mask: 0x1100000011}, 163 Args: []uint64{0x0000008007}, 164 Expected: false, 165 }, 166 "ArgHasNoBitsFail2": { 167 Condition: SeccompArgHasNoBits{Arg: 0, Mask: 0x1100000011}, 168 Args: []uint64{0x0700008000}, 169 Expected: false, 170 }, 171 "ArgHasNoBitsPass": { 172 Condition: SeccompArgHasNoBits{Arg: 0, Mask: 0x400000004}, 173 Args: []uint64{0x8000008000}, 174 Expected: true, 175 }, 176 "ArgEqualsPass": { 177 Condition: SeccompArgEquals{Arg: 0, Value: 0x123456789ABCDEF}, 178 Args: []uint64{0x123456789ABCDEF}, 179 Expected: true, 180 }, 181 "ArgEqualsFail1": { 182 Condition: SeccompArgEquals{Arg: 0, Value: 0x123456789ABCDEF}, 183 Args: []uint64{0x023456789ABCDEF}, 184 Expected: false, 185 }, 186 "ArgEqualsFail2": { 187 Condition: SeccompArgEquals{Arg: 0, Value: 0x123456789ABCDEF}, 188 Args: []uint64{0x123456789ABCDE0}, 189 Expected: false, 190 }, 191 } { 192 t.Run(name, func(t *testing.T) { 193 filter := SeccompFilter(0xf00, []SeccompSyscall{ 194 { 195 Syscall: 1, 196 Any: []SeccompConditions{{All: []SeccompCondition{tc.Condition}}}, 197 }, 198 }) 199 vm, err := bpf.NewVM(filter) 200 require.NoError(t, err) 201 result, err := vm.Run(seccompData(1, 0xf00, 0, tc.Args...)) 202 require.NoError(t, err) 203 if tc.Expected { 204 assert.Equal(t, SECCOMP_RET_ALLOW, result) 205 } else { 206 assert.Equal(t, int(SECCOMP_RET_ERRNO|syscall.EPERM), result) 207 } 208 }) 209 } 210 }