182 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|    Copyright The containerd Authors.
 | |
| 
 | |
|    Licensed under the Apache License, Version 2.0 (the "License");
 | |
|    you may not use this file except in compliance with the License.
 | |
|    You may obtain a copy of the License at
 | |
| 
 | |
|        http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
|    Unless required by applicable law or agreed to in writing, software
 | |
|    distributed under the License is distributed on an "AS IS" BASIS,
 | |
|    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|    See the License for the specific language governing permissions and
 | |
|    limitations under the License.
 | |
| */
 | |
| 
 | |
| package cap
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"strings"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| )
 | |
| 
 | |
| const procPIDStatus = `Name:   cat
 | |
| Umask:  0022
 | |
| State:  R (running)
 | |
| Tgid:   170065
 | |
| Ngid:   0
 | |
| Pid:    170065
 | |
| PPid:   170064
 | |
| TracerPid:      0
 | |
| Uid:    0       0       0       0
 | |
| Gid:    0       0       0       0
 | |
| FDSize: 64
 | |
| Groups: 0
 | |
| NStgid: 170065
 | |
| NSpid:  170065
 | |
| NSpgid: 170064
 | |
| NSsid:  3784
 | |
| VmPeak:     8216 kB
 | |
| VmSize:     8216 kB
 | |
| VmLck:         0 kB
 | |
| VmPin:         0 kB
 | |
| VmHWM:       676 kB
 | |
| VmRSS:       676 kB
 | |
| RssAnon:              72 kB
 | |
| RssFile:             604 kB
 | |
| RssShmem:              0 kB
 | |
| VmData:      324 kB
 | |
| VmStk:       132 kB
 | |
| VmExe:        20 kB
 | |
| VmLib:      1612 kB
 | |
| VmPTE:        56 kB
 | |
| VmSwap:        0 kB
 | |
| HugetlbPages:          0 kB
 | |
| CoreDumping:    0
 | |
| THP_enabled:    1
 | |
| Threads:        1
 | |
| SigQ:   0/63692
 | |
| SigPnd: 0000000000000000
 | |
| ShdPnd: 0000000000000000
 | |
| SigBlk: 0000000000000000
 | |
| SigIgn: 0000000000000000
 | |
| SigCgt: 0000000000000000
 | |
| CapInh: 0000000000000000
 | |
| CapPrm: 000000ffffffffff
 | |
| CapEff: 000000ffffffffff
 | |
| CapBnd: 000000ffffffffff
 | |
| CapAmb: 0000000000000000
 | |
| NoNewPrivs:     0
 | |
| Seccomp:        0
 | |
| Speculation_Store_Bypass:       thread vulnerable
 | |
| Cpus_allowed:   00000000,00000000,00000000,0000000f
 | |
| Cpus_allowed_list:      0-3
 | |
| Mems_allowed:   00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
 | |
| Mems_allowed_list:      0
 | |
| voluntary_ctxt_switches:        0
 | |
| nonvoluntary_ctxt_switches:     0
 | |
| `
 | |
| 
 | |
| func TestCapsList(t *testing.T) {
 | |
| 	assert.Len(t, caps316, 38)
 | |
| 	assert.Len(t, caps58, 40)
 | |
| 	assert.Len(t, caps59, 41)
 | |
| }
 | |
| 
 | |
| func TestFromNumber(t *testing.T) {
 | |
| 	assert.Equal(t, "CAP_CHOWN", FromNumber(0))
 | |
| 	assert.Equal(t, "CAP_SYS_ADMIN", FromNumber(21))
 | |
| 	assert.Equal(t, "CAP_CHECKPOINT_RESTORE", FromNumber(40))
 | |
| 	assert.Equal(t, "", FromNumber(-1))
 | |
| 	assert.Equal(t, "", FromNumber(63))
 | |
| 	assert.Equal(t, "", FromNumber(255))
 | |
| }
 | |
