1/* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15*/ 16 17// Package cap provides Linux capability utility 18package cap 19 20import ( 21 "bufio" 22 "io" 23 "os" 24 "strconv" 25 "strings" 26 27 "github.com/pkg/errors" 28) 29 30// FromNumber returns a cap string like "CAP_SYS_ADMIN" 31// that corresponds to the given number like 21. 32// 33// FromNumber returns an empty string for unknown cap number. 34func FromNumber(num int) string { 35 if num < 0 || num > len(capsLatest)-1 { 36 return "" 37 } 38 return capsLatest[num] 39} 40 41// FromBitmap parses an uint64 bitmap into string slice like 42// []{"CAP_SYS_ADMIN", ...}. 43// 44// Unknown cap numbers are returned as []int. 45func FromBitmap(v uint64) ([]string, []int) { 46 var ( 47 res []string 48 unknown []int 49 ) 50 for i := 0; i <= 63; i++ { 51 if b := (v >> i) & 0x1; b == 0x1 { 52 if s := FromNumber(i); s != "" { 53 res = append(res, s) 54 } else { 55 unknown = append(unknown, i) 56 } 57 } 58 } 59 return res, unknown 60} 61 62// Type is the type of capability 63type Type int 64 65const ( 66 // Effective is CapEff 67 Effective Type = 1 << iota 68 // Permitted is CapPrm 69 Permitted 70 // Inheritable is CapInh 71 Inheritable 72 // Bounding is CapBnd 73 Bounding 74 // Ambient is CapAmb 75 Ambient 76) 77 78// ParseProcPIDStatus returns uint64 bitmap value from /proc/<PID>/status file 79func ParseProcPIDStatus(r io.Reader) (map[Type]uint64, error) { 80 res := make(map[Type]uint64) 81 scanner := bufio.NewScanner(r) 82 for scanner.Scan() { 83 line := scanner.Text() 84 pair := strings.SplitN(line, ":", 2) 85 if len(pair) != 2 { 86 continue 87 } 88 k := strings.TrimSpace(pair[0]) 89 v := strings.TrimSpace(pair[1]) 90 switch k { 91 case "CapInh", "CapPrm", "CapEff", "CapBnd", "CapAmb": 92 ui64, err := strconv.ParseUint(v, 16, 64) 93 if err != nil { 94 return nil, errors.Errorf("failed to parse line %q", line) 95 } 96 switch k { 97 case "CapInh": 98 res[Inheritable] = ui64 99 case "CapPrm": 100 res[Permitted] = ui64 101 case "CapEff": 102 res[Effective] = ui64 103 case "CapBnd": 104 res[Bounding] = ui64 105 case "CapAmb": 106 res[Ambient] = ui64 107 } 108 } 109 } 110 if err := scanner.Err(); err != nil { 111 return nil, err 112 } 113 return res, nil 114} 115 116// Current returns the list of the effective and the known caps of 117// the current process. 118// 119// The result is like []string{"CAP_SYS_ADMIN", ...}. 120// 121// The result does not contain caps that are not recognized by 122// the "github.com/syndtr/gocapability" library. 123func Current() ([]string, error) { 124 f, err := os.Open("/proc/self/status") 125 if err != nil { 126 return nil, err 127 } 128 defer f.Close() 129 caps, err := ParseProcPIDStatus(f) 130 if err != nil { 131 return nil, err 132 } 133 capEff := caps[Effective] 134 names, _ := FromBitmap(capEff) 135 return names, nil 136} 137 138var ( 139 // caps35 is the caps of kernel 3.5 (37 entries) 140 caps35 = []string{ 141 "CAP_CHOWN", // 2.2 142 "CAP_DAC_OVERRIDE", // 2.2 143 "CAP_DAC_READ_SEARCH", // 2.2 144 "CAP_FOWNER", // 2.2 145 "CAP_FSETID", // 2.2 146 "CAP_KILL", // 2.2 147 "CAP_SETGID", // 2.2 148 "CAP_SETUID", // 2.2 149 "CAP_SETPCAP", // 2.2 150 "CAP_LINUX_IMMUTABLE", // 2.2 151 "CAP_NET_BIND_SERVICE", // 2.2 152 "CAP_NET_BROADCAST", // 2.2 153 "CAP_NET_ADMIN", // 2.2 154 "CAP_NET_RAW", // 2.2 155 "CAP_IPC_LOCK", // 2.2 156 "CAP_IPC_OWNER", // 2.2 157 "CAP_SYS_MODULE", // 2.2 158 "CAP_SYS_RAWIO", // 2.2 159 "CAP_SYS_CHROOT", // 2.2 160 "CAP_SYS_PTRACE", // 2.2 161 "CAP_SYS_PACCT", // 2.2 162 "CAP_SYS_ADMIN", // 2.2 163 "CAP_SYS_BOOT", // 2.2 164 "CAP_SYS_NICE", // 2.2 165 "CAP_SYS_RESOURCE", // 2.2 166 "CAP_SYS_TIME", // 2.2 167 "CAP_SYS_TTY_CONFIG", // 2.2 168 "CAP_MKNOD", // 2.4 169 "CAP_LEASE", // 2.4 170 "CAP_AUDIT_WRITE", // 2.6.11 171 "CAP_AUDIT_CONTROL", // 2.6.11 172 "CAP_SETFCAP", // 2.6.24 173 "CAP_MAC_OVERRIDE", // 2.6.25 174 "CAP_MAC_ADMIN", // 2.6.25 175 "CAP_SYSLOG", // 2.6.37 176 "CAP_WAKE_ALARM", // 3.0 177 "CAP_BLOCK_SUSPEND", // 3.5 178 } 179 // caps316 is the caps of kernel 3.16 (38 entries) 180 caps316 = append(caps35, "CAP_AUDIT_READ") 181 // caps58 is the caps of kernel 5.8 (40 entries) 182 caps58 = append(caps316, []string{"CAP_PERFMON", "CAP_BPF"}...) 183 // caps59 is the caps of kernel 5.9 (41 entries) 184 caps59 = append(caps58, "CAP_CHECKPOINT_RESTORE") 185 capsLatest = caps59 186) 187 188// Known returns the known cap strings of the latest kernel. 189// The current latest kernel is 5.9. 190func Known() []string { 191 return capsLatest 192} 193