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  }