| 
 | |
| func TestFromBitmap(t *testing.T) {
 | |
| 	type testCase struct {
 | |
| 		comment    string
 | |
| 		v          uint64
 | |
| 		knownNames []string
 | |
| 		unknown    []int
 | |
| 	}
 | |
| 	testCases := []testCase{
 | |
| 		{
 | |
| 			comment: "No cap",
 | |
| 			v:       0x0000000000000000,
 | |
| 		},
 | |
| 		{
 | |
| 			// 3.10 (same caps as 3.5) is the oldest kernel version we want to support
 | |
| 			comment:    "All caps on kernel 3.5 (last = CAP_BLOCK_SUSPEND)",
 | |
| 			v:          0x0000001fffffffff,
 | |
| 			knownNames: caps35,
 | |
| 		},
 | |
| 		{
 | |
| 			comment:    "All caps on kernel 3.16 (last = CAP_AUDIT_READ)",
 | |
| 			v:          0x0000003fffffffff,
 | |
| 			knownNames: caps316,
 | |
| 		},
 | |
| 		{
 | |
| 			comment:    "All caps on kernel 5.8 (last = CAP_BPF)",
 | |
| 			v:          0x000000ffffffffff,
 | |
| 			knownNames: caps58,
 | |
| 		},
 | |
| 		{
 | |
| 			comment:    "All caps on kernel 5.9 (last = CAP_CHECKPOINT_RESTORE)",
 | |
| 			v:          0x000001ffffffffff,
 | |
| 			knownNames: caps59,
 | |
| 		},
 | |
| 		{
 | |
| 			comment:    "Unknown caps",
 | |
| 			v:          0xf00001ffffffffff,
 | |
| 			knownNames: caps59,
 | |
| 			unknown:    []int{60, 61, 62, 63},
 | |
| 		},
 | |
| 	}
 | |
| 
 | |
| 	for _, tc := range testCases {
 | |
| 		knownNames, unknown := FromBitmap(tc.v)
 | |
| 		t.Logf("[%s] v=0x%x, got=%+v (%d entries), unknown=%v",
 | |
| 			tc.comment, tc.v, knownNames, len(knownNames), unknown)
 | |
| 		assert.Equal(t, tc.knownNames, knownNames)
 | |
| 		assert.Equal(t, tc.unknown, unknown)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func TestParseProcPIDStatus(t *testing.T) {
 | |
| 	res, err := ParseProcPIDStatus(strings.NewReader(procPIDStatus))
 | |
| 	assert.NoError(t, err)
 | |
| 	expected := map[Type]uint64{
 | |
| 		Inheritable: 0,
 | |
| 		Permitted:   0xffffffffff,
 | |
| 		Effective:   0xffffffffff,
 | |
| 		Bounding:    0xffffffffff,
 | |
| 		Ambient:     0,
 | |
| 	}
 | |
| 	assert.EqualValues(t, expected, res)
 | |
| }
 | |
| 
 | |
| func TestCurrent(t *testing.T) {
 | |
| 	caps, err := Current()
 | |
| 	assert.NoError(t, err)
 | |
| 	t.Logf("verify the result manually: %+v", caps)
 | |
| }
 | |
| 
 | |
| func TestKnown(t *testing.T) {
 | |
| 	caps := Known()
 | |
| 	assert.EqualValues(t, caps59, caps)
 | |
| }
 | |
| 
 | |
| func FuzzParseProcPIDStatus(f *testing.F) {
 | |
| 	f.Add(procPIDStatus)
 | |
| 	f.Fuzz(func(t *testing.T, s string) {
 | |
| 		result, err := ParseProcPIDStatus(bytes.NewReader([]byte(s)))
 | |
| 		if err != nil && result != nil {
 | |
| 			t.Errorf("either %+v or %+v must be nil", result, err)
 | |
| 		}
 | |
| 	})
 | |
| }
 | 
