 bbe46b8c43
			
		
	
	bbe46b8c43
	
	
	
		
			
			Signed-off-by: haoyun <yun.hao@daocloud.io> Co-authored-by: zounengren <zouyee1989@gmail.com>
		
			
				
	
	
		
			189 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			4.7 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 provides Linux capability utility
 | |
| package cap
 | |
| 
 | |
| import (
 | |
| 	"bufio"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 	"os"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| )
 | |
| 
 | |
| // FromNumber returns a cap string like "CAP_SYS_ADMIN"
 | |
| // that corresponds to the given number like 21.
 | |
| //
 | |
| // FromNumber returns an empty string for unknown cap number.
 | |
| func FromNumber(num int) string {
 | |
| 	if num < 0 || num > len(capsLatest)-1 {
 | |
| 		return ""
 | |
| 	}
 | |
| 	return capsLatest[num]
 | |
| }
 | |
| 
 | |
| // FromBitmap parses an uint64 bitmap into string slice like
 | |
| // []{"CAP_SYS_ADMIN", ...}.
 | |
| //
 | |
| // Unknown cap numbers are returned as []int.
 | |
| func FromBitmap(v uint64) ([]string, []int) {
 | |
| 	var (
 | |
| 		res     []string
 | |
| 		unknown []int
 | |
| 	)
 | |
| 	for i := 0; i <= 63; i++ {
 | |
| 		if b := (v >> i) & 0x1; b == 0x1 {
 | |
| 			if s := FromNumber(i); s != "" {
 | |
| 				res = append(res, s)
 | |
| 			} else {
 | |
| 				unknown = append(unknown, i)
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	return res, unknown
 | |
| }
 | |
| 
 | |
| // Type is the type of capability
 | |
| type Type int
 | |
| 
 | |
| const (
 | |
| 	// Effective is CapEff
 | |
| 	Effective Type = 1 << iota
 | |
| 	// Permitted is CapPrm
 | |
| 	Permitted
 | |
| 	// Inheritable is CapInh
 | |
| 	Inheritable
 | |
| 	// Bounding is CapBnd
 | |
| 	Bounding
 | |
| 	// Ambient is CapAmb
 | |
| 	Ambient
 | |
| )
 | |
| 
 | |
| // ParseProcPIDStatus returns uint64 bitmap value from /proc/<PID>/status file
 | |
| func ParseProcPIDStatus(r io.Reader) (map[Type]uint64, error) {
 | |
| 	res := make(map[Type]uint64)
 | |
| 	scanner := bufio.NewScanner(r)
 | |
| 	for scanner.Scan() {
 | |
| 		line := scanner.Text()
 | |
| 		pair := strings.SplitN(line, ":", 2)
 | |
| 		if len(pair) != 2 {
 | |
| 			continue
 | |
| 		}
 | |
| 		k := strings.TrimSpace(pair[0])
 | |
| 		v := strings.TrimSpace(pair[1])
 | |
| 		switch k {
 | |
| 		case "CapInh", "CapPrm", "CapEff", "CapBnd", "CapAmb":
 | |
| 			ui64, err := strconv.ParseUint(v, 16, 64)
 | |
| 			if err != nil {
 | |
| 				return nil, fmt.Errorf("failed to parse line %q", line)
 | |
| 			}
 | |
| 			switch k {
 | |
| 			case "CapInh":
 | |
| 				res[Inheritable] = ui64
 | |
| 			case "CapPrm":
 | |
| 				res[Permitted] = ui64
 | |
| 			case "CapEff":
 | |
| 				res[Effective] = ui64
 | |
| 			case "CapBnd":
 | |
| 				res[Bounding] = ui64
 | |
| 			case "CapAmb":
 | |
| 				res[Ambient] = ui64
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 	if err := scanner.Err(); err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	return res, nil
 | |
| }
 | |
| 
 | |
| // Current returns the list of the effective and the known caps of
 | |
| // the current process.
 | |
| //
 | |
| // The result is like []string{"CAP_SYS_ADMIN", ...}.
 | |
| func Current() ([]string, error) {
 | |
| 	f, err := os.Open("/proc/self/status")
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	defer f.Close()
 | |
| 	caps, err := ParseProcPIDStatus(f)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	capEff := caps[Effective]
 | |
| 	names, _ := FromBitmap(capEff)
 | |
| 	return names, nil
 | |
| }
 | |
| 
 | |
| var (
 | |
| 	// caps35 is the caps of kernel 3.5 (37 entries)
 | |
| 	caps35 = []string{
 | |
| 		"CAP_CHOWN",            // 2.2
 | |
| 		"CAP_DAC_OVERRIDE",     // 2.2
 | |
| 		"CAP_DAC_READ_SEARCH",  // 2.2
 | |
| 		"CAP_FOWNER",           // 2.2
 | |
| 		"CAP_FSETID",           // 2.2
 | |
| 		"CAP_KILL",             // 2.2
 | |
| 		"CAP_SETGID",           // 2.2
 | |
| 		"CAP_SETUID",           // 2.2
 | |
| 		"CAP_SETPCAP",          // 2.2
 | |
| 		"CAP_LINUX_IMMUTABLE",  // 2.2
 | |
| 		"CAP_NET_BIND_SERVICE", // 2.2
 | |
| 		"CAP_NET_BROADCAST",    // 2.2
 | |
| 		"CAP_NET_ADMIN",        // 2.2
 | |
| 		"CAP_NET_RAW",          // 2.2
 | |
| 		"CAP_IPC_LOCK",         // 2.2
 | |
| 		"CAP_IPC_OWNER",        // 2.2
 | |
| 		"CAP_SYS_MODULE",       // 2.2
 | |
| 		"CAP_SYS_RAWIO",        // 2.2
 | |
| 		"CAP_SYS_CHROOT",       // 2.2
 | |
| 		"CAP_SYS_PTRACE",       // 2.2
 | |
| 		"CAP_SYS_PACCT",        // 2.2
 | |
| 		"CAP_SYS_ADMIN",        // 2.2
 | |
| 		"CAP_SYS_BOOT",         // 2.2
 | |
| 		"CAP_SYS_NICE",         // 2.2
 | |
| 		"CAP_SYS_RESOURCE",     // 2.2
 | |
| 		"CAP_SYS_TIME",         // 2.2
 | |
| 		"CAP_SYS_TTY_CONFIG",   // 2.2
 | |
| 		"CAP_MKNOD",            // 2.4
 | |
| 		"CAP_LEASE",            // 2.4
 | |
| 		"CAP_AUDIT_WRITE",      // 2.6.11
 | |
| 		"CAP_AUDIT_CONTROL",    // 2.6.11
 | |
| 		"CAP_SETFCAP",          // 2.6.24
 | |
| 		"CAP_MAC_OVERRIDE",     // 2.6.25
 | |
| 		"CAP_MAC_ADMIN",        // 2.6.25
 | |
| 		"CAP_SYSLOG",           // 2.6.37
 | |
| 		"CAP_WAKE_ALARM",       // 3.0
 | |
| 		"CAP_BLOCK_SUSPEND",    // 3.5
 | |
| 	}
 | |
| 	// caps316 is the caps of kernel 3.16 (38 entries)
 | |
| 	caps316 = append(caps35, "CAP_AUDIT_READ")
 | |
| 	// caps58 is the caps of kernel 5.8 (40 entries)
 | |
| 	caps58 = append(caps316, []string{"CAP_PERFMON", "CAP_BPF"}...)
 | |
| 	// caps59 is the caps of kernel 5.9 (41 entries)
 | |
| 	caps59     = append(caps58, "CAP_CHECKPOINT_RESTORE")
 | |
| 	capsLatest = caps59
 | |
| )
 | |
| 
 | |
| // Known returns the known cap strings of the latest kernel.
 | |
| // The current latest kernel is 5.9.
 | |
| func Known() []string {
 | |
| 	return capsLatest
 | |
| }
 |