1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
// Copyright (c) 2020, Sylabs Inc. All rights reserved.
// This software is licensed under a 3-clause BSD license. Please consult the
// LICENSE.md file distributed with the sources of this project regarding your
// rights to use or distribute this software.
package capabilities
import (
"fmt"
"golang.org/x/sys/unix"
)
// getProcessCapabilities returns capabilities either effective,
// permitted or inheritable for the current process.
func getProcessCapabilities() ([2]unix.CapUserData, error) {
var data [2]unix.CapUserData
var header unix.CapUserHeader
header.Version = unix.LINUX_CAPABILITY_VERSION_3
if err := unix.Capget(&header, &data[0]); err != nil {
return data, fmt.Errorf("while getting capability: %s", err)
}
return data, nil
}
// GetProcessEffective returns effective capabilities for
// the current process.
func GetProcessEffective() (uint64, error) {
data, err := getProcessCapabilities()
if err != nil {
return 0, err
}
return uint64(data[0].Effective) | uint64(data[1].Effective)<<32, nil
}
// GetProcessPermitted returns permitted capabilities for
// the current process.
func GetProcessPermitted() (uint64, error) {
data, err := getProcessCapabilities()
if err != nil {
return 0, err
}
return uint64(data[0].Permitted) | uint64(data[1].Permitted)<<32, nil
}
// GetProcessInheritable returns inheritable capabilities for
// the current process.
func GetProcessInheritable() (uint64, error) {
data, err := getProcessCapabilities()
if err != nil {
return 0, err
}
return uint64(data[0].Inheritable) | uint64(data[1].Inheritable)<<32, nil
}
// GetProcessBounding returns bounding capabilities for
// the current process.
func GetProcessBounding() (uint64, error) {
data, err := getProcessCapabilities()
if err != nil {
return 0, err
}
return uint64(data[0].Inheritable) | uint64(data[1].Inheritable)<<32, nil
}
// SetProcessEffective set effective capabilities for the current process and
// returns previous effective set.
func SetProcessEffective(caps uint64) (uint64, error) {
var data [2]unix.CapUserData
var header unix.CapUserHeader
header.Version = unix.LINUX_CAPABILITY_VERSION_3
data, err := getProcessCapabilities()
if err != nil {
return 0, err
}
oldEffective := uint64(data[0].Effective) | uint64(data[1].Effective)<<32
data[0].Effective = uint32(caps)
data[1].Effective = uint32(caps >> 32)
effective := uint64(data[0].Effective) | uint64(data[1].Effective)<<32
permitted := uint64(data[0].Permitted) | uint64(data[1].Permitted)<<32
for i := 0; i <= len(Map); i++ {
if effective&uint64(1<<i) != 0 {
if permitted&uint64(1<<i) != 0 {
continue
}
strCap := "UNKNOWN"
for _, cap := range Map {
if uint(i) == cap.Value {
strCap = cap.Name
break
}
}
err := fmt.Sprintf("%s is not in the permitted capability set", strCap)
return 0, fmt.Errorf("while setting effective capabilities: %s", err)
}
}
if err := unix.Capset(&header, &data[0]); err != nil {
return 0, fmt.Errorf("while setting effective capabilities: %s", err)
}
return oldEffective, nil
}
|