github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/runsc/cmd/capability.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package cmd 16 17 import ( 18 "fmt" 19 20 specs "github.com/opencontainers/runtime-spec/specs-go" 21 "github.com/syndtr/gocapability/capability" 22 "github.com/SagerNet/gvisor/pkg/log" 23 ) 24 25 var allCapTypes = []capability.CapType{ 26 capability.BOUNDS, 27 capability.EFFECTIVE, 28 capability.PERMITTED, 29 capability.INHERITABLE, 30 capability.AMBIENT, 31 } 32 33 // applyCaps applies the capabilities in the spec to the current thread. 34 // 35 // Note that it must be called with current thread locked. 36 func applyCaps(caps *specs.LinuxCapabilities) error { 37 // Load current capabilities to trim the ones not permitted. 38 curCaps, err := capability.NewPid2(0) 39 if err != nil { 40 return err 41 } 42 if err := curCaps.Load(); err != nil { 43 return err 44 } 45 46 // Create an empty capability set to populate. 47 newCaps, err := capability.NewPid2(0) 48 if err != nil { 49 return err 50 } 51 52 for _, c := range allCapTypes { 53 if !newCaps.Empty(c) { 54 panic("unloaded capabilities must be empty") 55 } 56 set, err := trimCaps(getCaps(c, caps), curCaps) 57 if err != nil { 58 return err 59 } 60 newCaps.Set(c, set...) 61 } 62 63 if err := newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS); err != nil { 64 return err 65 } 66 log.Infof("Capabilities applied: %+v", newCaps) 67 return nil 68 } 69 70 func getCaps(which capability.CapType, caps *specs.LinuxCapabilities) []string { 71 switch which { 72 case capability.BOUNDS: 73 return caps.Bounding 74 case capability.EFFECTIVE: 75 return caps.Effective 76 case capability.PERMITTED: 77 return caps.Permitted 78 case capability.INHERITABLE: 79 return caps.Inheritable 80 case capability.AMBIENT: 81 return caps.Ambient 82 } 83 panic(fmt.Sprint("invalid capability type:", which)) 84 } 85 86 func trimCaps(names []string, setter capability.Capabilities) ([]capability.Cap, error) { 87 wantedCaps, err := capsFromNames(names) 88 if err != nil { 89 return nil, err 90 } 91 92 // Trim down capabilities that aren't possible to acquire. 93 var caps []capability.Cap 94 for _, c := range wantedCaps { 95 // Capability rules are more complicated than this, but this catches most 96 // problems with tests running with non-privileged user. 97 if setter.Get(capability.PERMITTED, c) { 98 caps = append(caps, c) 99 } else { 100 log.Warningf("Capability %q is not permitted, dropping it.", c) 101 } 102 } 103 return caps, nil 104 } 105 106 func capsFromNames(names []string) ([]capability.Cap, error) { 107 var caps []capability.Cap 108 for _, name := range names { 109 cap, ok := capFromName[name] 110 if !ok { 111 return nil, fmt.Errorf("invalid capability %q", name) 112 } 113 caps = append(caps, cap) 114 } 115 return caps, nil 116 } 117 118 var capFromName = map[string]capability.Cap{ 119 "CAP_CHOWN": capability.CAP_CHOWN, 120 "CAP_DAC_OVERRIDE": capability.CAP_DAC_OVERRIDE, 121 "CAP_DAC_READ_SEARCH": capability.CAP_DAC_READ_SEARCH, 122 "CAP_FOWNER": capability.CAP_FOWNER, 123 "CAP_FSETID": capability.CAP_FSETID, 124 "CAP_KILL": capability.CAP_KILL, 125 "CAP_SETGID": capability.CAP_SETGID, 126 "CAP_SETUID": capability.CAP_SETUID, 127 "CAP_SETPCAP": capability.CAP_SETPCAP, 128 "CAP_LINUX_IMMUTABLE": capability.CAP_LINUX_IMMUTABLE, 129 "CAP_NET_BIND_SERVICE": capability.CAP_NET_BIND_SERVICE, 130 "CAP_NET_BROADCAST": capability.CAP_NET_BROADCAST, 131 "CAP_NET_ADMIN": capability.CAP_NET_ADMIN, 132 "CAP_NET_RAW": capability.CAP_NET_RAW, 133 "CAP_IPC_LOCK": capability.CAP_IPC_LOCK, 134 "CAP_IPC_OWNER": capability.CAP_IPC_OWNER, 135 "CAP_SYS_MODULE": capability.CAP_SYS_MODULE, 136 "CAP_SYS_RAWIO": capability.CAP_SYS_RAWIO, 137 "CAP_SYS_CHROOT": capability.CAP_SYS_CHROOT, 138 "CAP_SYS_PTRACE": capability.CAP_SYS_PTRACE, 139 "CAP_SYS_PACCT": capability.CAP_SYS_PACCT, 140 "CAP_SYS_ADMIN": capability.CAP_SYS_ADMIN, 141 "CAP_SYS_BOOT": capability.CAP_SYS_BOOT, 142 "CAP_SYS_NICE": capability.CAP_SYS_NICE, 143 "CAP_SYS_RESOURCE": capability.CAP_SYS_RESOURCE, 144 "CAP_SYS_TIME": capability.CAP_SYS_TIME, 145 "CAP_SYS_TTY_CONFIG": capability.CAP_SYS_TTY_CONFIG, 146 "CAP_MKNOD": capability.CAP_MKNOD, 147 "CAP_LEASE": capability.CAP_LEASE, 148 "CAP_AUDIT_WRITE": capability.CAP_AUDIT_WRITE, 149 "CAP_AUDIT_CONTROL": capability.CAP_AUDIT_CONTROL, 150 "CAP_SETFCAP": capability.CAP_SETFCAP, 151 "CAP_MAC_OVERRIDE": capability.CAP_MAC_OVERRIDE, 152 "CAP_MAC_ADMIN": capability.CAP_MAC_ADMIN, 153 "CAP_SYSLOG": capability.CAP_SYSLOG, 154 "CAP_WAKE_ALARM": capability.CAP_WAKE_ALARM, 155 "CAP_BLOCK_SUSPEND": capability.CAP_BLOCK_SUSPEND, 156 "CAP_AUDIT_READ": capability.CAP_AUDIT_READ, 157 }