github.com/hms58/moby@v1.13.1/profiles/seccomp/seccomp.go (about) 1 // +build linux 2 3 package seccomp 4 5 import ( 6 "encoding/json" 7 "errors" 8 "fmt" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/pkg/stringutils" 12 "github.com/opencontainers/runtime-spec/specs-go" 13 libseccomp "github.com/seccomp/libseccomp-golang" 14 ) 15 16 //go:generate go run -tags 'seccomp' generate.go 17 18 // GetDefaultProfile returns the default seccomp profile. 19 func GetDefaultProfile(rs *specs.Spec) (*specs.Seccomp, error) { 20 return setupSeccomp(DefaultProfile(), rs) 21 } 22 23 // LoadProfile takes a file path and decodes the seccomp profile. 24 func LoadProfile(body string, rs *specs.Spec) (*specs.Seccomp, error) { 25 var config types.Seccomp 26 if err := json.Unmarshal([]byte(body), &config); err != nil { 27 return nil, fmt.Errorf("Decoding seccomp profile failed: %v", err) 28 } 29 return setupSeccomp(&config, rs) 30 } 31 32 var nativeToSeccomp = map[string]types.Arch{ 33 "amd64": types.ArchX86_64, 34 "arm64": types.ArchAARCH64, 35 "mips64": types.ArchMIPS64, 36 "mips64n32": types.ArchMIPS64N32, 37 "mipsel64": types.ArchMIPSEL64, 38 "mipsel64n32": types.ArchMIPSEL64N32, 39 "s390x": types.ArchS390X, 40 } 41 42 func setupSeccomp(config *types.Seccomp, rs *specs.Spec) (*specs.Seccomp, error) { 43 if config == nil { 44 return nil, nil 45 } 46 47 // No default action specified, no syscalls listed, assume seccomp disabled 48 if config.DefaultAction == "" && len(config.Syscalls) == 0 { 49 return nil, nil 50 } 51 52 newConfig := &specs.Seccomp{} 53 54 var arch string 55 var native, err = libseccomp.GetNativeArch() 56 if err == nil { 57 arch = native.String() 58 } 59 60 if len(config.Architectures) != 0 && len(config.ArchMap) != 0 { 61 return nil, errors.New("'architectures' and 'archMap' were specified in the seccomp profile, use either 'architectures' or 'archMap'") 62 } 63 64 // if config.Architectures == 0 then libseccomp will figure out the architecture to use 65 if len(config.Architectures) != 0 { 66 for _, a := range config.Architectures { 67 newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a)) 68 } 69 } 70 71 if len(config.ArchMap) != 0 { 72 for _, a := range config.ArchMap { 73 seccompArch, ok := nativeToSeccomp[arch] 74 if ok { 75 if a.Arch == seccompArch { 76 newConfig.Architectures = append(newConfig.Architectures, specs.Arch(a.Arch)) 77 for _, sa := range a.SubArches { 78 newConfig.Architectures = append(newConfig.Architectures, specs.Arch(sa)) 79 } 80 break 81 } 82 } 83 } 84 } 85 86 newConfig.DefaultAction = specs.Action(config.DefaultAction) 87 88 Loop: 89 // Loop through all syscall blocks and convert them to libcontainer format after filtering them 90 for _, call := range config.Syscalls { 91 if len(call.Excludes.Arches) > 0 { 92 if stringutils.InSlice(call.Excludes.Arches, arch) { 93 continue Loop 94 } 95 } 96 if len(call.Excludes.Caps) > 0 { 97 for _, c := range call.Excludes.Caps { 98 if stringutils.InSlice(rs.Process.Capabilities, c) { 99 continue Loop 100 } 101 } 102 } 103 if len(call.Includes.Arches) > 0 { 104 if !stringutils.InSlice(call.Includes.Arches, arch) { 105 continue Loop 106 } 107 } 108 if len(call.Includes.Caps) > 0 { 109 for _, c := range call.Includes.Caps { 110 if !stringutils.InSlice(rs.Process.Capabilities, c) { 111 continue Loop 112 } 113 } 114 } 115 116 if call.Name != "" && len(call.Names) != 0 { 117 return nil, errors.New("'name' and 'names' were specified in the seccomp profile, use either 'name' or 'names'") 118 } 119 120 if call.Name != "" { 121 newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(call.Name, call.Action, call.Args)) 122 } 123 124 for _, n := range call.Names { 125 newConfig.Syscalls = append(newConfig.Syscalls, createSpecsSyscall(n, call.Action, call.Args)) 126 } 127 } 128 129 return newConfig, nil 130 } 131 132 func createSpecsSyscall(name string, action types.Action, args []*types.Arg) specs.Syscall { 133 newCall := specs.Syscall{ 134 Name: name, 135 Action: specs.Action(action), 136 } 137 138 // Loop through all the arguments of the syscall and convert them 139 for _, arg := range args { 140 newArg := specs.Arg{ 141 Index: arg.Index, 142 Value: arg.Value, 143 ValueTwo: arg.ValueTwo, 144 Op: specs.Operator(arg.Op), 145 } 146 147 newCall.Args = append(newCall.Args, newArg) 148 } 149 return newCall 150 }