github.com/sdibtacm/sandbox@v0.0.0-20200320120712-60470cf803dc/exec/scmpFilter/scmp.go (about) 1 package scmpFilter 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "github.com/sdibtacm/sandbox/exec/log" 8 "github.com/sdibtacm/sandbox/g" 9 "github.com/sdibtacm/sandbox/units/helper" 10 "github.com/sdibtacm/sandbox/units/seccomp" 11 "io" 12 "io/ioutil" 13 "os" 14 "syscall" 15 "unsafe" 16 ) 17 18 const ( 19 EPERM = int16(syscall.EPERM) 20 ENOSYS = int16(syscall.ENOSYS) 21 ) 22 23 const ( 24 DEFAULT_KILL ScmpAction = 0x00 25 DEFAULT_TRACE ScmpAction = 0x01 26 DEFAULT_EPERM ScmpAction = 0x02 27 DEFAULT_ENOSYS ScmpAction = 0x03 28 29 OTHERS_KILL ScmpAction = 0x10 30 OTHERS_TRACE ScmpAction = 0x11 31 OTHERS_EPERM ScmpAction = 0x12 32 OTHERS_ENOSYS ScmpAction = 0x13 33 ) 34 35 var ( 36 ErrScmpNotAllowDefaultActionAllow = errors.New("only lrun filter can let default action is 'act_allow' ") 37 ) 38 39 type scmpMid struct { 40 seccomp.ScmpFilter 41 } 42 43 type ScmpAction int8 44 45 type ScmpFilterLoadHelper struct { 46 Action ScmpAction 47 48 LrunScmpFilter string // https://github.com/quark-zju/lrun/blob/master/src/seccomp.h 49 50 Level int 51 52 ExecvePathPointer unsafe.Pointer 53 } 54 55 type scmpLoadFilter struct { 56 SetPrivs bool 57 BPF *syscall.SockFprog 58 } 59 60 func GetScmpFilter(helper *ScmpFilterLoadHelper) (filter *scmpLoadFilter, err error) { 61 if helper.Level == 0 { 62 return nil, nil 63 } 64 65 var scmp *seccomp.ScmpFilter 66 defer func() { 67 if scmp != nil { 68 scmp.Release() 69 } 70 // we hope will release after function return 71 }() 72 73 if helper.Level == -1 { 74 // will load by lrun scmp filter string 75 scmp, err = lrunFilterParse(helper) 76 } else { 77 // load as white list 78 scmp, err = nFilterParse(helper) 79 } 80 if err != nil { 81 return 82 } 83 84 midFilter := scmpLoadFilter{} 85 86 midFilter.SetPrivs = true 87 midFilter.BPF, err = scmpToBPF(scmp) 88 if err != nil { 89 return 90 } 91 92 filter = &midFilter 93 return 94 } 95 96 func nFilterParse(helper *ScmpFilterLoadHelper) (scmp *seccomp.ScmpFilter, err error) { 97 if helper.Action&0x10 == 0x10 { 98 err = ErrScmpNotAllowDefaultActionAllow 99 g.GetLog().Warning("{}", err) 100 return 101 } 102 103 switch helper.Action | 0x00 { 104 case 0x00: 105 scmp, err = seccomp.NewFilter(seccomp.ActKill) 106 case 0x01: 107 scmp, err = seccomp.NewFilter(seccomp.ActTrace) 108 case 0x02: 109 scmp, err = seccomp.NewFilter(seccomp.ActErrno.SetReturnCode(EPERM)) 110 case 0x03: 111 scmp, err = seccomp.NewFilter(seccomp.ActErrno.SetReturnCode(ENOSYS)) 112 } 113 114 switch helper.Level { 115 case 1: 116 117 } 118 119 return 120 } 121 122 func scmpToBPF(filter *seccomp.ScmpFilter) (BPF *syscall.SockFprog, err error) { 123 124 scmpBPFTempFile, err := ioutil.TempFile("", "sandbox-ScmpBPF-") 125 defer func() { 126 if scmpBPFTempFile != nil { 127 _ = scmpBPFTempFile.Close() 128 os.Remove(scmpBPFTempFile.Name()) 129 } 130 }() 131 132 if err != nil { 133 g.GetLog().Warning("can not make bpf temp file with error: {}", err) 134 return 135 } 136 137 err = filter.ExportBPF2Fd(scmpBPFTempFile.Fd()) 138 if err != nil { 139 return 140 } 141 _ = scmpBPFTempFile.Sync() 142 143 BpfFileStat, _ := scmpBPFTempFile.Stat() 144 sockFilterFileSize := BpfFileStat.Size() 145 if sockFilterFileSize%8 != 0 { 146 err = errors.New("sockFilterFileSize error " + string(sockFilterFileSize)) 147 return 148 } 149 sockFilters := make([]syscall.SockFilter, sockFilterFileSize/8) 150 var ret = sockFilterFileSize 151 ret, err = scmpBPFTempFile.Seek(0, io.SeekStart) 152 if err != nil { 153 return 154 } 155 if ret != 0 { 156 log.GetLog().Warning("seek fail, ret not at file start, now at:{}", ret) 157 err = errors.New("seek fail, ret not at file start") 158 } 159 160 sockFilterFileContent, err := ioutil.ReadAll(scmpBPFTempFile) 161 bytesBuffer := bytes.NewBuffer(sockFilterFileContent) 162 if helper.IsLittleEndian() { 163 err = binary.Read(bytesBuffer, binary.LittleEndian, &sockFilters) 164 } else { 165 err = binary.Read(bytesBuffer, binary.BigEndian, &sockFilters) 166 } 167 168 BPF = &syscall.SockFprog{ 169 Len: uint16(sockFilterFileSize / 8), 170 Filter: &sockFilters[0], 171 } 172 return 173 }