Update runc to v1.0.0-rc91
https://github.com/opencontainers/runc/releases/tag/v1.0.0-rc91 Signed-off-by: Davanum Srinivas <davanum@gmail.com>
This commit is contained in:
parent
c91c72c867
commit
963625d7bc
47
vendor.conf
47
vendor.conf
@ -17,7 +17,7 @@ github.com/docker/go-units v0.4.0
|
|||||||
github.com/godbus/dbus/v5 v5.0.3
|
github.com/godbus/dbus/v5 v5.0.3
|
||||||
github.com/gogo/googleapis v1.3.2
|
github.com/gogo/googleapis v1.3.2
|
||||||
github.com/gogo/protobuf v1.3.1
|
github.com/gogo/protobuf v1.3.1
|
||||||
github.com/golang/protobuf v1.3.3
|
github.com/golang/protobuf v1.3.5
|
||||||
github.com/google/go-cmp v0.2.0
|
github.com/google/go-cmp v0.2.0
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||||
@ -31,13 +31,13 @@ github.com/Microsoft/go-winio v0.4.14
|
|||||||
github.com/Microsoft/hcsshim v0.8.9
|
github.com/Microsoft/hcsshim v0.8.9
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/runc v1.0.0-rc10
|
github.com/opencontainers/runc v1.0.0-rc91
|
||||||
github.com/opencontainers/runtime-spec v1.0.2
|
github.com/opencontainers/runtime-spec 237cc4f519e2e8f9b235bacccfa8ef5a84df2875 # v1.0.3-0.20200520003142-237cc4f519e2
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.3.0
|
github.com/prometheus/client_golang v1.6.0
|
||||||
github.com/prometheus/client_model v0.1.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/common v0.7.0
|
github.com/prometheus/common v0.9.1
|
||||||
github.com/prometheus/procfs v0.0.8
|
github.com/prometheus/procfs v0.0.11
|
||||||
github.com/russross/blackfriday/v2 v2.0.1
|
github.com/russross/blackfriday/v2 v2.0.1
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0
|
github.com/shurcooL/sanitized_anchor_name v1.0.0
|
||||||
github.com/sirupsen/logrus v1.6.0
|
github.com/sirupsen/logrus v1.6.0
|
||||||
@ -47,42 +47,41 @@ go.etcd.io/bbolt v1.3.5
|
|||||||
go.opencensus.io v0.22.0
|
go.opencensus.io v0.22.0
|
||||||
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
||||||
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||||
golang.org/x/sys 5c8b2ff67527cb88b770f693cebf3799036d8bc0
|
golang.org/x/sys 9dae0f8f577553e0f21298e18926efc9644c281d
|
||||||
golang.org/x/text v0.3.3
|
golang.org/x/text v0.3.3
|
||||||
google.golang.org/genproto e50cd9704f63023d62cd06a1994b98227fc4d21a
|
google.golang.org/genproto e50cd9704f63023d62cd06a1994b98227fc4d21a
|
||||||
google.golang.org/grpc v1.27.1
|
google.golang.org/grpc v1.27.1
|
||||||
gotest.tools/v3 v3.0.2
|
gotest.tools/v3 v3.0.2
|
||||||
|
|
||||||
# cgroups dependencies
|
# cgroups dependencies
|
||||||
github.com/cilium/ebpf 4032b1d8aae306b7bb94a2a11002932caf88c644
|
github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28
|
||||||
|
|
||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/containerd/cri 4f8a580795344b0f4c1146a3abce0409962f3890 # master
|
github.com/containerd/cri aa0f4fd37b82a273156d35a7e13831bd0940ab99 # master
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
||||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||||
github.com/emicklei/go-restful v2.9.5
|
github.com/emicklei/go-restful v2.9.5
|
||||||
|
github.com/go-logr/logr v0.2.0
|
||||||
github.com/google/gofuzz v1.1.0
|
github.com/google/gofuzz v1.1.0
|
||||||
github.com/json-iterator/go v1.1.8
|
github.com/json-iterator/go v1.1.9
|
||||||
github.com/modern-go/concurrent 1.0.3
|
github.com/modern-go/concurrent 1.0.3
|
||||||
github.com/modern-go/reflect2 v1.0.1
|
github.com/modern-go/reflect2 v1.0.1
|
||||||
github.com/opencontainers/selinux bb88c45a3863dc4c38320d71b890bb30ef9feba4
|
github.com/opencontainers/selinux v1.5.1
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1
|
github.com/seccomp/libseccomp-golang v0.9.1
|
||||||
github.com/stretchr/testify v1.4.0
|
|
||||||
github.com/tchap/go-patricia v2.2.6
|
github.com/tchap/go-patricia v2.2.6
|
||||||
golang.org/x/crypto bac4c82f69751a6dd76e702d54b3ceb88adab236
|
golang.org/x/crypto bac4c82f69751a6dd76e702d54b3ceb88adab236
|
||||||
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
golang.org/x/oauth2 858c2ad4c8b6c5d10852cb89079f6ca1c7309787
|
||||||
golang.org/x/time 9d24e82272b4f38b78bc8cff74fa936d31ccd8ef
|
golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82
|
||||||
gopkg.in/inf.v0 v0.9.1
|
gopkg.in/inf.v0 v0.9.1
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/api v0.18.2
|
k8s.io/api v0.19.0-beta.2
|
||||||
k8s.io/apimachinery v0.18.2
|
k8s.io/apimachinery v0.19.0-beta.2
|
||||||
k8s.io/apiserver v0.18.2
|
k8s.io/apiserver v0.19.0-beta.2
|
||||||
k8s.io/client-go v0.18.2
|
k8s.io/client-go v0.19.0-beta.2
|
||||||
k8s.io/cri-api v0.18.2
|
k8s.io/cri-api v0.19.0-beta.2
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog/v2 v2.2.0
|
||||||
k8s.io/kubernetes v1.18.2
|
k8s.io/utils 2df71ebbae66f39338aed4cd0bb82d2212ee33cc
|
||||||
k8s.io/utils a9aa75ae1b89e1b992c33383f48e942d97e52dae
|
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
|
|
||||||
@ -90,7 +89,7 @@ sigs.k8s.io/yaml v1.2.0
|
|||||||
github.com/containerd/go-cni v1.0.0
|
github.com/containerd/go-cni v1.0.0
|
||||||
github.com/containernetworking/cni v0.7.1
|
github.com/containernetworking/cni v0.7.1
|
||||||
github.com/containernetworking/plugins v0.7.6
|
github.com/containernetworking/plugins v0.7.6
|
||||||
github.com/fsnotify/fsnotify v1.4.8
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
|
|
||||||
# image decrypt depedencies
|
# image decrypt depedencies
|
||||||
github.com/containerd/imgcrypt v1.0.1
|
github.com/containerd/imgcrypt v1.0.1
|
||||||
|
16
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
16
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
@ -3,14 +3,13 @@ package ebpf
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// MapABI are the attributes of a Map which are available across all supported kernels.
|
// MapABI are the attributes of a Map which are available across all supported kernels.
|
||||||
@ -35,7 +34,7 @@ func newMapABIFromSpec(spec *MapSpec) *MapABI {
|
|||||||
func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
|
func newMapABIFromFd(fd *internal.FD) (string, *MapABI, error) {
|
||||||
info, err := bpfGetMapInfoByFD(fd)
|
info, err := bpfGetMapInfoByFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == syscall.EINVAL {
|
if errors.Is(err, syscall.EINVAL) {
|
||||||
abi, err := newMapABIFromProc(fd)
|
abi, err := newMapABIFromProc(fd)
|
||||||
return "", abi, err
|
return "", abi, err
|
||||||
}
|
}
|
||||||
@ -98,7 +97,7 @@ func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI {
|
|||||||
func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) {
|
func newProgramABIFromFd(fd *internal.FD) (string, *ProgramABI, error) {
|
||||||
info, err := bpfGetProgInfoByFD(fd)
|
info, err := bpfGetProgInfoByFD(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == syscall.EINVAL {
|
if errors.Is(err, syscall.EINVAL) {
|
||||||
return newProgramABIFromProc(fd)
|
return newProgramABIFromProc(fd)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,7 +126,7 @@ func newProgramABIFromProc(fd *internal.FD) (string, *ProgramABI, error) {
|
|||||||
"prog_type": &abi.Type,
|
"prog_type": &abi.Type,
|
||||||
"prog_tag": &name,
|
"prog_tag": &name,
|
||||||
})
|
})
|
||||||
if errors.Cause(err) == errMissingFields {
|
if errors.Is(err, errMissingFields) {
|
||||||
return "", nil, &internal.UnsupportedFeatureError{
|
return "", nil, &internal.UnsupportedFeatureError{
|
||||||
Name: "reading ABI from /proc/self/fdinfo",
|
Name: "reading ABI from /proc/self/fdinfo",
|
||||||
MinimumVersion: internal.Version{4, 11, 0},
|
MinimumVersion: internal.Version{4, 11, 0},
|
||||||
@ -152,7 +151,10 @@ func scanFdInfo(fd *internal.FD, fields map[string]interface{}) error {
|
|||||||
}
|
}
|
||||||
defer fh.Close()
|
defer fh.Close()
|
||||||
|
|
||||||
return errors.Wrap(scanFdInfoReader(fh, fields), fh.Name())
|
if err := scanFdInfoReader(fh, fields); err != nil {
|
||||||
|
return fmt.Errorf("%s: %w", fh.Name(), err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errMissingFields = errors.New("missing fields")
|
var errMissingFields = errors.New("missing fields")
|
||||||
@ -176,7 +178,7 @@ func scanFdInfoReader(r io.Reader, fields map[string]interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if n, err := fmt.Fscanln(bytes.NewReader(parts[1]), field); err != nil || n != 1 {
|
if n, err := fmt.Fscanln(bytes.NewReader(parts[1]), field); err != nil || n != 1 {
|
||||||
return errors.Wrapf(err, "can't parse field %s", name)
|
return fmt.Errorf("can't parse field %s: %v", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
scanned++
|
scanned++
|
||||||
|
114
vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
114
vendor/github.com/cilium/ebpf/asm/instruction.go
generated
vendored
@ -2,12 +2,11 @@ package asm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// InstructionSize is the size of a BPF instruction in bytes
|
// InstructionSize is the size of a BPF instruction in bytes
|
||||||
@ -39,10 +38,12 @@ func (ins *Instruction) Unmarshal(r io.Reader, bo binary.ByteOrder) (uint64, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
ins.OpCode = bi.OpCode
|
ins.OpCode = bi.OpCode
|
||||||
ins.Dst = bi.Registers.Dst()
|
|
||||||
ins.Src = bi.Registers.Src()
|
|
||||||
ins.Offset = bi.Offset
|
ins.Offset = bi.Offset
|
||||||
ins.Constant = int64(bi.Constant)
|
ins.Constant = int64(bi.Constant)
|
||||||
|
ins.Dst, ins.Src, err = bi.Registers.Unmarshal(bo)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("can't unmarshal registers: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
if !bi.OpCode.isDWordLoad() {
|
if !bi.OpCode.isDWordLoad() {
|
||||||
return InstructionSize, nil
|
return InstructionSize, nil
|
||||||
@ -75,9 +76,14 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
|
|||||||
cons = int32(uint32(ins.Constant))
|
cons = int32(uint32(ins.Constant))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
regs, err := newBPFRegisters(ins.Dst, ins.Src, bo)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("can't marshal registers: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
bpfi := bpfInstruction{
|
bpfi := bpfInstruction{
|
||||||
ins.OpCode,
|
ins.OpCode,
|
||||||
newBPFRegisters(ins.Dst, ins.Src),
|
regs,
|
||||||
ins.Offset,
|
ins.Offset,
|
||||||
cons,
|
cons,
|
||||||
}
|
}
|
||||||
@ -103,22 +109,52 @@ func (ins Instruction) Marshal(w io.Writer, bo binary.ByteOrder) (uint64, error)
|
|||||||
|
|
||||||
// RewriteMapPtr changes an instruction to use a new map fd.
|
// RewriteMapPtr changes an instruction to use a new map fd.
|
||||||
//
|
//
|
||||||
// Returns an error if the fd is invalid, or the instruction
|
// Returns an error if the instruction doesn't load a map.
|
||||||
// is incorrect.
|
|
||||||
func (ins *Instruction) RewriteMapPtr(fd int) error {
|
func (ins *Instruction) RewriteMapPtr(fd int) error {
|
||||||
if !ins.OpCode.isDWordLoad() {
|
if !ins.OpCode.isDWordLoad() {
|
||||||
return errors.Errorf("%s is not a 64 bit load", ins.OpCode)
|
return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fd < 0 {
|
if ins.Src != PseudoMapFD && ins.Src != PseudoMapValue {
|
||||||
return errors.New("invalid fd")
|
return errors.New("not a load from a map")
|
||||||
}
|
}
|
||||||
|
|
||||||
ins.Src = R1
|
// Preserve the offset value for direct map loads.
|
||||||
ins.Constant = int64(fd)
|
offset := uint64(ins.Constant) & (math.MaxUint32 << 32)
|
||||||
|
rawFd := uint64(uint32(fd))
|
||||||
|
ins.Constant = int64(offset | rawFd)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ins *Instruction) mapPtr() uint32 {
|
||||||
|
return uint32(uint64(ins.Constant) & math.MaxUint32)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewriteMapOffset changes the offset of a direct load from a map.
|
||||||
|
//
|
||||||
|
// Returns an error if the instruction is not a direct load.
|
||||||
|
func (ins *Instruction) RewriteMapOffset(offset uint32) error {
|
||||||
|
if !ins.OpCode.isDWordLoad() {
|
||||||
|
return fmt.Errorf("%s is not a 64 bit load", ins.OpCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ins.Src != PseudoMapValue {
|
||||||
|
return errors.New("not a direct load from a map")
|
||||||
|
}
|
||||||
|
|
||||||
|
fd := uint64(ins.Constant) & math.MaxUint32
|
||||||
|
ins.Constant = int64(uint64(offset)<<32 | fd)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ins *Instruction) mapOffset() uint32 {
|
||||||
|
return uint32(uint64(ins.Constant) >> 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ins *Instruction) isLoadFromMap() bool {
|
||||||
|
return ins.OpCode == LoadImmOp(DWord) && (ins.Src == PseudoMapFD || ins.Src == PseudoMapValue)
|
||||||
|
}
|
||||||
|
|
||||||
// Format implements fmt.Formatter.
|
// Format implements fmt.Formatter.
|
||||||
func (ins Instruction) Format(f fmt.State, c rune) {
|
func (ins Instruction) Format(f fmt.State, c rune) {
|
||||||
if c != 'v' {
|
if c != 'v' {
|
||||||
@ -139,6 +175,19 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ins.isLoadFromMap() {
|
||||||
|
fd := int32(ins.mapPtr())
|
||||||
|
switch ins.Src {
|
||||||
|
case PseudoMapFD:
|
||||||
|
fmt.Fprintf(f, "LoadMapPtr dst: %s fd: %d", ins.Dst, fd)
|
||||||
|
|
||||||
|
case PseudoMapValue:
|
||||||
|
fmt.Fprintf(f, "LoadMapValue dst: %s, fd: %d off: %d", ins.Dst, fd, ins.mapOffset())
|
||||||
|
}
|
||||||
|
|
||||||
|
goto ref
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Fprintf(f, "%v ", op)
|
fmt.Fprintf(f, "%v ", op)
|
||||||
switch cls := op.Class(); cls {
|
switch cls := op.Class(); cls {
|
||||||
case LdClass, LdXClass, StClass, StXClass:
|
case LdClass, LdXClass, StClass, StXClass:
|
||||||
@ -166,7 +215,7 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
|||||||
case JumpClass:
|
case JumpClass:
|
||||||
switch jop := op.JumpOp(); jop {
|
switch jop := op.JumpOp(); jop {
|
||||||
case Call:
|
case Call:
|
||||||
if ins.Src == R1 {
|
if ins.Src == PseudoCall {
|
||||||
// bpf-to-bpf call
|
// bpf-to-bpf call
|
||||||
fmt.Fprint(f, ins.Constant)
|
fmt.Fprint(f, ins.Constant)
|
||||||
} else {
|
} else {
|
||||||
@ -183,6 +232,7 @@ func (ins Instruction) Format(f fmt.State, c rune) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ref:
|
||||||
if ins.Reference != "" {
|
if ins.Reference != "" {
|
||||||
fmt.Fprintf(f, " <%s>", ins.Reference)
|
fmt.Fprintf(f, " <%s>", ins.Reference)
|
||||||
}
|
}
|
||||||
@ -235,7 +285,7 @@ func (insns Instructions) SymbolOffsets() (map[string]int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := offsets[ins.Symbol]; ok {
|
if _, ok := offsets[ins.Symbol]; ok {
|
||||||
return nil, errors.Errorf("duplicate symbol %s", ins.Symbol)
|
return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
offsets[ins.Symbol] = i
|
offsets[ins.Symbol] = i
|
||||||
@ -273,7 +323,7 @@ func (insns Instructions) marshalledOffsets() (map[string]int, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := symbols[ins.Symbol]; ok {
|
if _, ok := symbols[ins.Symbol]; ok {
|
||||||
return nil, errors.Errorf("duplicate symbol %s", ins.Symbol)
|
return nil, fmt.Errorf("duplicate symbol %s", ins.Symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
symbols[ins.Symbol] = currentPos
|
symbols[ins.Symbol] = currentPos
|
||||||
@ -350,11 +400,11 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
|
|||||||
num := 0
|
num := 0
|
||||||
for i, ins := range insns {
|
for i, ins := range insns {
|
||||||
switch {
|
switch {
|
||||||
case ins.OpCode.JumpOp() == Call && ins.Constant == -1:
|
case ins.OpCode.JumpOp() == Call && ins.Src == PseudoCall && ins.Constant == -1:
|
||||||
// Rewrite bpf to bpf call
|
// Rewrite bpf to bpf call
|
||||||
offset, ok := absoluteOffsets[ins.Reference]
|
offset, ok := absoluteOffsets[ins.Reference]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
|
return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
ins.Constant = int64(offset - num - 1)
|
ins.Constant = int64(offset - num - 1)
|
||||||
@ -363,7 +413,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
|
|||||||
// Rewrite jump to label
|
// Rewrite jump to label
|
||||||
offset, ok := absoluteOffsets[ins.Reference]
|
offset, ok := absoluteOffsets[ins.Reference]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
|
return fmt.Errorf("instruction %d: reference to missing symbol %s", i, ins.Reference)
|
||||||
}
|
}
|
||||||
|
|
||||||
ins.Offset = int16(offset - num - 1)
|
ins.Offset = int16(offset - num - 1)
|
||||||
@ -371,7 +421,7 @@ func (insns Instructions) Marshal(w io.Writer, bo binary.ByteOrder) error {
|
|||||||
|
|
||||||
n, err := ins.Marshal(w, bo)
|
n, err := ins.Marshal(w, bo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "instruction %d", i)
|
return fmt.Errorf("instruction %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
num += int(n / InstructionSize)
|
num += int(n / InstructionSize)
|
||||||
@ -388,16 +438,26 @@ type bpfInstruction struct {
|
|||||||
|
|
||||||
type bpfRegisters uint8
|
type bpfRegisters uint8
|
||||||
|
|
||||||
func newBPFRegisters(dst, src Register) bpfRegisters {
|
func newBPFRegisters(dst, src Register, bo binary.ByteOrder) (bpfRegisters, error) {
|
||||||
return bpfRegisters((src << 4) | (dst & 0xF))
|
switch bo {
|
||||||
|
case binary.LittleEndian:
|
||||||
|
return bpfRegisters((src << 4) | (dst & 0xF)), nil
|
||||||
|
case binary.BigEndian:
|
||||||
|
return bpfRegisters((dst << 4) | (src & 0xF)), nil
|
||||||
|
default:
|
||||||
|
return 0, fmt.Errorf("unrecognized ByteOrder %T", bo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r bpfRegisters) Dst() Register {
|
func (r bpfRegisters) Unmarshal(bo binary.ByteOrder) (dst, src Register, err error) {
|
||||||
return Register(r & 0xF)
|
switch bo {
|
||||||
}
|
case binary.LittleEndian:
|
||||||
|
return Register(r & 0xF), Register(r >> 4), nil
|
||||||
func (r bpfRegisters) Src() Register {
|
case binary.BigEndian:
|
||||||
return Register(r >> 4)
|
return Register(r >> 4), Register(r & 0xf), nil
|
||||||
|
default:
|
||||||
|
return 0, 0, fmt.Errorf("unrecognized ByteOrder %T", bo)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type unreferencedSymbolError struct {
|
type unreferencedSymbolError struct {
|
||||||
|
2
vendor/github.com/cilium/ebpf/asm/jump.go
generated
vendored
2
vendor/github.com/cilium/ebpf/asm/jump.go
generated
vendored
@ -95,7 +95,7 @@ func (op JumpOp) Label(label string) Instruction {
|
|||||||
if op == Call {
|
if op == Call {
|
||||||
return Instruction{
|
return Instruction{
|
||||||
OpCode: OpCode(JumpClass).SetJumpOp(Call),
|
OpCode: OpCode(JumpClass).SetJumpOp(Call),
|
||||||
Src: R1,
|
Src: PseudoCall,
|
||||||
Constant: -1,
|
Constant: -1,
|
||||||
Reference: label,
|
Reference: label,
|
||||||
}
|
}
|
||||||
|
17
vendor/github.com/cilium/ebpf/asm/load_store.go
generated
vendored
17
vendor/github.com/cilium/ebpf/asm/load_store.go
generated
vendored
@ -110,11 +110,26 @@ func LoadMapPtr(dst Register, fd int) Instruction {
|
|||||||
return Instruction{
|
return Instruction{
|
||||||
OpCode: LoadImmOp(DWord),
|
OpCode: LoadImmOp(DWord),
|
||||||
Dst: dst,
|
Dst: dst,
|
||||||
Src: R1,
|
Src: PseudoMapFD,
|
||||||
Constant: int64(fd),
|
Constant: int64(fd),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LoadMapValue stores a pointer to the value at a certain offset of a map.
|
||||||
|
func LoadMapValue(dst Register, fd int, offset uint32) Instruction {
|
||||||
|
if fd < 0 {
|
||||||
|
return Instruction{OpCode: InvalidOpCode}
|
||||||
|
}
|
||||||
|
|
||||||
|
fdAndOffset := (uint64(offset) << 32) | uint64(uint32(fd))
|
||||||
|
return Instruction{
|
||||||
|
OpCode: LoadImmOp(DWord),
|
||||||
|
Dst: dst,
|
||||||
|
Src: PseudoMapValue,
|
||||||
|
Constant: int64(fdAndOffset),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// LoadIndOp returns the OpCode for loading a value of given size from an sk_buff.
|
// LoadIndOp returns the OpCode for loading a value of given size from an sk_buff.
|
||||||
func LoadIndOp(size Size) OpCode {
|
func LoadIndOp(size Size) OpCode {
|
||||||
return OpCode(LdClass).SetMode(IndMode).SetSize(size)
|
return OpCode(LdClass).SetMode(IndMode).SetSize(size)
|
||||||
|
2
vendor/github.com/cilium/ebpf/asm/opcode.go
generated
vendored
2
vendor/github.com/cilium/ebpf/asm/opcode.go
generated
vendored
@ -225,7 +225,7 @@ func (op OpCode) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(&f, "%#x", op)
|
fmt.Fprintf(&f, "OpCode(%#x)", uint8(op))
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.String()
|
return f.String()
|
||||||
|
7
vendor/github.com/cilium/ebpf/asm/register.go
generated
vendored
7
vendor/github.com/cilium/ebpf/asm/register.go
generated
vendored
@ -33,6 +33,13 @@ const (
|
|||||||
RFP = R10
|
RFP = R10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Pseudo registers used by 64bit loads and jumps
|
||||||
|
const (
|
||||||
|
PseudoMapFD = R1 // BPF_PSEUDO_MAP_FD
|
||||||
|
PseudoMapValue = R2 // BPF_PSEUDO_MAP_VALUE
|
||||||
|
PseudoCall = R1 // BPF_PSEUDO_CALL
|
||||||
|
)
|
||||||
|
|
||||||
func (r Register) String() string {
|
func (r Register) String() string {
|
||||||
v := uint8(r)
|
v := uint8(r)
|
||||||
if v == 10 {
|
if v == 10 {
|
||||||
|
117
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
117
vendor/github.com/cilium/ebpf/collection.go
generated
vendored
@ -1,9 +1,13 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CollectionOptions control loading a collection into the kernel.
|
// CollectionOptions control loading a collection into the kernel.
|
||||||
@ -39,6 +43,89 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
|
|||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RewriteMaps replaces all references to specific maps.
|
||||||
|
//
|
||||||
|
// Use this function to use pre-existing maps instead of creating new ones
|
||||||
|
// when calling NewCollection. Any named maps are removed from CollectionSpec.Maps.
|
||||||
|
//
|
||||||
|
// Returns an error if a named map isn't used in at least one program.
|
||||||
|
func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
|
||||||
|
for symbol, m := range maps {
|
||||||
|
// have we seen a program that uses this symbol / map
|
||||||
|
seen := false
|
||||||
|
fd := m.FD()
|
||||||
|
for progName, progSpec := range cs.Programs {
|
||||||
|
err := progSpec.Instructions.RewriteMapPtr(symbol, fd)
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case err == nil:
|
||||||
|
seen = true
|
||||||
|
|
||||||
|
case asm.IsUnreferencedSymbol(err):
|
||||||
|
// Not all programs need to use the map
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("program %s: %w", progName, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !seen {
|
||||||
|
return fmt.Errorf("map %s not referenced by any programs", symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent NewCollection from creating rewritten maps
|
||||||
|
delete(cs.Maps, symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RewriteConstants replaces the value of multiple constants.
|
||||||
|
//
|
||||||
|
// The constant must be defined like so in the C program:
|
||||||
|
//
|
||||||
|
// static volatile const type foobar;
|
||||||
|
// static volatile const type foobar = default;
|
||||||
|
//
|
||||||
|
// Replacement values must be of the same length as the C sizeof(type).
|
||||||
|
// If necessary, they are marshalled according to the same rules as
|
||||||
|
// map values.
|
||||||
|
//
|
||||||
|
// From Linux 5.5 the verifier will use constants to eliminate dead code.
|
||||||
|
//
|
||||||
|
// Returns an error if a constant doesn't exist.
|
||||||
|
func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error {
|
||||||
|
rodata := cs.Maps[".rodata"]
|
||||||
|
if rodata == nil {
|
||||||
|
return errors.New("missing .rodata section")
|
||||||
|
}
|
||||||
|
|
||||||
|
if rodata.BTF == nil {
|
||||||
|
return errors.New(".rodata section has no BTF")
|
||||||
|
}
|
||||||
|
|
||||||
|
if n := len(rodata.Contents); n != 1 {
|
||||||
|
return fmt.Errorf("expected one key in .rodata, found %d", n)
|
||||||
|
}
|
||||||
|
|
||||||
|
kv := rodata.Contents[0]
|
||||||
|
value, ok := kv.Value.([]byte)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("first value in .rodata is %T not []byte", kv.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := make([]byte, len(value))
|
||||||
|
copy(buf, value)
|
||||||
|
|
||||||
|
err := patchValue(buf, btf.MapValue(rodata.BTF), consts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rodata.Contents[0] = MapKV{kv.Key, buf}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Collection is a collection of Programs and Maps associated
|
// Collection is a collection of Programs and Maps associated
|
||||||
// with their symbols
|
// with their symbols
|
||||||
type Collection struct {
|
type Collection struct {
|
||||||
@ -99,14 +186,14 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col
|
|||||||
var handle *btf.Handle
|
var handle *btf.Handle
|
||||||
if mapSpec.BTF != nil {
|
if mapSpec.BTF != nil {
|
||||||
handle, err = loadBTF(btf.MapSpec(mapSpec.BTF))
|
handle, err = loadBTF(btf.MapSpec(mapSpec.BTF))
|
||||||
if err != nil && !btf.IsNotSupported(err) {
|
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := newMapWithBTF(mapSpec, handle)
|
m, err := newMapWithBTF(mapSpec, handle)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "map %s", mapName)
|
return nil, fmt.Errorf("map %s: %w", mapName, err)
|
||||||
}
|
}
|
||||||
maps[mapName] = m
|
maps[mapName] = m
|
||||||
}
|
}
|
||||||
@ -116,37 +203,43 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (col
|
|||||||
|
|
||||||
// Rewrite any reference to a valid map.
|
// Rewrite any reference to a valid map.
|
||||||
for i := range progSpec.Instructions {
|
for i := range progSpec.Instructions {
|
||||||
var (
|
ins := &progSpec.Instructions[i]
|
||||||
ins = &progSpec.Instructions[i]
|
|
||||||
m = maps[ins.Reference]
|
|
||||||
)
|
|
||||||
|
|
||||||
if ins.Reference == "" || m == nil {
|
if ins.OpCode != asm.LoadImmOp(asm.DWord) || ins.Reference == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ins.Src == asm.R1 {
|
if uint32(ins.Constant) != math.MaxUint32 {
|
||||||
// Don't overwrite maps already rewritten, users can
|
// Don't overwrite maps already rewritten, users can
|
||||||
// rewrite programs in the spec themselves
|
// rewrite programs in the spec themselves
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m := maps[ins.Reference]
|
||||||
|
if m == nil {
|
||||||
|
return nil, fmt.Errorf("program %s: missing map %s", progName, ins.Reference)
|
||||||
|
}
|
||||||
|
|
||||||
|
fd := m.FD()
|
||||||
|
if fd < 0 {
|
||||||
|
return nil, fmt.Errorf("map %s: %w", ins.Reference, internal.ErrClosedFd)
|
||||||
|
}
|
||||||
if err := ins.RewriteMapPtr(m.FD()); err != nil {
|
if err := ins.RewriteMapPtr(m.FD()); err != nil {
|
||||||
return nil, errors.Wrapf(err, "progam %s: map %s", progName, ins.Reference)
|
return nil, fmt.Errorf("progam %s: map %s: %w", progName, ins.Reference, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var handle *btf.Handle
|
var handle *btf.Handle
|
||||||
if progSpec.BTF != nil {
|
if progSpec.BTF != nil {
|
||||||
handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF))
|
handle, err = loadBTF(btf.ProgramSpec(progSpec.BTF))
|
||||||
if err != nil && !btf.IsNotSupported(err) {
|
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prog, err := newProgramWithBTF(progSpec, handle, opts.Programs)
|
prog, err := newProgramWithBTF(progSpec, handle, opts.Programs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "program %s", progName)
|
return nil, fmt.Errorf("program %s: %w", progName, err)
|
||||||
}
|
}
|
||||||
progs[progName] = prog
|
progs[progName] = prog
|
||||||
}
|
}
|
||||||
|
607
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
607
vendor/github.com/cilium/ebpf/elf_reader.go
generated
vendored
@ -4,21 +4,23 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type elfCode struct {
|
type elfCode struct {
|
||||||
*elf.File
|
*elf.File
|
||||||
symbols []elf.Symbol
|
symbols []elf.Symbol
|
||||||
symbolsPerSection map[elf.SectionIndex]map[uint64]string
|
symbolsPerSection map[elf.SectionIndex]map[uint64]elf.Symbol
|
||||||
license string
|
license string
|
||||||
version uint32
|
version uint32
|
||||||
}
|
}
|
||||||
@ -32,7 +34,10 @@ func LoadCollectionSpec(file string) (*CollectionSpec, error) {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
spec, err := LoadCollectionSpecFromReader(f)
|
spec, err := LoadCollectionSpecFromReader(f)
|
||||||
return spec, errors.Wrapf(err, "file %s", file)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("file %s: %w", file, err)
|
||||||
|
}
|
||||||
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
|
// LoadCollectionSpecFromReader parses an ELF file into a CollectionSpec.
|
||||||
@ -45,7 +50,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
|
|
||||||
symbols, err := f.Symbols()
|
symbols, err := f.Symbols()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load symbols")
|
return nil, fmt.Errorf("load symbols: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0}
|
ec := &elfCode{f, symbols, symbolsPerSection(symbols), "", 0}
|
||||||
@ -57,6 +62,7 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
progSections = make(map[elf.SectionIndex]*elf.Section)
|
progSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
relSections = make(map[elf.SectionIndex]*elf.Section)
|
relSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
mapSections = make(map[elf.SectionIndex]*elf.Section)
|
mapSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
|
dataSections = make(map[elf.SectionIndex]*elf.Section)
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, sec := range ec.Sections {
|
for i, sec := range ec.Sections {
|
||||||
@ -69,15 +75,17 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
mapSections[elf.SectionIndex(i)] = sec
|
mapSections[elf.SectionIndex(i)] = sec
|
||||||
case sec.Name == ".maps":
|
case sec.Name == ".maps":
|
||||||
btfMaps[elf.SectionIndex(i)] = sec
|
btfMaps[elf.SectionIndex(i)] = sec
|
||||||
|
case sec.Name == ".bss" || sec.Name == ".rodata" || sec.Name == ".data":
|
||||||
|
dataSections[elf.SectionIndex(i)] = sec
|
||||||
case sec.Type == elf.SHT_REL:
|
case sec.Type == elf.SHT_REL:
|
||||||
if int(sec.Info) >= len(ec.Sections) {
|
if int(sec.Info) >= len(ec.Sections) {
|
||||||
return nil, errors.Errorf("found relocation section %v for missing section %v", i, sec.Info)
|
return nil, fmt.Errorf("found relocation section %v for missing section %v", i, sec.Info)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store relocations under the section index of the target
|
// Store relocations under the section index of the target
|
||||||
idx := elf.SectionIndex(sec.Info)
|
idx := elf.SectionIndex(sec.Info)
|
||||||
if relSections[idx] != nil {
|
if relSections[idx] != nil {
|
||||||
return nil, errors.Errorf("section %d has multiple relocation sections", sec.Info)
|
return nil, fmt.Errorf("section %d has multiple relocation sections", sec.Info)
|
||||||
}
|
}
|
||||||
relSections[idx] = sec
|
relSections[idx] = sec
|
||||||
case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
|
case sec.Type == elf.SHT_PROGBITS && (sec.Flags&elf.SHF_EXECINSTR) != 0 && sec.Size > 0:
|
||||||
@ -87,34 +95,52 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
|
|
||||||
ec.license, err = loadLicense(licenseSection)
|
ec.license, err = loadLicense(licenseSection)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load license")
|
return nil, fmt.Errorf("load license: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ec.version, err = loadVersion(versionSection, ec.ByteOrder)
|
ec.version, err = loadVersion(versionSection, ec.ByteOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load version")
|
return nil, fmt.Errorf("load version: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
btf, err := btf.LoadSpecFromReader(rd)
|
btfSpec, err := btf.LoadSpecFromReader(rd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load BTF")
|
return nil, fmt.Errorf("load BTF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
relocations, referencedSections, err := ec.loadRelocations(relSections)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("load relocations: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
maps := make(map[string]*MapSpec)
|
maps := make(map[string]*MapSpec)
|
||||||
|
|
||||||
if err := ec.loadMaps(maps, mapSections); err != nil {
|
if err := ec.loadMaps(maps, mapSections); err != nil {
|
||||||
return nil, errors.Wrap(err, "load maps")
|
return nil, fmt.Errorf("load maps: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(btfMaps) > 0 {
|
if len(btfMaps) > 0 {
|
||||||
if err := ec.loadBTFMaps(maps, btfMaps, btf); err != nil {
|
if err := ec.loadBTFMaps(maps, btfMaps, btfSpec); err != nil {
|
||||||
return nil, errors.Wrap(err, "load BTF maps")
|
return nil, fmt.Errorf("load BTF maps: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progs, err := ec.loadPrograms(progSections, relSections, btf)
|
if len(dataSections) > 0 {
|
||||||
|
for idx := range dataSections {
|
||||||
|
if !referencedSections[idx] {
|
||||||
|
// Prune data sections which are not referenced by any
|
||||||
|
// instructions.
|
||||||
|
delete(dataSections, idx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ec.loadDataSections(maps, dataSections, btfSpec); err != nil {
|
||||||
|
return nil, fmt.Errorf("load data sections: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
progs, err := ec.loadPrograms(progSections, relocations, btfSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "load programs")
|
return nil, fmt.Errorf("load programs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &CollectionSpec{maps, progs}, nil
|
return &CollectionSpec{maps, progs}, nil
|
||||||
@ -122,11 +148,12 @@ func LoadCollectionSpecFromReader(rd io.ReaderAt) (*CollectionSpec, error) {
|
|||||||
|
|
||||||
func loadLicense(sec *elf.Section) (string, error) {
|
func loadLicense(sec *elf.Section) (string, error) {
|
||||||
if sec == nil {
|
if sec == nil {
|
||||||
return "", errors.Errorf("missing license section")
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := sec.Data()
|
data, err := sec.Data()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", errors.Wrapf(err, "section %s", sec.Name)
|
return "", fmt.Errorf("section %s: %v", sec.Name, err)
|
||||||
}
|
}
|
||||||
return string(bytes.TrimRight(data, "\000")), nil
|
return string(bytes.TrimRight(data, "\000")), nil
|
||||||
}
|
}
|
||||||
@ -137,52 +164,51 @@ func loadVersion(sec *elf.Section, bo binary.ByteOrder) (uint32, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var version uint32
|
var version uint32
|
||||||
err := binary.Read(sec.Open(), bo, &version)
|
if err := binary.Read(sec.Open(), bo, &version); err != nil {
|
||||||
return version, errors.Wrapf(err, "section %s", sec.Name)
|
return 0, fmt.Errorf("section %s: %v", sec.Name, err)
|
||||||
|
}
|
||||||
|
return version, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*elf.Section, btf *btf.Spec) (map[string]*ProgramSpec, error) {
|
func (ec *elfCode) loadPrograms(progSections map[elf.SectionIndex]*elf.Section, relocations map[elf.SectionIndex]map[uint64]elf.Symbol, btfSpec *btf.Spec) (map[string]*ProgramSpec, error) {
|
||||||
var (
|
var (
|
||||||
progs []*ProgramSpec
|
progs []*ProgramSpec
|
||||||
libs []*ProgramSpec
|
libs []*ProgramSpec
|
||||||
)
|
)
|
||||||
|
|
||||||
for idx, prog := range progSections {
|
for idx, sec := range progSections {
|
||||||
syms := ec.symbolsPerSection[idx]
|
syms := ec.symbolsPerSection[idx]
|
||||||
if len(syms) == 0 {
|
if len(syms) == 0 {
|
||||||
return nil, errors.Errorf("section %v: missing symbols", prog.Name)
|
return nil, fmt.Errorf("section %v: missing symbols", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
funcSym := syms[0]
|
funcSym, ok := syms[0]
|
||||||
if funcSym == "" {
|
if !ok {
|
||||||
return nil, errors.Errorf("section %v: no label at start", prog.Name)
|
return nil, fmt.Errorf("section %v: no label at start", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
rels, err := ec.loadRelocations(relSections[idx])
|
insns, length, err := ec.loadInstructions(sec, syms, relocations[idx])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "program %s: can't load relocations", funcSym)
|
return nil, fmt.Errorf("program %s: can't unmarshal instructions: %w", funcSym.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
insns, length, err := ec.loadInstructions(prog, syms, rels)
|
progType, attachType, attachTo := getProgType(sec.Name)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "program %s: can't unmarshal instructions", funcSym)
|
|
||||||
}
|
|
||||||
|
|
||||||
progType, attachType := getProgType(prog.Name)
|
|
||||||
|
|
||||||
spec := &ProgramSpec{
|
spec := &ProgramSpec{
|
||||||
Name: funcSym,
|
Name: funcSym.Name,
|
||||||
Type: progType,
|
Type: progType,
|
||||||
AttachType: attachType,
|
AttachType: attachType,
|
||||||
|
AttachTo: attachTo,
|
||||||
License: ec.license,
|
License: ec.license,
|
||||||
KernelVersion: ec.version,
|
KernelVersion: ec.version,
|
||||||
Instructions: insns,
|
Instructions: insns,
|
||||||
|
ByteOrder: ec.ByteOrder,
|
||||||
}
|
}
|
||||||
|
|
||||||
if btf != nil {
|
if btfSpec != nil {
|
||||||
spec.BTF, err = btf.Program(prog.Name, length)
|
spec.BTF, err = btfSpec.Program(sec.Name, length)
|
||||||
if err != nil {
|
if err != nil && !errors.Is(err, btf.ErrNoExtendedInfo) {
|
||||||
return nil, errors.Wrapf(err, "BTF for section %s (program %s)", prog.Name, funcSym)
|
return nil, fmt.Errorf("program %s: %w", funcSym.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +226,7 @@ func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*
|
|||||||
for _, prog := range progs {
|
for _, prog := range progs {
|
||||||
err := link(prog, libs)
|
err := link(prog, libs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "program %s", prog.Name)
|
return nil, fmt.Errorf("program %s: %w", prog.Name, err)
|
||||||
}
|
}
|
||||||
res[prog.Name] = prog
|
res[prog.Name] = prog
|
||||||
}
|
}
|
||||||
@ -208,39 +234,158 @@ func (ec *elfCode) loadPrograms(progSections, relSections map[elf.SectionIndex]*
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]string) (asm.Instructions, uint64, error) {
|
func (ec *elfCode) loadInstructions(section *elf.Section, symbols, relocations map[uint64]elf.Symbol) (asm.Instructions, uint64, error) {
|
||||||
var (
|
var (
|
||||||
r = section.Open()
|
r = section.Open()
|
||||||
insns asm.Instructions
|
insns asm.Instructions
|
||||||
ins asm.Instruction
|
|
||||||
offset uint64
|
offset uint64
|
||||||
)
|
)
|
||||||
for {
|
for {
|
||||||
|
var ins asm.Instruction
|
||||||
n, err := ins.Unmarshal(r, ec.ByteOrder)
|
n, err := ins.Unmarshal(r, ec.ByteOrder)
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
return insns, offset, nil
|
return insns, offset, nil
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, errors.Wrapf(err, "offset %d", offset)
|
return nil, 0, fmt.Errorf("offset %d: %w", offset, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ins.Symbol = symbols[offset]
|
ins.Symbol = symbols[offset].Name
|
||||||
ins.Reference = relocations[offset]
|
|
||||||
|
if rel, ok := relocations[offset]; ok {
|
||||||
|
if err = ec.relocateInstruction(&ins, rel); err != nil {
|
||||||
|
return nil, 0, fmt.Errorf("offset %d: can't relocate instruction: %w", offset, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
insns = append(insns, ins)
|
insns = append(insns, ins)
|
||||||
offset += n
|
offset += n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ec *elfCode) relocateInstruction(ins *asm.Instruction, rel elf.Symbol) error {
|
||||||
|
var (
|
||||||
|
typ = elf.ST_TYPE(rel.Info)
|
||||||
|
bind = elf.ST_BIND(rel.Info)
|
||||||
|
name = rel.Name
|
||||||
|
)
|
||||||
|
|
||||||
|
if typ == elf.STT_SECTION {
|
||||||
|
// Symbols with section type do not have a name set. Get it
|
||||||
|
// from the section itself.
|
||||||
|
idx := int(rel.Section)
|
||||||
|
if idx > len(ec.Sections) {
|
||||||
|
return errors.New("out-of-bounds section index")
|
||||||
|
}
|
||||||
|
|
||||||
|
name = ec.Sections[idx].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
outer:
|
||||||
|
switch {
|
||||||
|
case ins.OpCode == asm.LoadImmOp(asm.DWord):
|
||||||
|
// There are two distinct types of a load from a map:
|
||||||
|
// a direct one, where the value is extracted without
|
||||||
|
// a call to map_lookup_elem in eBPF, and an indirect one
|
||||||
|
// that goes via the helper. They are distinguished by
|
||||||
|
// different relocations.
|
||||||
|
switch typ {
|
||||||
|
case elf.STT_SECTION:
|
||||||
|
// This is a direct load since the referenced symbol is a
|
||||||
|
// section. Weirdly, the offset of the real symbol in the
|
||||||
|
// section is encoded in the instruction stream.
|
||||||
|
if bind != elf.STB_LOCAL {
|
||||||
|
return fmt.Errorf("direct load: %s: unsupported relocation %s", name, bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
// For some reason, clang encodes the offset of the symbol its
|
||||||
|
// section in the first basic BPF instruction, while the kernel
|
||||||
|
// expects it in the second one.
|
||||||
|
ins.Constant <<= 32
|
||||||
|
ins.Src = asm.PseudoMapValue
|
||||||
|
|
||||||
|
case elf.STT_NOTYPE:
|
||||||
|
if bind == elf.STB_GLOBAL && rel.Section == elf.SHN_UNDEF {
|
||||||
|
// This is a relocation generated by inline assembly.
|
||||||
|
// We can't do more than assigning ins.Reference.
|
||||||
|
break outer
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is an ELF generated on clang < 8, which doesn't tag
|
||||||
|
// relocations appropriately.
|
||||||
|
fallthrough
|
||||||
|
|
||||||
|
case elf.STT_OBJECT:
|
||||||
|
if bind != elf.STB_GLOBAL {
|
||||||
|
return fmt.Errorf("load: %s: unsupported binding: %s", name, bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
ins.Src = asm.PseudoMapFD
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("load: %s: unsupported relocation: %s", name, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the instruction as needing an update when creating the
|
||||||
|
// collection.
|
||||||
|
if err := ins.RewriteMapPtr(-1); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
case ins.OpCode.JumpOp() == asm.Call:
|
||||||
|
if ins.Src != asm.PseudoCall {
|
||||||
|
return fmt.Errorf("call: %s: incorrect source register", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch typ {
|
||||||
|
case elf.STT_NOTYPE, elf.STT_FUNC:
|
||||||
|
if bind != elf.STB_GLOBAL {
|
||||||
|
return fmt.Errorf("call: %s: unsupported binding: %s", name, bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
case elf.STT_SECTION:
|
||||||
|
if bind != elf.STB_LOCAL {
|
||||||
|
return fmt.Errorf("call: %s: unsupported binding: %s", name, bind)
|
||||||
|
}
|
||||||
|
|
||||||
|
// The function we want to call is in the indicated section,
|
||||||
|
// at the offset encoded in the instruction itself. Reverse
|
||||||
|
// the calculation to find the real function we're looking for.
|
||||||
|
// A value of -1 references the first instruction in the section.
|
||||||
|
offset := int64(int32(ins.Constant)+1) * asm.InstructionSize
|
||||||
|
if offset < 0 {
|
||||||
|
return fmt.Errorf("call: %s: invalid offset %d", name, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
sym, ok := ec.symbolsPerSection[rel.Section][uint64(offset)]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("call: %s: no symbol at offset %d", name, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
ins.Constant = -1
|
||||||
|
name = sym.Name
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("call: %s: invalid symbol type %s", name, typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("relocation for unsupported instruction: %s", ins.OpCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
ins.Reference = name
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section) error {
|
func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section) error {
|
||||||
for idx, sec := range mapSections {
|
for idx, sec := range mapSections {
|
||||||
syms := ec.symbolsPerSection[idx]
|
syms := ec.symbolsPerSection[idx]
|
||||||
if len(syms) == 0 {
|
if len(syms) == 0 {
|
||||||
return errors.Errorf("section %v: no symbols", sec.Name)
|
return fmt.Errorf("section %v: no symbols", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sec.Size%uint64(len(syms)) != 0 {
|
if sec.Size%uint64(len(syms)) != 0 {
|
||||||
return errors.Errorf("section %v: map descriptors are not of equal size", sec.Name)
|
return fmt.Errorf("section %v: map descriptors are not of equal size", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -248,36 +393,38 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
|
|||||||
size = sec.Size / uint64(len(syms))
|
size = sec.Size / uint64(len(syms))
|
||||||
)
|
)
|
||||||
for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
|
for i, offset := 0, uint64(0); i < len(syms); i, offset = i+1, offset+size {
|
||||||
mapSym := syms[offset]
|
mapSym, ok := syms[offset]
|
||||||
if mapSym == "" {
|
if !ok {
|
||||||
return errors.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
|
return fmt.Errorf("section %s: missing symbol for map at offset %d", sec.Name, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
if maps[mapSym] != nil {
|
if maps[mapSym.Name] != nil {
|
||||||
return errors.Errorf("section %v: map %v already exists", sec.Name, mapSym)
|
return fmt.Errorf("section %v: map %v already exists", sec.Name, mapSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
lr := io.LimitReader(r, int64(size))
|
lr := io.LimitReader(r, int64(size))
|
||||||
|
|
||||||
var spec MapSpec
|
spec := MapSpec{
|
||||||
|
Name: SanitizeName(mapSym.Name, -1),
|
||||||
|
}
|
||||||
switch {
|
switch {
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.Type) != nil:
|
||||||
return errors.Errorf("map %v: missing type", mapSym)
|
return fmt.Errorf("map %v: missing type", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.KeySize) != nil:
|
||||||
return errors.Errorf("map %v: missing key size", mapSym)
|
return fmt.Errorf("map %v: missing key size", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.ValueSize) != nil:
|
||||||
return errors.Errorf("map %v: missing value size", mapSym)
|
return fmt.Errorf("map %v: missing value size", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.MaxEntries) != nil:
|
||||||
return errors.Errorf("map %v: missing max entries", mapSym)
|
return fmt.Errorf("map %v: missing max entries", mapSym)
|
||||||
case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
|
case binary.Read(lr, ec.ByteOrder, &spec.Flags) != nil:
|
||||||
return errors.Errorf("map %v: missing flags", mapSym)
|
return fmt.Errorf("map %v: missing flags", mapSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
|
if _, err := io.Copy(internal.DiscardZeroes{}, lr); err != nil {
|
||||||
return errors.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
|
return fmt.Errorf("map %v: unknown and non-zero fields in definition", mapSym)
|
||||||
}
|
}
|
||||||
|
|
||||||
maps[mapSym] = &spec
|
maps[mapSym.Name] = &spec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,85 +432,117 @@ func (ec *elfCode) loadMaps(maps map[string]*MapSpec, mapSections map[elf.Sectio
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
|
func (ec *elfCode) loadBTFMaps(maps map[string]*MapSpec, mapSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
|
||||||
|
|
||||||
if spec == nil {
|
if spec == nil {
|
||||||
return errors.Errorf("missing BTF")
|
return fmt.Errorf("missing BTF")
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, sec := range mapSections {
|
for idx, sec := range mapSections {
|
||||||
syms := ec.symbolsPerSection[idx]
|
syms := ec.symbolsPerSection[idx]
|
||||||
if len(syms) == 0 {
|
if len(syms) == 0 {
|
||||||
return errors.Errorf("section %v: no symbols", sec.Name)
|
return fmt.Errorf("section %v: no symbols", sec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, sym := range syms {
|
for _, sym := range syms {
|
||||||
if maps[sym] != nil {
|
name := sym.Name
|
||||||
return errors.Errorf("section %v: map %v already exists", sec.Name, sym)
|
if maps[name] != nil {
|
||||||
|
return fmt.Errorf("section %v: map %v already exists", sec.Name, sym)
|
||||||
}
|
}
|
||||||
|
|
||||||
btfMap, err := spec.Map(sym)
|
mapSpec, err := mapSpecFromBTF(spec, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "map %v: can't get BTF", sym)
|
return fmt.Errorf("map %v: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := mapSpecFromBTF(btfMap)
|
maps[name] = mapSpec
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "map %v", sym)
|
|
||||||
}
|
|
||||||
|
|
||||||
maps[sym] = spec
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapSpecFromBTF(btfMap *btf.Map) (*MapSpec, error) {
|
func mapSpecFromBTF(spec *btf.Spec, name string) (*MapSpec, error) {
|
||||||
|
btfMap, btfMapMembers, err := spec.Map(name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get BTF: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
keyType := btf.MapKey(btfMap)
|
||||||
|
size, err := btf.Sizeof(keyType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get size of BTF key: %w", err)
|
||||||
|
}
|
||||||
|
keySize := uint32(size)
|
||||||
|
|
||||||
|
valueType := btf.MapValue(btfMap)
|
||||||
|
size, err = btf.Sizeof(valueType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get size of BTF value: %w", err)
|
||||||
|
}
|
||||||
|
valueSize := uint32(size)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
mapType, flags, maxEntries uint32
|
mapType, flags, maxEntries uint32
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
for _, member := range btf.MapType(btfMap).Members {
|
for _, member := range btfMapMembers {
|
||||||
switch member.Name {
|
switch member.Name {
|
||||||
case "type":
|
case "type":
|
||||||
mapType, err = uintFromBTF(member.Type)
|
mapType, err = uintFromBTF(member.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get type")
|
return nil, fmt.Errorf("can't get type: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "map_flags":
|
case "map_flags":
|
||||||
flags, err = uintFromBTF(member.Type)
|
flags, err = uintFromBTF(member.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get BTF map flags")
|
return nil, fmt.Errorf("can't get BTF map flags: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "max_entries":
|
case "max_entries":
|
||||||
maxEntries, err = uintFromBTF(member.Type)
|
maxEntries, err = uintFromBTF(member.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get BTF map max entries")
|
return nil, fmt.Errorf("can't get BTF map max entries: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case "key":
|
case "key_size":
|
||||||
case "value":
|
if _, isVoid := keyType.(*btf.Void); !isVoid {
|
||||||
|
return nil, errors.New("both key and key_size given")
|
||||||
|
}
|
||||||
|
|
||||||
|
keySize, err = uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get BTF key size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
case "value_size":
|
||||||
|
if _, isVoid := valueType.(*btf.Void); !isVoid {
|
||||||
|
return nil, errors.New("both value and value_size given")
|
||||||
|
}
|
||||||
|
|
||||||
|
valueSize, err = uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get BTF value size: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
case "pinning":
|
||||||
|
pinning, err := uintFromBTF(member.Type)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get pinning: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if pinning != 0 {
|
||||||
|
return nil, fmt.Errorf("'pinning' attribute not supported: %w", ErrNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
case "key", "value":
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("unrecognized field %s in BTF map definition", member.Name)
|
return nil, fmt.Errorf("unrecognized field %s in BTF map definition", member.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
keySize, err := btf.Sizeof(btf.MapKey(btfMap))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't get size of BTF key")
|
|
||||||
}
|
|
||||||
|
|
||||||
valueSize, err := btf.Sizeof(btf.MapValue(btfMap))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't get size of BTF value")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &MapSpec{
|
return &MapSpec{
|
||||||
Type: MapType(mapType),
|
Type: MapType(mapType),
|
||||||
KeySize: uint32(keySize),
|
KeySize: keySize,
|
||||||
ValueSize: uint32(valueSize),
|
ValueSize: valueSize,
|
||||||
MaxEntries: maxEntries,
|
MaxEntries: maxEntries,
|
||||||
Flags: flags,
|
Flags: flags,
|
||||||
BTF: btfMap,
|
BTF: btfMap,
|
||||||
@ -375,127 +554,163 @@ func mapSpecFromBTF(btfMap *btf.Map) (*MapSpec, error) {
|
|||||||
func uintFromBTF(typ btf.Type) (uint32, error) {
|
func uintFromBTF(typ btf.Type) (uint32, error) {
|
||||||
ptr, ok := typ.(*btf.Pointer)
|
ptr, ok := typ.(*btf.Pointer)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, errors.Errorf("not a pointer: %v", typ)
|
return 0, fmt.Errorf("not a pointer: %v", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
arr, ok := ptr.Target.(*btf.Array)
|
arr, ok := ptr.Target.(*btf.Array)
|
||||||
if !ok {
|
if !ok {
|
||||||
return 0, errors.Errorf("not a pointer to array: %v", typ)
|
return 0, fmt.Errorf("not a pointer to array: %v", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
return arr.Nelems, nil
|
return arr.Nelems, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProgType(v string) (ProgramType, AttachType) {
|
func (ec *elfCode) loadDataSections(maps map[string]*MapSpec, dataSections map[elf.SectionIndex]*elf.Section, spec *btf.Spec) error {
|
||||||
types := map[string]ProgramType{
|
if spec == nil {
|
||||||
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c#n3568
|
return errors.New("data sections require BTF, make sure all consts are marked as static")
|
||||||
"socket": SocketFilter,
|
|
||||||
"seccomp": SocketFilter,
|
|
||||||
"kprobe/": Kprobe,
|
|
||||||
"uprobe/": Kprobe,
|
|
||||||
"kretprobe/": Kprobe,
|
|
||||||
"uretprobe/": Kprobe,
|
|
||||||
"tracepoint/": TracePoint,
|
|
||||||
"raw_tracepoint/": RawTracepoint,
|
|
||||||
"xdp": XDP,
|
|
||||||
"perf_event": PerfEvent,
|
|
||||||
"lwt_in": LWTIn,
|
|
||||||
"lwt_out": LWTOut,
|
|
||||||
"lwt_xmit": LWTXmit,
|
|
||||||
"lwt_seg6local": LWTSeg6Local,
|
|
||||||
"sockops": SockOps,
|
|
||||||
"sk_skb": SkSKB,
|
|
||||||
"sk_msg": SkMsg,
|
|
||||||
"lirc_mode2": LircMode2,
|
|
||||||
"flow_dissector": FlowDissector,
|
|
||||||
|
|
||||||
"cgroup_skb/": CGroupSKB,
|
|
||||||
"cgroup/dev": CGroupDevice,
|
|
||||||
"cgroup/skb": CGroupSKB,
|
|
||||||
"cgroup/sock": CGroupSock,
|
|
||||||
"cgroup/post_bind": CGroupSock,
|
|
||||||
"cgroup/bind": CGroupSockAddr,
|
|
||||||
"cgroup/connect": CGroupSockAddr,
|
|
||||||
"cgroup/sendmsg": CGroupSockAddr,
|
|
||||||
"cgroup/recvmsg": CGroupSockAddr,
|
|
||||||
"cgroup/sysctl": CGroupSysctl,
|
|
||||||
"cgroup/getsockopt": CGroupSockopt,
|
|
||||||
"cgroup/setsockopt": CGroupSockopt,
|
|
||||||
"classifier": SchedCLS,
|
|
||||||
"action": SchedACT,
|
|
||||||
}
|
|
||||||
attachTypes := map[string]AttachType{
|
|
||||||
"cgroup_skb/ingress": AttachCGroupInetIngress,
|
|
||||||
"cgroup_skb/egress": AttachCGroupInetEgress,
|
|
||||||
"cgroup/sock": AttachCGroupInetSockCreate,
|
|
||||||
"cgroup/post_bind4": AttachCGroupInet4PostBind,
|
|
||||||
"cgroup/post_bind6": AttachCGroupInet6PostBind,
|
|
||||||
"cgroup/dev": AttachCGroupDevice,
|
|
||||||
"sockops": AttachCGroupSockOps,
|
|
||||||
"sk_skb/stream_parser": AttachSkSKBStreamParser,
|
|
||||||
"sk_skb/stream_verdict": AttachSkSKBStreamVerdict,
|
|
||||||
"sk_msg": AttachSkSKBStreamVerdict,
|
|
||||||
"lirc_mode2": AttachLircMode2,
|
|
||||||
"flow_dissector": AttachFlowDissector,
|
|
||||||
"cgroup/bind4": AttachCGroupInet4Bind,
|
|
||||||
"cgroup/bind6": AttachCGroupInet6Bind,
|
|
||||||
"cgroup/connect4": AttachCGroupInet4Connect,
|
|
||||||
"cgroup/connect6": AttachCGroupInet6Connect,
|
|
||||||
"cgroup/sendmsg4": AttachCGroupUDP4Sendmsg,
|
|
||||||
"cgroup/sendmsg6": AttachCGroupUDP6Sendmsg,
|
|
||||||
"cgroup/recvmsg4": AttachCGroupUDP4Recvmsg,
|
|
||||||
"cgroup/recvmsg6": AttachCGroupUDP6Recvmsg,
|
|
||||||
"cgroup/sysctl": AttachCGroupSysctl,
|
|
||||||
"cgroup/getsockopt": AttachCGroupGetsockopt,
|
|
||||||
"cgroup/setsockopt": AttachCGroupSetsockopt,
|
|
||||||
}
|
|
||||||
attachType := AttachNone
|
|
||||||
for k, t := range attachTypes {
|
|
||||||
if strings.HasPrefix(v, k) {
|
|
||||||
attachType = t
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, t := range types {
|
for _, sec := range dataSections {
|
||||||
if strings.HasPrefix(v, k) {
|
btfMap, err := spec.Datasec(sec.Name)
|
||||||
return t, attachType
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data, err := sec.Data()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if uint64(len(data)) > math.MaxUint32 {
|
||||||
|
return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
mapSpec := &MapSpec{
|
||||||
|
Name: SanitizeName(sec.Name, -1),
|
||||||
|
Type: Array,
|
||||||
|
KeySize: 4,
|
||||||
|
ValueSize: uint32(len(data)),
|
||||||
|
MaxEntries: 1,
|
||||||
|
Contents: []MapKV{{uint32(0), data}},
|
||||||
|
BTF: btfMap,
|
||||||
|
}
|
||||||
|
|
||||||
|
switch sec.Name {
|
||||||
|
case ".rodata":
|
||||||
|
mapSpec.Flags = unix.BPF_F_RDONLY_PROG
|
||||||
|
mapSpec.Freeze = true
|
||||||
|
case ".bss":
|
||||||
|
// The kernel already zero-initializes the map
|
||||||
|
mapSpec.Contents = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
maps[sec.Name] = mapSpec
|
||||||
}
|
}
|
||||||
return UnspecifiedProgram, AttachNone
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ec *elfCode) loadRelocations(sec *elf.Section) (map[uint64]string, error) {
|
func getProgType(sectionName string) (ProgramType, AttachType, string) {
|
||||||
rels := make(map[uint64]string)
|
types := map[string]struct {
|
||||||
if sec == nil {
|
progType ProgramType
|
||||||
return rels, nil
|
attachType AttachType
|
||||||
|
}{
|
||||||
|
// From https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/lib/bpf/libbpf.c
|
||||||
|
"socket": {SocketFilter, AttachNone},
|
||||||
|
"seccomp": {SocketFilter, AttachNone},
|
||||||
|
"kprobe/": {Kprobe, AttachNone},
|
||||||
|
"uprobe/": {Kprobe, AttachNone},
|
||||||
|
"kretprobe/": {Kprobe, AttachNone},
|
||||||
|
"uretprobe/": {Kprobe, AttachNone},
|
||||||
|
"tracepoint/": {TracePoint, AttachNone},
|
||||||
|
"raw_tracepoint/": {RawTracepoint, AttachNone},
|
||||||
|
"xdp": {XDP, AttachNone},
|
||||||
|
"perf_event": {PerfEvent, AttachNone},
|
||||||
|
"lwt_in": {LWTIn, AttachNone},
|
||||||
|
"lwt_out": {LWTOut, AttachNone},
|
||||||
|
"lwt_xmit": {LWTXmit, AttachNone},
|
||||||
|
"lwt_seg6local": {LWTSeg6Local, AttachNone},
|
||||||
|
"sockops": {SockOps, AttachCGroupSockOps},
|
||||||
|
"sk_skb/stream_parser": {SkSKB, AttachSkSKBStreamParser},
|
||||||
|
"sk_skb/stream_verdict": {SkSKB, AttachSkSKBStreamParser},
|
||||||
|
"sk_msg": {SkMsg, AttachSkSKBStreamVerdict},
|
||||||
|
"lirc_mode2": {LircMode2, AttachLircMode2},
|
||||||
|
"flow_dissector": {FlowDissector, AttachFlowDissector},
|
||||||
|
"iter/": {Tracing, AttachTraceIter},
|
||||||
|
|
||||||
|
"cgroup_skb/ingress": {CGroupSKB, AttachCGroupInetIngress},
|
||||||
|
"cgroup_skb/egress": {CGroupSKB, AttachCGroupInetEgress},
|
||||||
|
"cgroup/dev": {CGroupDevice, AttachCGroupDevice},
|
||||||
|
"cgroup/skb": {CGroupSKB, AttachNone},
|
||||||
|
"cgroup/sock": {CGroupSock, AttachCGroupInetSockCreate},
|
||||||
|
"cgroup/post_bind4": {CGroupSock, AttachCGroupInet4PostBind},
|
||||||
|
"cgroup/post_bind6": {CGroupSock, AttachCGroupInet6PostBind},
|
||||||
|
"cgroup/bind4": {CGroupSockAddr, AttachCGroupInet4Bind},
|
||||||
|
"cgroup/bind6": {CGroupSockAddr, AttachCGroupInet6Bind},
|
||||||
|
"cgroup/connect4": {CGroupSockAddr, AttachCGroupInet4Connect},
|
||||||
|
"cgroup/connect6": {CGroupSockAddr, AttachCGroupInet6Connect},
|
||||||
|
"cgroup/sendmsg4": {CGroupSockAddr, AttachCGroupUDP4Sendmsg},
|
||||||
|
"cgroup/sendmsg6": {CGroupSockAddr, AttachCGroupUDP6Sendmsg},
|
||||||
|
"cgroup/recvmsg4": {CGroupSockAddr, AttachCGroupUDP4Recvmsg},
|
||||||
|
"cgroup/recvmsg6": {CGroupSockAddr, AttachCGroupUDP6Recvmsg},
|
||||||
|
"cgroup/sysctl": {CGroupSysctl, AttachCGroupSysctl},
|
||||||
|
"cgroup/getsockopt": {CGroupSockopt, AttachCGroupGetsockopt},
|
||||||
|
"cgroup/setsockopt": {CGroupSockopt, AttachCGroupSetsockopt},
|
||||||
|
"classifier": {SchedCLS, AttachNone},
|
||||||
|
"action": {SchedACT, AttachNone},
|
||||||
}
|
}
|
||||||
|
|
||||||
if sec.Entsize < 16 {
|
for prefix, t := range types {
|
||||||
return nil, errors.New("rels are less than 16 bytes")
|
if !strings.HasPrefix(sectionName, prefix) {
|
||||||
}
|
continue
|
||||||
|
|
||||||
r := sec.Open()
|
|
||||||
for off := uint64(0); off < sec.Size; off += sec.Entsize {
|
|
||||||
ent := io.LimitReader(r, int64(sec.Entsize))
|
|
||||||
|
|
||||||
var rel elf.Rel64
|
|
||||||
if binary.Read(ent, ec.ByteOrder, &rel) != nil {
|
|
||||||
return nil, errors.Errorf("can't parse relocation at offset %v", off)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
symNo := int(elf.R_SYM64(rel.Info) - 1)
|
if !strings.HasSuffix(prefix, "/") {
|
||||||
if symNo >= len(ec.symbols) {
|
return t.progType, t.attachType, ""
|
||||||
return nil, errors.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rels[rel.Off] = ec.symbols[symNo].Name
|
return t.progType, t.attachType, sectionName[len(prefix):]
|
||||||
}
|
}
|
||||||
return rels, nil
|
|
||||||
|
return UnspecifiedProgram, AttachNone, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]string {
|
func (ec *elfCode) loadRelocations(sections map[elf.SectionIndex]*elf.Section) (map[elf.SectionIndex]map[uint64]elf.Symbol, map[elf.SectionIndex]bool, error) {
|
||||||
result := make(map[elf.SectionIndex]map[uint64]string)
|
result := make(map[elf.SectionIndex]map[uint64]elf.Symbol)
|
||||||
for i, sym := range symbols {
|
targets := make(map[elf.SectionIndex]bool)
|
||||||
|
for idx, sec := range sections {
|
||||||
|
rels := make(map[uint64]elf.Symbol)
|
||||||
|
|
||||||
|
if sec.Entsize < 16 {
|
||||||
|
return nil, nil, fmt.Errorf("section %s: relocations are less than 16 bytes", sec.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
r := sec.Open()
|
||||||
|
for off := uint64(0); off < sec.Size; off += sec.Entsize {
|
||||||
|
ent := io.LimitReader(r, int64(sec.Entsize))
|
||||||
|
|
||||||
|
var rel elf.Rel64
|
||||||
|
if binary.Read(ent, ec.ByteOrder, &rel) != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't parse relocation at offset %v", off)
|
||||||
|
}
|
||||||
|
|
||||||
|
symNo := int(elf.R_SYM64(rel.Info) - 1)
|
||||||
|
if symNo >= len(ec.symbols) {
|
||||||
|
return nil, nil, fmt.Errorf("relocation at offset %d: symbol %v doesnt exist", off, symNo)
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol := ec.symbols[symNo]
|
||||||
|
targets[symbol.Section] = true
|
||||||
|
rels[rel.Off] = ec.symbols[symNo]
|
||||||
|
}
|
||||||
|
|
||||||
|
result[idx] = rels
|
||||||
|
}
|
||||||
|
return result, targets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]elf.Symbol {
|
||||||
|
result := make(map[elf.SectionIndex]map[uint64]elf.Symbol)
|
||||||
|
for _, sym := range symbols {
|
||||||
switch elf.ST_TYPE(sym.Info) {
|
switch elf.ST_TYPE(sym.Info) {
|
||||||
case elf.STT_NOTYPE:
|
case elf.STT_NOTYPE:
|
||||||
// Older versions of LLVM doesn't tag
|
// Older versions of LLVM doesn't tag
|
||||||
@ -509,15 +724,19 @@ func symbolsPerSection(symbols []elf.Symbol) map[elf.SectionIndex]map[uint64]str
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if sym.Section == elf.SHN_UNDEF || sym.Section >= elf.SHN_LORESERVE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if sym.Name == "" {
|
if sym.Name == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
idx := sym.Section
|
idx := sym.Section
|
||||||
if _, ok := result[idx]; !ok {
|
if _, ok := result[idx]; !ok {
|
||||||
result[idx] = make(map[uint64]string)
|
result[idx] = make(map[uint64]elf.Symbol)
|
||||||
}
|
}
|
||||||
result[idx][sym.Value] = symbols[i].Name
|
result[idx][sym.Value] = sym
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
7
vendor/github.com/cilium/ebpf/go.mod
generated
vendored
7
vendor/github.com/cilium/ebpf/go.mod
generated
vendored
@ -1,8 +1,5 @@
|
|||||||
module github.com/cilium/ebpf
|
module github.com/cilium/ebpf
|
||||||
|
|
||||||
go 1.12
|
go 1.13
|
||||||
|
|
||||||
require (
|
require golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9
|
||||||
github.com/pkg/errors v0.8.1
|
|
||||||
golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7
|
|
||||||
)
|
|
||||||
|
432
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
432
vendor/github.com/cilium/ebpf/internal/btf/btf.go
generated
vendored
@ -4,20 +4,29 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"debug/elf"
|
"debug/elf"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const btfMagic = 0xeB9F
|
const btfMagic = 0xeB9F
|
||||||
|
|
||||||
|
// Errors returned by BTF functions.
|
||||||
|
var (
|
||||||
|
ErrNotSupported = internal.ErrNotSupported
|
||||||
|
ErrNotFound = errors.New("not found")
|
||||||
|
ErrNoExtendedInfo = errors.New("no extended info")
|
||||||
|
)
|
||||||
|
|
||||||
// Spec represents decoded BTF.
|
// Spec represents decoded BTF.
|
||||||
type Spec struct {
|
type Spec struct {
|
||||||
rawTypes []rawType
|
rawTypes []rawType
|
||||||
@ -25,6 +34,7 @@ type Spec struct {
|
|||||||
types map[string][]Type
|
types map[string][]Type
|
||||||
funcInfos map[string]extInfo
|
funcInfos map[string]extInfo
|
||||||
lineInfos map[string]extInfo
|
lineInfos map[string]extInfo
|
||||||
|
byteOrder binary.ByteOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
type btfHeader struct {
|
type btfHeader struct {
|
||||||
@ -52,6 +62,7 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
var (
|
var (
|
||||||
btfSection *elf.Section
|
btfSection *elf.Section
|
||||||
btfExtSection *elf.Section
|
btfExtSection *elf.Section
|
||||||
|
sectionSizes = make(map[string]uint32)
|
||||||
)
|
)
|
||||||
|
|
||||||
for _, sec := range file.Sections {
|
for _, sec := range file.Sections {
|
||||||
@ -60,6 +71,16 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
btfSection = sec
|
btfSection = sec
|
||||||
case ".BTF.ext":
|
case ".BTF.ext":
|
||||||
btfExtSection = sec
|
btfExtSection = sec
|
||||||
|
default:
|
||||||
|
if sec.Type != elf.SHT_PROGBITS && sec.Type != elf.SHT_NOBITS {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if sec.Size > math.MaxUint32 {
|
||||||
|
return nil, fmt.Errorf("section %s exceeds maximum size", sec.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
sectionSizes[sec.Name] = uint32(sec.Size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,74 +88,59 @@ func LoadSpecFromReader(rd io.ReaderAt) (*Spec, error) {
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
spec, err := parseBTF(btfSection.Open(), file.ByteOrder)
|
symbols, err := file.Symbols()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't read symbols: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
variableOffsets := make(map[variable]uint32)
|
||||||
|
for _, symbol := range symbols {
|
||||||
|
if idx := symbol.Section; idx >= elf.SHN_LORESERVE && idx <= elf.SHN_HIRESERVE {
|
||||||
|
// Ignore things like SHN_ABS
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
secName := file.Sections[symbol.Section].Name
|
||||||
|
if _, ok := sectionSizes[secName]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if symbol.Value > math.MaxUint32 {
|
||||||
|
return nil, fmt.Errorf("section %s: symbol %s: size exceeds maximum", secName, symbol.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
variableOffsets[variable{secName, symbol.Name}] = uint32(symbol.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec, err := loadNakedSpec(btfSection.Open(), file.ByteOrder, sectionSizes, variableOffsets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if btfExtSection != nil {
|
if btfExtSection == nil {
|
||||||
spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
|
return spec, nil
|
||||||
if err != nil {
|
}
|
||||||
return nil, errors.Wrap(err, "can't read ext info")
|
|
||||||
}
|
spec.funcInfos, spec.lineInfos, err = parseExtInfos(btfExtSection.Open(), file.ByteOrder, spec.strings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't read ext info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec, nil
|
return spec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) (*Spec, error) {
|
func loadNakedSpec(btf io.ReadSeeker, bo binary.ByteOrder, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) (*Spec, error) {
|
||||||
rawBTF, err := ioutil.ReadAll(btf)
|
rawTypes, rawStrings, err := parseBTF(btf, bo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't read BTF")
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
rd := bytes.NewReader(rawBTF)
|
err = fixupDatasec(rawTypes, rawStrings, sectionSizes, variableOffsets)
|
||||||
|
|
||||||
var header btfHeader
|
|
||||||
if err := binary.Read(rd, bo, &header); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't read header")
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Magic != btfMagic {
|
|
||||||
return nil, errors.Errorf("incorrect magic value %v", header.Magic)
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Version != 1 {
|
|
||||||
return nil, errors.Errorf("unexpected version %v", header.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
if header.Flags != 0 {
|
|
||||||
return nil, errors.Errorf("unsupported flags %v", header.Flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
|
||||||
if remainder < 0 {
|
|
||||||
return nil, errors.New("header is too short")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "header padding")
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't seek to start of string section")
|
|
||||||
}
|
|
||||||
|
|
||||||
strings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't read type names")
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil {
|
types, err := inflateRawTypes(rawTypes, rawStrings)
|
||||||
return nil, errors.Wrap(err, "can't seek to start of type section")
|
|
||||||
}
|
|
||||||
|
|
||||||
rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "can't read types")
|
|
||||||
}
|
|
||||||
|
|
||||||
types, err := inflateRawTypes(rawTypes, strings)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -142,13 +148,158 @@ func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) (*Spec, error) {
|
|||||||
return &Spec{
|
return &Spec{
|
||||||
rawTypes: rawTypes,
|
rawTypes: rawTypes,
|
||||||
types: types,
|
types: types,
|
||||||
strings: strings,
|
strings: rawStrings,
|
||||||
funcInfos: make(map[string]extInfo),
|
byteOrder: bo,
|
||||||
lineInfos: make(map[string]extInfo),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
|
var kernelBTF struct {
|
||||||
|
sync.Mutex
|
||||||
|
*Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadKernelSpec returns the current kernel's BTF information.
|
||||||
|
//
|
||||||
|
// Requires a >= 5.5 kernel with CONFIG_DEBUG_INFO_BTF enabled. Returns
|
||||||
|
// ErrNotSupported if BTF is not enabled.
|
||||||
|
func LoadKernelSpec() (*Spec, error) {
|
||||||
|
kernelBTF.Lock()
|
||||||
|
defer kernelBTF.Unlock()
|
||||||
|
|
||||||
|
if kernelBTF.Spec != nil {
|
||||||
|
return kernelBTF.Spec, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
kernelBTF.Spec, err = loadKernelSpec()
|
||||||
|
return kernelBTF.Spec, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadKernelSpec() (*Spec, error) {
|
||||||
|
fh, err := os.Open("/sys/kernel/btf/vmlinux")
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return nil, fmt.Errorf("can't open kernel BTF at /sys/kernel/btf/vmlinux: %w", ErrNotFound)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't read kernel BTF: %s", err)
|
||||||
|
}
|
||||||
|
defer fh.Close()
|
||||||
|
|
||||||
|
return loadNakedSpec(fh, internal.NativeEndian, nil, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseBTF(btf io.ReadSeeker, bo binary.ByteOrder) ([]rawType, stringTable, error) {
|
||||||
|
rawBTF, err := ioutil.ReadAll(btf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't read BTF: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rd := bytes.NewReader(rawBTF)
|
||||||
|
|
||||||
|
var header btfHeader
|
||||||
|
if err := binary.Read(rd, bo, &header); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't read header: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Magic != btfMagic {
|
||||||
|
return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Version != 1 {
|
||||||
|
return nil, nil, fmt.Errorf("unexpected version %v", header.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Flags != 0 {
|
||||||
|
return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
||||||
|
if remainder < 0 {
|
||||||
|
return nil, nil, errors.New("header is too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := io.CopyN(internal.DiscardZeroes{}, rd, remainder); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("header padding: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := rd.Seek(int64(header.HdrLen+header.StringOff), io.SeekStart); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't seek to start of string section: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawStrings, err := readStringTable(io.LimitReader(rd, int64(header.StringLen)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't read type names: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := rd.Seek(int64(header.HdrLen+header.TypeOff), io.SeekStart); err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't seek to start of type section: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawTypes, err := readTypes(io.LimitReader(rd, int64(header.TypeLen)), bo)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, fmt.Errorf("can't read types: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return rawTypes, rawStrings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type variable struct {
|
||||||
|
section string
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func fixupDatasec(rawTypes []rawType, rawStrings stringTable, sectionSizes map[string]uint32, variableOffsets map[variable]uint32) error {
|
||||||
|
for i, rawType := range rawTypes {
|
||||||
|
if rawType.Kind() != kindDatasec {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
name, err := rawStrings.Lookup(rawType.NameOff)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if name == ".kconfig" || name == ".ksym" {
|
||||||
|
return fmt.Errorf("reference to %s: %w", name, ErrNotSupported)
|
||||||
|
}
|
||||||
|
|
||||||
|
size, ok := sectionSizes[name]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("data section %s: missing size", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawTypes[i].SizeType = size
|
||||||
|
|
||||||
|
secinfos := rawType.data.([]btfVarSecinfo)
|
||||||
|
for j, secInfo := range secinfos {
|
||||||
|
id := int(secInfo.Type - 1)
|
||||||
|
if id >= len(rawTypes) {
|
||||||
|
return fmt.Errorf("data section %s: invalid type id %d for variable %d", name, id, j)
|
||||||
|
}
|
||||||
|
|
||||||
|
varName, err := rawStrings.Lookup(rawTypes[id].NameOff)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("data section %s: can't get name for type %d: %w", name, id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
offset, ok := variableOffsets[variable{name, varName}]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("data section %s: missing offset for variable %s", name, varName)
|
||||||
|
}
|
||||||
|
|
||||||
|
secinfos[j].Offset = offset
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type marshalOpts struct {
|
||||||
|
ByteOrder binary.ByteOrder
|
||||||
|
StripFuncLinkage bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Spec) marshal(opts marshalOpts) ([]byte, error) {
|
||||||
var (
|
var (
|
||||||
buf bytes.Buffer
|
buf bytes.Buffer
|
||||||
header = new(btfHeader)
|
header = new(btfHeader)
|
||||||
@ -160,17 +311,14 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
|
|||||||
_, _ = buf.Write(make([]byte, headerLen))
|
_, _ = buf.Write(make([]byte, headerLen))
|
||||||
|
|
||||||
// Write type section, just after the header.
|
// Write type section, just after the header.
|
||||||
for _, typ := range s.rawTypes {
|
for _, raw := range s.rawTypes {
|
||||||
if typ.Kind() == kindDatasec {
|
switch {
|
||||||
// Datasec requires patching with information from the ELF
|
case opts.StripFuncLinkage && raw.Kind() == kindFunc:
|
||||||
// file. We don't support this at the moment, so patch
|
raw.SetLinkage(linkageStatic)
|
||||||
// out any Datasec by turning it into a void*.
|
|
||||||
typ = rawType{}
|
|
||||||
typ.SetKind(kindPointer)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := typ.Marshal(&buf, bo); err != nil {
|
if err := raw.Marshal(&buf, opts.ByteOrder); err != nil {
|
||||||
return nil, errors.Wrap(err, "can't marshal BTF")
|
return nil, fmt.Errorf("can't marshal BTF: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,9 +340,9 @@ func (s *Spec) marshal(bo binary.ByteOrder) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
raw := buf.Bytes()
|
raw := buf.Bytes()
|
||||||
err := binary.Write(sliceWriter(raw[:headerLen]), bo, header)
|
err := binary.Write(sliceWriter(raw[:headerLen]), opts.ByteOrder, header)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't write header")
|
return nil, fmt.Errorf("can't write header: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return raw, nil
|
return raw, nil
|
||||||
@ -214,17 +362,22 @@ func (sw sliceWriter) Write(p []byte) (int, error) {
|
|||||||
//
|
//
|
||||||
// Length is the number of bytes in the raw BPF instruction stream.
|
// Length is the number of bytes in the raw BPF instruction stream.
|
||||||
//
|
//
|
||||||
// Returns an error if there is no BTF.
|
// Returns an error which may wrap ErrNoExtendedInfo if the Spec doesn't
|
||||||
|
// contain extended BTF info.
|
||||||
func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
||||||
if length == 0 {
|
if length == 0 {
|
||||||
return nil, errors.New("length musn't be zero")
|
return nil, errors.New("length musn't be zero")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if s.funcInfos == nil && s.lineInfos == nil {
|
||||||
|
return nil, fmt.Errorf("BTF for section %s: %w", name, ErrNoExtendedInfo)
|
||||||
|
}
|
||||||
|
|
||||||
funcInfos, funcOK := s.funcInfos[name]
|
funcInfos, funcOK := s.funcInfos[name]
|
||||||
lineInfos, lineOK := s.lineInfos[name]
|
lineInfos, lineOK := s.lineInfos[name]
|
||||||
|
|
||||||
if !funcOK && !lineOK {
|
if !funcOK && !lineOK {
|
||||||
return nil, errors.Errorf("no BTF for program %s", name)
|
return nil, fmt.Errorf("no extended BTF info for section %s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Program{s, length, funcInfos, lineInfos}, nil
|
return &Program{s, length, funcInfos, lineInfos}, nil
|
||||||
@ -233,15 +386,15 @@ func (s *Spec) Program(name string, length uint64) (*Program, error) {
|
|||||||
// Map finds the BTF for a map.
|
// Map finds the BTF for a map.
|
||||||
//
|
//
|
||||||
// Returns an error if there is no BTF for the given name.
|
// Returns an error if there is no BTF for the given name.
|
||||||
func (s *Spec) Map(name string) (*Map, error) {
|
func (s *Spec) Map(name string) (*Map, []Member, error) {
|
||||||
var mapVar Var
|
var mapVar Var
|
||||||
if err := s.FindType(name, &mapVar); err != nil {
|
if err := s.FindType(name, &mapVar); err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
mapStruct, ok := mapVar.Type.(*Struct)
|
mapStruct, ok := mapVar.Type.(*Struct)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.Errorf("expected struct, have %s", mapVar.Type)
|
return nil, nil, fmt.Errorf("expected struct, have %s", mapVar.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
var key, value Type
|
var key, value Type
|
||||||
@ -256,23 +409,32 @@ func (s *Spec) Map(name string) (*Map, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if key == nil {
|
if key == nil {
|
||||||
return nil, errors.Errorf("map %s: missing 'key' in type", name)
|
key = (*Void)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil, errors.Errorf("map %s: missing 'value' in type", name)
|
value = (*Void)(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Map{mapStruct, s, key, value}, nil
|
return &Map{s, key, value}, mapStruct.Members, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var errNotFound = errors.New("not found")
|
// Datasec returns the BTF required to create maps which represent data sections.
|
||||||
|
func (s *Spec) Datasec(name string) (*Map, error) {
|
||||||
|
var datasec Datasec
|
||||||
|
if err := s.FindType(name, &datasec); err != nil {
|
||||||
|
return nil, fmt.Errorf("data section %s: can't get BTF: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Map{s, &Void{}, &datasec}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// FindType searches for a type with a specific name.
|
// FindType searches for a type with a specific name.
|
||||||
//
|
//
|
||||||
// hint determines the type of the returned Type.
|
// hint determines the type of the returned Type.
|
||||||
//
|
//
|
||||||
// Returns an error if there is no or multiple matches.
|
// Returns an error wrapping ErrNotFound if no matching
|
||||||
|
// type exists in spec.
|
||||||
func (s *Spec) FindType(name string, typ Type) error {
|
func (s *Spec) FindType(name string, typ Type) error {
|
||||||
var (
|
var (
|
||||||
wanted = reflect.TypeOf(typ)
|
wanted = reflect.TypeOf(typ)
|
||||||
@ -285,14 +447,14 @@ func (s *Spec) FindType(name string, typ Type) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if candidate != nil {
|
if candidate != nil {
|
||||||
return errors.Errorf("type %s: multiple candidates for %T", name, typ)
|
return fmt.Errorf("type %s: multiple candidates for %T", name, typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
candidate = typ
|
candidate = typ
|
||||||
}
|
}
|
||||||
|
|
||||||
if candidate == nil {
|
if candidate == nil {
|
||||||
return errors.WithMessagef(errNotFound, "type %s", name)
|
return fmt.Errorf("type %s: %w", name, ErrNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := reflect.Indirect(reflect.ValueOf(copyType(candidate)))
|
value := reflect.Indirect(reflect.ValueOf(copyType(candidate)))
|
||||||
@ -307,16 +469,22 @@ type Handle struct {
|
|||||||
|
|
||||||
// NewHandle loads BTF into the kernel.
|
// NewHandle loads BTF into the kernel.
|
||||||
//
|
//
|
||||||
// Returns an error if BTF is not supported, which can
|
// Returns ErrNotSupported if BTF is not supported.
|
||||||
// be checked by IsNotSupported.
|
|
||||||
func NewHandle(spec *Spec) (*Handle, error) {
|
func NewHandle(spec *Spec) (*Handle, error) {
|
||||||
if err := haveBTF(); err != nil {
|
if err := haveBTF(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
btf, err := spec.marshal(internal.NativeEndian)
|
if spec.byteOrder != internal.NativeEndian {
|
||||||
|
return nil, fmt.Errorf("can't load %s BTF on %s", spec.byteOrder, internal.NativeEndian)
|
||||||
|
}
|
||||||
|
|
||||||
|
btf, err := spec.marshal(marshalOpts{
|
||||||
|
ByteOrder: internal.NativeEndian,
|
||||||
|
StripFuncLinkage: haveFuncLinkage() != nil,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't marshal BTF")
|
return nil, fmt.Errorf("can't marshal BTF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if uint64(len(btf)) > math.MaxUint32 {
|
if uint64(len(btf)) > math.MaxUint32 {
|
||||||
@ -360,7 +528,6 @@ func (h *Handle) FD() int {
|
|||||||
|
|
||||||
// Map is the BTF for a map.
|
// Map is the BTF for a map.
|
||||||
type Map struct {
|
type Map struct {
|
||||||
definition *Struct
|
|
||||||
spec *Spec
|
spec *Spec
|
||||||
key, value Type
|
key, value Type
|
||||||
}
|
}
|
||||||
@ -371,12 +538,6 @@ func MapSpec(m *Map) *Spec {
|
|||||||
return m.spec
|
return m.spec
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapType should be a method on Map, but is a free function
|
|
||||||
// to hide it from users of the ebpf package.
|
|
||||||
func MapType(m *Map) *Struct {
|
|
||||||
return m.definition
|
|
||||||
}
|
|
||||||
|
|
||||||
// MapKey should be a method on Map, but is a free function
|
// MapKey should be a method on Map, but is a free function
|
||||||
// to hide it from users of the ebpf package.
|
// to hide it from users of the ebpf package.
|
||||||
func MapKey(m *Map) Type {
|
func MapKey(m *Map) Type {
|
||||||
@ -411,12 +572,12 @@ func ProgramSpec(s *Program) *Spec {
|
|||||||
func ProgramAppend(s, other *Program) error {
|
func ProgramAppend(s, other *Program) error {
|
||||||
funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
|
funcInfos, err := s.funcInfos.append(other.funcInfos, s.length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "func infos")
|
return fmt.Errorf("func infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
|
lineInfos, err := s.lineInfos.append(other.lineInfos, s.length)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "line infos")
|
return fmt.Errorf("line infos: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.length += other.length
|
s.length += other.length
|
||||||
@ -451,13 +612,6 @@ func ProgramLineInfos(s *Program) (recordSize uint32, bytes []byte, err error) {
|
|||||||
return s.lineInfos.recordSize, bytes, nil
|
return s.lineInfos.recordSize, bytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotSupported returns true if the error indicates that the kernel
|
|
||||||
// doesn't support BTF.
|
|
||||||
func IsNotSupported(err error) bool {
|
|
||||||
ufe, ok := errors.Cause(err).(*internal.UnsupportedFeatureError)
|
|
||||||
return ok && ufe.Name == "BTF"
|
|
||||||
}
|
|
||||||
|
|
||||||
type bpfLoadBTFAttr struct {
|
type bpfLoadBTFAttr struct {
|
||||||
btf internal.Pointer
|
btf internal.Pointer
|
||||||
logBuf internal.Pointer
|
logBuf internal.Pointer
|
||||||
@ -477,26 +631,36 @@ func bpfLoadBTF(attr *bpfLoadBTFAttr) (*internal.FD, error) {
|
|||||||
return internal.NewFD(uint32(fd)), nil
|
return internal.NewFD(uint32(fd)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func minimalBTF(bo binary.ByteOrder) []byte {
|
func marshalBTF(types interface{}, strings []byte, bo binary.ByteOrder) []byte {
|
||||||
const minHeaderLength = 24
|
const minHeaderLength = 24
|
||||||
|
|
||||||
|
typesLen := uint32(binary.Size(types))
|
||||||
|
header := btfHeader{
|
||||||
|
Magic: btfMagic,
|
||||||
|
Version: 1,
|
||||||
|
HdrLen: minHeaderLength,
|
||||||
|
TypeOff: 0,
|
||||||
|
TypeLen: typesLen,
|
||||||
|
StringOff: typesLen,
|
||||||
|
StringLen: uint32(len(strings)),
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
_ = binary.Write(buf, bo, &header)
|
||||||
|
_ = binary.Write(buf, bo, types)
|
||||||
|
buf.Write(strings)
|
||||||
|
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
var haveBTF = internal.FeatureTest("BTF", "5.1", func() (bool, error) {
|
||||||
var (
|
var (
|
||||||
types struct {
|
types struct {
|
||||||
Integer btfType
|
Integer btfType
|
||||||
Var btfType
|
Var btfType
|
||||||
btfVar struct{ Linkage uint32 }
|
btfVar struct{ Linkage uint32 }
|
||||||
}
|
}
|
||||||
typLen = uint32(binary.Size(&types))
|
|
||||||
strings = []byte{0, 'a', 0}
|
strings = []byte{0, 'a', 0}
|
||||||
header = btfHeader{
|
|
||||||
Magic: btfMagic,
|
|
||||||
Version: 1,
|
|
||||||
HdrLen: minHeaderLength,
|
|
||||||
TypeOff: 0,
|
|
||||||
TypeLen: typLen,
|
|
||||||
StringOff: typLen,
|
|
||||||
StringLen: uint32(len(strings)),
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// We use a BTF_KIND_VAR here, to make sure that
|
// We use a BTF_KIND_VAR here, to make sure that
|
||||||
@ -507,16 +671,8 @@ func minimalBTF(bo binary.ByteOrder) []byte {
|
|||||||
types.Var.SetKind(kindVar)
|
types.Var.SetKind(kindVar)
|
||||||
types.Var.SizeType = 1
|
types.Var.SizeType = 1
|
||||||
|
|
||||||
buf := new(bytes.Buffer)
|
btf := marshalBTF(&types, strings, internal.NativeEndian)
|
||||||
_ = binary.Write(buf, bo, &header)
|
|
||||||
_ = binary.Write(buf, bo, &types)
|
|
||||||
buf.Write(strings)
|
|
||||||
|
|
||||||
return buf.Bytes()
|
|
||||||
}
|
|
||||||
|
|
||||||
var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool {
|
|
||||||
btf := minimalBTF(internal.NativeEndian)
|
|
||||||
fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
|
fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
|
||||||
btf: internal.NewSlicePointer(btf),
|
btf: internal.NewSlicePointer(btf),
|
||||||
btfSize: uint32(len(btf)),
|
btfSize: uint32(len(btf)),
|
||||||
@ -526,5 +682,35 @@ var haveBTF = internal.FeatureTest("BTF", "5.1", func() bool {
|
|||||||
}
|
}
|
||||||
// Check for EINVAL specifically, rather than err != nil since we
|
// Check for EINVAL specifically, rather than err != nil since we
|
||||||
// otherwise misdetect due to insufficient permissions.
|
// otherwise misdetect due to insufficient permissions.
|
||||||
return errors.Cause(err) != unix.EINVAL
|
return !errors.Is(err, unix.EINVAL), nil
|
||||||
|
})
|
||||||
|
|
||||||
|
var haveFuncLinkage = internal.FeatureTest("BTF func linkage", "5.6", func() (bool, error) {
|
||||||
|
var (
|
||||||
|
types struct {
|
||||||
|
FuncProto btfType
|
||||||
|
Func btfType
|
||||||
|
}
|
||||||
|
strings = []byte{0, 'a', 0}
|
||||||
|
)
|
||||||
|
|
||||||
|
types.FuncProto.SetKind(kindFuncProto)
|
||||||
|
types.Func.SetKind(kindFunc)
|
||||||
|
types.Func.SizeType = 1 // aka FuncProto
|
||||||
|
types.Func.NameOff = 1
|
||||||
|
types.Func.SetLinkage(linkageGlobal)
|
||||||
|
|
||||||
|
btf := marshalBTF(&types, strings, internal.NativeEndian)
|
||||||
|
|
||||||
|
fd, err := bpfLoadBTF(&bpfLoadBTFAttr{
|
||||||
|
btf: internal.NewSlicePointer(btf),
|
||||||
|
btfSize: uint32(len(btf)),
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
fd.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for EINVAL specifically, rather than err != nil since we
|
||||||
|
// otherwise misdetect due to insufficient permissions.
|
||||||
|
return !errors.Is(err, unix.EINVAL), nil
|
||||||
})
|
})
|
||||||
|
101
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
101
vendor/github.com/cilium/ebpf/internal/btf/btf_types.go
generated
vendored
@ -2,9 +2,8 @@ package btf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// btfKind describes a Type.
|
// btfKind describes a Type.
|
||||||
@ -32,6 +31,14 @@ const (
|
|||||||
kindDatasec
|
kindDatasec
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type btfFuncLinkage uint8
|
||||||
|
|
||||||
|
const (
|
||||||
|
linkageStatic btfFuncLinkage = iota
|
||||||
|
linkageGlobal
|
||||||
|
linkageExtern
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
btfTypeKindShift = 24
|
btfTypeKindShift = 24
|
||||||
btfTypeKindLen = 4
|
btfTypeKindLen = 4
|
||||||
@ -43,7 +50,7 @@ const (
|
|||||||
type btfType struct {
|
type btfType struct {
|
||||||
NameOff uint32
|
NameOff uint32
|
||||||
/* "info" bits arrangement
|
/* "info" bits arrangement
|
||||||
* bits 0-15: vlen (e.g. # of struct's members)
|
* bits 0-15: vlen (e.g. # of struct's members), linkage
|
||||||
* bits 16-23: unused
|
* bits 16-23: unused
|
||||||
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
* bits 24-27: kind (e.g. int, ptr, array...etc)
|
||||||
* bits 28-30: unused
|
* bits 28-30: unused
|
||||||
@ -61,6 +68,45 @@ type btfType struct {
|
|||||||
SizeType uint32
|
SizeType uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (k btfKind) String() string {
|
||||||
|
switch k {
|
||||||
|
case kindUnknown:
|
||||||
|
return "Unknown"
|
||||||
|
case kindInt:
|
||||||
|
return "Integer"
|
||||||
|
case kindPointer:
|
||||||
|
return "Pointer"
|
||||||
|
case kindArray:
|
||||||
|
return "Array"
|
||||||
|
case kindStruct:
|
||||||
|
return "Struct"
|
||||||
|
case kindUnion:
|
||||||
|
return "Union"
|
||||||
|
case kindEnum:
|
||||||
|
return "Enumeration"
|
||||||
|
case kindForward:
|
||||||
|
return "Forward"
|
||||||
|
case kindTypedef:
|
||||||
|
return "Typedef"
|
||||||
|
case kindVolatile:
|
||||||
|
return "Volatile"
|
||||||
|
case kindConst:
|
||||||
|
return "Const"
|
||||||
|
case kindRestrict:
|
||||||
|
return "Restrict"
|
||||||
|
case kindFunc:
|
||||||
|
return "Function"
|
||||||
|
case kindFuncProto:
|
||||||
|
return "Function Proto"
|
||||||
|
case kindVar:
|
||||||
|
return "Variable"
|
||||||
|
case kindDatasec:
|
||||||
|
return "Section"
|
||||||
|
default:
|
||||||
|
return fmt.Sprintf("Unknown (%d)", k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func mask(len uint32) uint32 {
|
func mask(len uint32) uint32 {
|
||||||
return (1 << len) - 1
|
return (1 << len) - 1
|
||||||
}
|
}
|
||||||
@ -90,6 +136,14 @@ func (bt *btfType) SetVlen(vlen int) {
|
|||||||
bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
|
bt.setInfo(uint32(vlen), btfTypeVlenMask, btfTypeVlenShift)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) Linkage() btfFuncLinkage {
|
||||||
|
return btfFuncLinkage(bt.info(btfTypeVlenMask, btfTypeVlenShift))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bt *btfType) SetLinkage(linkage btfFuncLinkage) {
|
||||||
|
bt.setInfo(uint32(linkage), btfTypeVlenMask, btfTypeVlenShift)
|
||||||
|
}
|
||||||
|
|
||||||
func (bt *btfType) Type() TypeID {
|
func (bt *btfType) Type() TypeID {
|
||||||
// TODO: Panic here if wrong kind?
|
// TODO: Panic here if wrong kind?
|
||||||
return TypeID(bt.SizeType)
|
return TypeID(bt.SizeType)
|
||||||
@ -129,6 +183,26 @@ type btfMember struct {
|
|||||||
Offset uint32
|
Offset uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type btfVarSecinfo struct {
|
||||||
|
Type TypeID
|
||||||
|
Offset uint32
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfVariable struct {
|
||||||
|
Linkage uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfEnum struct {
|
||||||
|
NameOff uint32
|
||||||
|
Val int32
|
||||||
|
}
|
||||||
|
|
||||||
|
type btfParam struct {
|
||||||
|
NameOff uint32
|
||||||
|
Type TypeID
|
||||||
|
}
|
||||||
|
|
||||||
func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
||||||
var (
|
var (
|
||||||
header btfType
|
header btfType
|
||||||
@ -139,14 +213,13 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
|||||||
if err := binary.Read(r, bo, &header); err == io.EOF {
|
if err := binary.Read(r, bo, &header); err == io.EOF {
|
||||||
return types, nil
|
return types, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, errors.Wrapf(err, "can't read type info for id %v", id)
|
return nil, fmt.Errorf("can't read type info for id %v: %v", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var data interface{}
|
var data interface{}
|
||||||
switch header.Kind() {
|
switch header.Kind() {
|
||||||
case kindInt:
|
case kindInt:
|
||||||
// sizeof(uint32)
|
data = new(uint32)
|
||||||
data = make([]byte, 4)
|
|
||||||
case kindPointer:
|
case kindPointer:
|
||||||
case kindArray:
|
case kindArray:
|
||||||
data = new(btfArray)
|
data = new(btfArray)
|
||||||
@ -155,8 +228,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
|||||||
case kindUnion:
|
case kindUnion:
|
||||||
data = make([]btfMember, header.Vlen())
|
data = make([]btfMember, header.Vlen())
|
||||||
case kindEnum:
|
case kindEnum:
|
||||||
// sizeof(struct btf_enum)
|
data = make([]btfEnum, header.Vlen())
|
||||||
data = make([]byte, header.Vlen()*4*2)
|
|
||||||
case kindForward:
|
case kindForward:
|
||||||
case kindTypedef:
|
case kindTypedef:
|
||||||
case kindVolatile:
|
case kindVolatile:
|
||||||
@ -164,16 +236,13 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
|||||||
case kindRestrict:
|
case kindRestrict:
|
||||||
case kindFunc:
|
case kindFunc:
|
||||||
case kindFuncProto:
|
case kindFuncProto:
|
||||||
// sizeof(struct btf_param)
|
data = make([]btfParam, header.Vlen())
|
||||||
data = make([]byte, header.Vlen()*4*2)
|
|
||||||
case kindVar:
|
case kindVar:
|
||||||
// sizeof(struct btf_variable)
|
data = new(btfVariable)
|
||||||
data = make([]byte, 4)
|
|
||||||
case kindDatasec:
|
case kindDatasec:
|
||||||
// sizeof(struct btf_var_secinfo)
|
data = make([]btfVarSecinfo, header.Vlen())
|
||||||
data = make([]byte, header.Vlen()*4*3)
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
return nil, fmt.Errorf("type id %v: unknown kind: %v", id, header.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
if data == nil {
|
if data == nil {
|
||||||
@ -182,7 +251,7 @@ func readTypes(r io.Reader, bo binary.ByteOrder) ([]rawType, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(r, bo, data); err != nil {
|
if err := binary.Read(r, bo, data); err != nil {
|
||||||
return nil, errors.Wrapf(err, "type id %d: kind %v: can't read %T", id, header.Kind(), data)
|
return nil, fmt.Errorf("type id %d: kind %v: can't read %T: %v", id, header.Kind(), data, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
types = append(types, rawType{header, data})
|
types = append(types, rawType{header, data})
|
||||||
|
44
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
44
vendor/github.com/cilium/ebpf/internal/btf/ext_info.go
generated
vendored
@ -3,13 +3,13 @@ package btf
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type btfExtHeader struct {
|
type btfExtHeader struct {
|
||||||
@ -25,23 +25,21 @@ type btfExtHeader struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) {
|
func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (funcInfo, lineInfo map[string]extInfo, err error) {
|
||||||
const expectedMagic = 0xeB9F
|
|
||||||
|
|
||||||
var header btfExtHeader
|
var header btfExtHeader
|
||||||
if err := binary.Read(r, bo, &header); err != nil {
|
if err := binary.Read(r, bo, &header); err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "can't read header")
|
return nil, nil, fmt.Errorf("can't read header: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header.Magic != expectedMagic {
|
if header.Magic != btfMagic {
|
||||||
return nil, nil, errors.Errorf("incorrect magic value %v", header.Magic)
|
return nil, nil, fmt.Errorf("incorrect magic value %v", header.Magic)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header.Version != 1 {
|
if header.Version != 1 {
|
||||||
return nil, nil, errors.Errorf("unexpected version %v", header.Version)
|
return nil, nil, fmt.Errorf("unexpected version %v", header.Version)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header.Flags != 0 {
|
if header.Flags != 0 {
|
||||||
return nil, nil, errors.Errorf("unsupported flags %v", header.Flags)
|
return nil, nil, fmt.Errorf("unsupported flags %v", header.Flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
remainder := int64(header.HdrLen) - int64(binary.Size(&header))
|
||||||
@ -53,25 +51,25 @@ func parseExtInfos(r io.ReadSeeker, bo binary.ByteOrder, strings stringTable) (f
|
|||||||
// .BTF ext header. We need to ignore non-null values.
|
// .BTF ext header. We need to ignore non-null values.
|
||||||
_, err = io.CopyN(ioutil.Discard, r, remainder)
|
_, err = io.CopyN(ioutil.Discard, r, remainder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "header padding")
|
return nil, nil, fmt.Errorf("header padding: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil {
|
if _, err := r.Seek(int64(header.HdrLen+header.FuncInfoOff), io.SeekStart); err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "can't seek to function info section")
|
return nil, nil, fmt.Errorf("can't seek to function info section: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings)
|
funcInfo, err = parseExtInfo(io.LimitReader(r, int64(header.FuncInfoLen)), bo, strings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "function info")
|
return nil, nil, fmt.Errorf("function info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil {
|
if _, err := r.Seek(int64(header.HdrLen+header.LineInfoOff), io.SeekStart); err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "can't seek to line info section")
|
return nil, nil, fmt.Errorf("can't seek to line info section: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings)
|
lineInfo, err = parseExtInfo(io.LimitReader(r, int64(header.LineInfoLen)), bo, strings)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, errors.Wrap(err, "line info")
|
return nil, nil, fmt.Errorf("line info: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return funcInfo, lineInfo, nil
|
return funcInfo, lineInfo, nil
|
||||||
@ -94,7 +92,7 @@ type extInfo struct {
|
|||||||
|
|
||||||
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
func (ei extInfo) append(other extInfo, offset uint64) (extInfo, error) {
|
||||||
if other.recordSize != ei.recordSize {
|
if other.recordSize != ei.recordSize {
|
||||||
return extInfo{}, errors.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
|
return extInfo{}, fmt.Errorf("ext_info record size mismatch, want %d (got %d)", ei.recordSize, other.recordSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
records := make([]extInfoRecord, 0, len(ei.records)+len(other.records))
|
records := make([]extInfoRecord, 0, len(ei.records)+len(other.records))
|
||||||
@ -119,7 +117,7 @@ func (ei extInfo) MarshalBinary() ([]byte, error) {
|
|||||||
// while the ELF tracks it in bytes.
|
// while the ELF tracks it in bytes.
|
||||||
insnOff := uint32(info.InsnOff / asm.InstructionSize)
|
insnOff := uint32(info.InsnOff / asm.InstructionSize)
|
||||||
if err := binary.Write(buf, internal.NativeEndian, insnOff); err != nil {
|
if err := binary.Write(buf, internal.NativeEndian, insnOff); err != nil {
|
||||||
return nil, errors.Wrap(err, "can't write instruction offset")
|
return nil, fmt.Errorf("can't write instruction offset: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.Write(info.Opaque)
|
buf.Write(info.Opaque)
|
||||||
@ -131,7 +129,7 @@ func (ei extInfo) MarshalBinary() ([]byte, error) {
|
|||||||
func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) {
|
func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[string]extInfo, error) {
|
||||||
var recordSize uint32
|
var recordSize uint32
|
||||||
if err := binary.Read(r, bo, &recordSize); err != nil {
|
if err := binary.Read(r, bo, &recordSize); err != nil {
|
||||||
return nil, errors.Wrap(err, "can't read record size")
|
return nil, fmt.Errorf("can't read record size: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if recordSize < 4 {
|
if recordSize < 4 {
|
||||||
@ -145,32 +143,32 @@ func parseExtInfo(r io.Reader, bo binary.ByteOrder, strings stringTable) (map[st
|
|||||||
if err := binary.Read(r, bo, &infoHeader); err == io.EOF {
|
if err := binary.Read(r, bo, &infoHeader); err == io.EOF {
|
||||||
return result, nil
|
return result, nil
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't read ext info header")
|
return nil, fmt.Errorf("can't read ext info header: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
secName, err := strings.Lookup(infoHeader.SecNameOff)
|
secName, err := strings.Lookup(infoHeader.SecNameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get section name")
|
return nil, fmt.Errorf("can't get section name: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if infoHeader.NumInfo == 0 {
|
if infoHeader.NumInfo == 0 {
|
||||||
return nil, errors.Errorf("section %s has invalid number of records", secName)
|
return nil, fmt.Errorf("section %s has invalid number of records", secName)
|
||||||
}
|
}
|
||||||
|
|
||||||
var records []extInfoRecord
|
var records []extInfoRecord
|
||||||
for i := uint32(0); i < infoHeader.NumInfo; i++ {
|
for i := uint32(0); i < infoHeader.NumInfo; i++ {
|
||||||
var byteOff uint32
|
var byteOff uint32
|
||||||
if err := binary.Read(r, bo, &byteOff); err != nil {
|
if err := binary.Read(r, bo, &byteOff); err != nil {
|
||||||
return nil, errors.Wrapf(err, "section %v: can't read extended info offset", secName)
|
return nil, fmt.Errorf("section %v: can't read extended info offset: %v", secName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, int(recordSize-4))
|
buf := make([]byte, int(recordSize-4))
|
||||||
if _, err := io.ReadFull(r, buf); err != nil {
|
if _, err := io.ReadFull(r, buf); err != nil {
|
||||||
return nil, errors.Wrapf(err, "section %v: can't read record", secName)
|
return nil, fmt.Errorf("section %v: can't read record: %v", secName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if byteOff%asm.InstructionSize != 0 {
|
if byteOff%asm.InstructionSize != 0 {
|
||||||
return nil, errors.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff)
|
return nil, fmt.Errorf("section %v: offset %v is not aligned with instruction size", secName, byteOff)
|
||||||
}
|
}
|
||||||
|
|
||||||
records = append(records, extInfoRecord{uint64(byteOff), buf})
|
records = append(records, extInfoRecord{uint64(byteOff), buf})
|
||||||
|
14
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
14
vendor/github.com/cilium/ebpf/internal/btf/strings.go
generated
vendored
@ -2,10 +2,10 @@ package btf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type stringTable []byte
|
type stringTable []byte
|
||||||
@ -13,7 +13,7 @@ type stringTable []byte
|
|||||||
func readStringTable(r io.Reader) (stringTable, error) {
|
func readStringTable(r io.Reader) (stringTable, error) {
|
||||||
contents, err := ioutil.ReadAll(r)
|
contents, err := ioutil.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't read string table")
|
return nil, fmt.Errorf("can't read string table: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(contents) < 1 {
|
if len(contents) < 1 {
|
||||||
@ -33,22 +33,22 @@ func readStringTable(r io.Reader) (stringTable, error) {
|
|||||||
|
|
||||||
func (st stringTable) Lookup(offset uint32) (string, error) {
|
func (st stringTable) Lookup(offset uint32) (string, error) {
|
||||||
if int64(offset) > int64(^uint(0)>>1) {
|
if int64(offset) > int64(^uint(0)>>1) {
|
||||||
return "", errors.Errorf("offset %d overflows int", offset)
|
return "", fmt.Errorf("offset %d overflows int", offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
pos := int(offset)
|
pos := int(offset)
|
||||||
if pos >= len(st) {
|
if pos >= len(st) {
|
||||||
return "", errors.Errorf("offset %d is out of bounds", offset)
|
return "", fmt.Errorf("offset %d is out of bounds", offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pos > 0 && st[pos-1] != '\x00' {
|
if pos > 0 && st[pos-1] != '\x00' {
|
||||||
return "", errors.Errorf("offset %d isn't start of a string", offset)
|
return "", fmt.Errorf("offset %d isn't start of a string", offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
str := st[pos:]
|
str := st[pos:]
|
||||||
end := bytes.IndexByte(str, '\x00')
|
end := bytes.IndexByte(str, '\x00')
|
||||||
if end == -1 {
|
if end == -1 {
|
||||||
return "", errors.Errorf("offset %d isn't null terminated", offset)
|
return "", fmt.Errorf("offset %d isn't null terminated", offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
return string(str[:end]), nil
|
return string(str[:end]), nil
|
||||||
|
117
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
117
vendor/github.com/cilium/ebpf/internal/btf/types.go
generated
vendored
@ -1,9 +1,9 @@
|
|||||||
package btf
|
package btf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const maxTypeDepth = 32
|
const maxTypeDepth = 32
|
||||||
@ -38,9 +38,10 @@ func (n Name) name() string {
|
|||||||
// Void is the unit type of BTF.
|
// Void is the unit type of BTF.
|
||||||
type Void struct{}
|
type Void struct{}
|
||||||
|
|
||||||
func (v Void) ID() TypeID { return 0 }
|
func (v *Void) ID() TypeID { return 0 }
|
||||||
func (v Void) copy() Type { return Void{} }
|
func (v *Void) size() uint32 { return 0 }
|
||||||
func (v Void) walk(*copyStack) {}
|
func (v *Void) copy() Type { return (*Void)(nil) }
|
||||||
|
func (v *Void) walk(*copyStack) {}
|
||||||
|
|
||||||
// Int is an integer of a given length.
|
// Int is an integer of a given length.
|
||||||
type Int struct {
|
type Int struct {
|
||||||
@ -103,7 +104,8 @@ func (s *Struct) walk(cs *copyStack) {
|
|||||||
|
|
||||||
func (s *Struct) copy() Type {
|
func (s *Struct) copy() Type {
|
||||||
cpy := *s
|
cpy := *s
|
||||||
cpy.Members = copyMembers(cpy.Members)
|
cpy.Members = make([]Member, len(s.Members))
|
||||||
|
copy(cpy.Members, s.Members)
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +128,8 @@ func (u *Union) walk(cs *copyStack) {
|
|||||||
|
|
||||||
func (u *Union) copy() Type {
|
func (u *Union) copy() Type {
|
||||||
cpy := *u
|
cpy := *u
|
||||||
cpy.Members = copyMembers(cpy.Members)
|
cpy.Members = make([]Member, len(u.Members))
|
||||||
|
copy(cpy.Members, u.Members)
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,14 +142,6 @@ type Member struct {
|
|||||||
Offset uint32
|
Offset uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyMembers(in []Member) []Member {
|
|
||||||
cpy := make([]Member, 0, len(in))
|
|
||||||
for _, member := range in {
|
|
||||||
cpy = append(cpy, member)
|
|
||||||
}
|
|
||||||
return cpy
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enum lists possible values.
|
// Enum lists possible values.
|
||||||
type Enum struct {
|
type Enum struct {
|
||||||
TypeID
|
TypeID
|
||||||
@ -265,15 +260,31 @@ type Datasec struct {
|
|||||||
TypeID
|
TypeID
|
||||||
Name
|
Name
|
||||||
Size uint32
|
Size uint32
|
||||||
|
Vars []VarSecinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *Datasec) size() uint32 { return ds.Size }
|
||||||
|
|
||||||
|
func (ds *Datasec) walk(cs *copyStack) {
|
||||||
|
for i := range ds.Vars {
|
||||||
|
cs.push(&ds.Vars[i].Type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds *Datasec) size() uint32 { return ds.Size }
|
|
||||||
func (ds *Datasec) walk(*copyStack) {}
|
|
||||||
func (ds *Datasec) copy() Type {
|
func (ds *Datasec) copy() Type {
|
||||||
cpy := *ds
|
cpy := *ds
|
||||||
|
cpy.Vars = make([]VarSecinfo, len(ds.Vars))
|
||||||
|
copy(cpy.Vars, ds.Vars)
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// VarSecinfo describes variable in a Datasec
|
||||||
|
type VarSecinfo struct {
|
||||||
|
Type Type
|
||||||
|
Offset uint32
|
||||||
|
Size uint32
|
||||||
|
}
|
||||||
|
|
||||||
type sizer interface {
|
type sizer interface {
|
||||||
size() uint32
|
size() uint32
|
||||||
}
|
}
|
||||||
@ -326,7 +337,7 @@ func Sizeof(typ Type) (int, error) {
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0, errors.Errorf("unrecognized type %T", typ)
|
return 0, fmt.Errorf("unrecognized type %T", typ)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n > 0 && elem > math.MaxInt64/n {
|
if n > 0 && elem > math.MaxInt64/n {
|
||||||
@ -405,12 +416,17 @@ var _ namer = Name("")
|
|||||||
// compilation units, multiple types may share the same name. A Type may form a
|
// compilation units, multiple types may share the same name. A Type may form a
|
||||||
// cyclic graph by pointing at itself.
|
// cyclic graph by pointing at itself.
|
||||||
func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map[string][]Type, err error) {
|
func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map[string][]Type, err error) {
|
||||||
type fixup struct {
|
type fixupDef struct {
|
||||||
id TypeID
|
id TypeID
|
||||||
typ *Type
|
expectedKind btfKind
|
||||||
|
typ *Type
|
||||||
|
}
|
||||||
|
|
||||||
|
var fixups []fixupDef
|
||||||
|
fixup := func(id TypeID, expectedKind btfKind, typ *Type) {
|
||||||
|
fixups = append(fixups, fixupDef{id, expectedKind, typ})
|
||||||
}
|
}
|
||||||
|
|
||||||
var fixups []fixup
|
|
||||||
convertMembers := func(raw []btfMember) ([]Member, error) {
|
convertMembers := func(raw []btfMember) ([]Member, error) {
|
||||||
// NB: The fixup below relies on pre-allocating this array to
|
// NB: The fixup below relies on pre-allocating this array to
|
||||||
// work, since otherwise append might re-allocate members.
|
// work, since otherwise append might re-allocate members.
|
||||||
@ -418,7 +434,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
for i, btfMember := range raw {
|
for i, btfMember := range raw {
|
||||||
name, err := rawStrings.LookupName(btfMember.NameOff)
|
name, err := rawStrings.LookupName(btfMember.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "can't get name for member %d", i)
|
return nil, fmt.Errorf("can't get name for member %d: %w", i, err)
|
||||||
}
|
}
|
||||||
members = append(members, Member{
|
members = append(members, Member{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -426,13 +442,13 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
for i := range members {
|
for i := range members {
|
||||||
fixups = append(fixups, fixup{raw[i].Type, &members[i].Type})
|
fixup(raw[i].Type, kindUnknown, &members[i].Type)
|
||||||
}
|
}
|
||||||
return members, nil
|
return members, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
types := make([]Type, 0, len(rawTypes))
|
types := make([]Type, 0, len(rawTypes))
|
||||||
types = append(types, Void{})
|
types = append(types, (*Void)(nil))
|
||||||
namedTypes = make(map[string][]Type)
|
namedTypes = make(map[string][]Type)
|
||||||
|
|
||||||
for i, raw := range rawTypes {
|
for i, raw := range rawTypes {
|
||||||
@ -445,7 +461,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
|
|
||||||
name, err := rawStrings.LookupName(raw.NameOff)
|
name, err := rawStrings.LookupName(raw.NameOff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "can't get name for type id %d", id)
|
return nil, fmt.Errorf("can't get name for type id %d: %w", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch raw.Kind() {
|
switch raw.Kind() {
|
||||||
@ -454,7 +470,7 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
|
|
||||||
case kindPointer:
|
case kindPointer:
|
||||||
ptr := &Pointer{id, nil}
|
ptr := &Pointer{id, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &ptr.Target})
|
fixup(raw.Type(), kindUnknown, &ptr.Target)
|
||||||
typ = ptr
|
typ = ptr
|
||||||
|
|
||||||
case kindArray:
|
case kindArray:
|
||||||
@ -463,20 +479,20 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
// IndexType is unused according to btf.rst.
|
// IndexType is unused according to btf.rst.
|
||||||
// Don't make it available right now.
|
// Don't make it available right now.
|
||||||
arr := &Array{id, nil, btfArr.Nelems}
|
arr := &Array{id, nil, btfArr.Nelems}
|
||||||
fixups = append(fixups, fixup{btfArr.Type, &arr.Type})
|
fixup(btfArr.Type, kindUnknown, &arr.Type)
|
||||||
typ = arr
|
typ = arr
|
||||||
|
|
||||||
case kindStruct:
|
case kindStruct:
|
||||||
members, err := convertMembers(raw.data.([]btfMember))
|
members, err := convertMembers(raw.data.([]btfMember))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "struct %s (id %d)", name, id)
|
return nil, fmt.Errorf("struct %s (id %d): %w", name, id, err)
|
||||||
}
|
}
|
||||||
typ = &Struct{id, name, raw.Size(), members}
|
typ = &Struct{id, name, raw.Size(), members}
|
||||||
|
|
||||||
case kindUnion:
|
case kindUnion:
|
||||||
members, err := convertMembers(raw.data.([]btfMember))
|
members, err := convertMembers(raw.data.([]btfMember))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "union %s (id %d)", name, id)
|
return nil, fmt.Errorf("union %s (id %d): %w", name, id, err)
|
||||||
}
|
}
|
||||||
typ = &Union{id, name, raw.Size(), members}
|
typ = &Union{id, name, raw.Size(), members}
|
||||||
|
|
||||||
@ -488,44 +504,55 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
|
|
||||||
case kindTypedef:
|
case kindTypedef:
|
||||||
typedef := &Typedef{id, name, nil}
|
typedef := &Typedef{id, name, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &typedef.Type})
|
fixup(raw.Type(), kindUnknown, &typedef.Type)
|
||||||
typ = typedef
|
typ = typedef
|
||||||
|
|
||||||
case kindVolatile:
|
case kindVolatile:
|
||||||
volatile := &Volatile{id, nil}
|
volatile := &Volatile{id, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &volatile.Type})
|
fixup(raw.Type(), kindUnknown, &volatile.Type)
|
||||||
typ = volatile
|
typ = volatile
|
||||||
|
|
||||||
case kindConst:
|
case kindConst:
|
||||||
cnst := &Const{id, nil}
|
cnst := &Const{id, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &cnst.Type})
|
fixup(raw.Type(), kindUnknown, &cnst.Type)
|
||||||
typ = cnst
|
typ = cnst
|
||||||
|
|
||||||
case kindRestrict:
|
case kindRestrict:
|
||||||
restrict := &Restrict{id, nil}
|
restrict := &Restrict{id, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &restrict.Type})
|
fixup(raw.Type(), kindUnknown, &restrict.Type)
|
||||||
typ = restrict
|
typ = restrict
|
||||||
|
|
||||||
case kindFunc:
|
case kindFunc:
|
||||||
fn := &Func{id, name, nil}
|
fn := &Func{id, name, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &fn.Type})
|
fixup(raw.Type(), kindFuncProto, &fn.Type)
|
||||||
typ = fn
|
typ = fn
|
||||||
|
|
||||||
case kindFuncProto:
|
case kindFuncProto:
|
||||||
fp := &FuncProto{id, nil}
|
fp := &FuncProto{id, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &fp.Return})
|
fixup(raw.Type(), kindUnknown, &fp.Return)
|
||||||
typ = fp
|
typ = fp
|
||||||
|
|
||||||
case kindVar:
|
case kindVar:
|
||||||
v := &Var{id, name, nil}
|
v := &Var{id, name, nil}
|
||||||
fixups = append(fixups, fixup{raw.Type(), &v.Type})
|
fixup(raw.Type(), kindUnknown, &v.Type)
|
||||||
typ = v
|
typ = v
|
||||||
|
|
||||||
case kindDatasec:
|
case kindDatasec:
|
||||||
typ = &Datasec{id, name, raw.SizeType}
|
btfVars := raw.data.([]btfVarSecinfo)
|
||||||
|
vars := make([]VarSecinfo, 0, len(btfVars))
|
||||||
|
for _, btfVar := range btfVars {
|
||||||
|
vars = append(vars, VarSecinfo{
|
||||||
|
Offset: btfVar.Offset,
|
||||||
|
Size: btfVar.Size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for i := range vars {
|
||||||
|
fixup(btfVars[i].Type, kindVar, &vars[i].Type)
|
||||||
|
}
|
||||||
|
typ = &Datasec{id, name, raw.SizeType, vars}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
return nil, fmt.Errorf("type id %d: unknown kind: %v", id, raw.Kind())
|
||||||
}
|
}
|
||||||
|
|
||||||
types = append(types, typ)
|
types = append(types, typ)
|
||||||
@ -540,7 +567,17 @@ func inflateRawTypes(rawTypes []rawType, rawStrings stringTable) (namedTypes map
|
|||||||
for _, fixup := range fixups {
|
for _, fixup := range fixups {
|
||||||
i := int(fixup.id)
|
i := int(fixup.id)
|
||||||
if i >= len(types) {
|
if i >= len(types) {
|
||||||
return nil, errors.Errorf("reference to invalid type id: %d", fixup.id)
|
return nil, fmt.Errorf("reference to invalid type id: %d", fixup.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default void (id 0) to unknown
|
||||||
|
rawKind := kindUnknown
|
||||||
|
if i > 0 {
|
||||||
|
rawKind = rawTypes[i-1].Kind()
|
||||||
|
}
|
||||||
|
|
||||||
|
if expected := fixup.expectedKind; expected != kindUnknown && rawKind != expected {
|
||||||
|
return nil, fmt.Errorf("expected type id %d to have kind %s, found %s", fixup.id, expected, rawKind)
|
||||||
}
|
}
|
||||||
|
|
||||||
*fixup.typ = types[i]
|
*fixup.typ = types[i]
|
||||||
|
60
vendor/github.com/cilium/ebpf/internal/cpu.go
generated
vendored
60
vendor/github.com/cilium/ebpf/internal/cpu.go
generated
vendored
@ -2,10 +2,9 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"io/ioutil"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var sysCPU struct {
|
var sysCPU struct {
|
||||||
@ -18,45 +17,44 @@ var sysCPU struct {
|
|||||||
// Logical CPU numbers must be of the form 0-n
|
// Logical CPU numbers must be of the form 0-n
|
||||||
func PossibleCPUs() (int, error) {
|
func PossibleCPUs() (int, error) {
|
||||||
sysCPU.once.Do(func() {
|
sysCPU.once.Do(func() {
|
||||||
sysCPU.num, sysCPU.err = parseCPUs("/sys/devices/system/cpu/possible")
|
sysCPU.num, sysCPU.err = parseCPUsFromFile("/sys/devices/system/cpu/possible")
|
||||||
})
|
})
|
||||||
|
|
||||||
return sysCPU.num, sysCPU.err
|
return sysCPU.num, sysCPU.err
|
||||||
}
|
}
|
||||||
|
|
||||||
var onlineCPU struct {
|
func parseCPUsFromFile(path string) (int, error) {
|
||||||
once sync.Once
|
spec, err := ioutil.ReadFile(path)
|
||||||
err error
|
|
||||||
num int
|
|
||||||
}
|
|
||||||
|
|
||||||
// OnlineCPUs returns the number of currently online CPUs
|
|
||||||
// Logical CPU numbers must be of the form 0-n
|
|
||||||
func OnlineCPUs() (int, error) {
|
|
||||||
onlineCPU.once.Do(func() {
|
|
||||||
onlineCPU.num, onlineCPU.err = parseCPUs("/sys/devices/system/cpu/online")
|
|
||||||
})
|
|
||||||
|
|
||||||
return onlineCPU.num, onlineCPU.err
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseCPUs parses the number of cpus from sysfs,
|
|
||||||
// in the format of "/sys/devices/system/cpu/{possible,online,..}.
|
|
||||||
// Logical CPU numbers must be of the form 0-n
|
|
||||||
func parseCPUs(path string) (int, error) {
|
|
||||||
file, err := os.Open(path)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer file.Close()
|
|
||||||
|
n, err := parseCPUs(string(spec))
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("can't parse %s: %v", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseCPUs parses the number of cpus from a string produced
|
||||||
|
// by bitmap_list_string() in the Linux kernel.
|
||||||
|
// Multiple ranges are rejected, since they can't be unified
|
||||||
|
// into a single number.
|
||||||
|
// This is the format of /sys/devices/system/cpu/possible, it
|
||||||
|
// is not suitable for /sys/devices/system/cpu/online, etc.
|
||||||
|
func parseCPUs(spec string) (int, error) {
|
||||||
|
if strings.Trim(spec, "\n") == "0" {
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
|
||||||
var low, high int
|
var low, high int
|
||||||
n, _ := fmt.Fscanf(file, "%d-%d", &low, &high)
|
n, err := fmt.Sscanf(spec, "%d-%d\n", &low, &high)
|
||||||
if n < 1 || low != 0 {
|
if n != 2 || err != nil {
|
||||||
return 0, errors.Wrapf(err, "%s has unknown format", path)
|
return 0, fmt.Errorf("invalid format: %s", spec)
|
||||||
}
|
}
|
||||||
if n == 1 {
|
if low != 0 {
|
||||||
high = low
|
return 0, fmt.Errorf("CPU spec doesn't start at zero: %s", spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
// cpus is 0 indexed
|
// cpus is 0 indexed
|
||||||
|
15
vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
15
vendor/github.com/cilium/ebpf/internal/errors.go
generated
vendored
@ -2,11 +2,11 @@ package internal
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrorWithLog returns an error that includes logs from the
|
// ErrorWithLog returns an error that includes logs from the
|
||||||
@ -16,19 +16,20 @@ import (
|
|||||||
// the log. It is used to check for truncation of the output.
|
// the log. It is used to check for truncation of the output.
|
||||||
func ErrorWithLog(err error, log []byte, logErr error) error {
|
func ErrorWithLog(err error, log []byte, logErr error) error {
|
||||||
logStr := strings.Trim(CString(log), "\t\r\n ")
|
logStr := strings.Trim(CString(log), "\t\r\n ")
|
||||||
if errors.Cause(logErr) == unix.ENOSPC {
|
if errors.Is(logErr, unix.ENOSPC) {
|
||||||
logStr += " (truncated...)"
|
logStr += " (truncated...)"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &loadError{err, logStr}
|
return &VerifierError{err, logStr}
|
||||||
}
|
}
|
||||||
|
|
||||||
type loadError struct {
|
// VerifierError includes information from the eBPF verifier.
|
||||||
|
type VerifierError struct {
|
||||||
cause error
|
cause error
|
||||||
log string
|
log string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (le *loadError) Error() string {
|
func (le *VerifierError) Error() string {
|
||||||
if le.log == "" {
|
if le.log == "" {
|
||||||
return le.cause.Error()
|
return le.cause.Error()
|
||||||
}
|
}
|
||||||
@ -36,10 +37,6 @@ func (le *loadError) Error() string {
|
|||||||
return fmt.Sprintf("%s: %s", le.cause, le.log)
|
return fmt.Sprintf("%s: %s", le.cause, le.log)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (le *loadError) Cause() error {
|
|
||||||
return le.cause
|
|
||||||
}
|
|
||||||
|
|
||||||
// CString turns a NUL / zero terminated byte buffer into a string.
|
// CString turns a NUL / zero terminated byte buffer into a string.
|
||||||
func CString(in []byte) string {
|
func CString(in []byte) string {
|
||||||
inLen := bytes.IndexByte(in, 0)
|
inLen := bytes.IndexByte(in, 0)
|
||||||
|
12
vendor/github.com/cilium/ebpf/internal/fd.go
generated
vendored
12
vendor/github.com/cilium/ebpf/internal/fd.go
generated
vendored
@ -1,12 +1,13 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrClosedFd = errors.New("use of closed file descriptor")
|
var ErrClosedFd = errors.New("use of closed file descriptor")
|
||||||
@ -56,8 +57,13 @@ func (fd *FD) Dup() (*FD, error) {
|
|||||||
|
|
||||||
dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
|
dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't dup fd")
|
return nil, fmt.Errorf("can't dup fd: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewFD(uint32(dup)), nil
|
return NewFD(uint32(dup)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fd *FD) File(name string) *os.File {
|
||||||
|
fd.Forget()
|
||||||
|
return os.NewFile(uintptr(fd.raw), name)
|
||||||
|
}
|
||||||
|
73
vendor/github.com/cilium/ebpf/internal/feature.go
generated
vendored
73
vendor/github.com/cilium/ebpf/internal/feature.go
generated
vendored
@ -1,12 +1,14 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNotSupported indicates that a feature is not supported by the current kernel.
|
||||||
|
var ErrNotSupported = errors.New("not supported")
|
||||||
|
|
||||||
// UnsupportedFeatureError is returned by FeatureTest() functions.
|
// UnsupportedFeatureError is returned by FeatureTest() functions.
|
||||||
type UnsupportedFeatureError struct {
|
type UnsupportedFeatureError struct {
|
||||||
// The minimum Linux mainline version required for this feature.
|
// The minimum Linux mainline version required for this feature.
|
||||||
@ -21,33 +23,68 @@ func (ufe *UnsupportedFeatureError) Error() string {
|
|||||||
return fmt.Sprintf("%s not supported (requires >= %s)", ufe.Name, ufe.MinimumVersion)
|
return fmt.Sprintf("%s not supported (requires >= %s)", ufe.Name, ufe.MinimumVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is indicates that UnsupportedFeatureError is ErrNotSupported.
|
||||||
|
func (ufe *UnsupportedFeatureError) Is(target error) bool {
|
||||||
|
return target == ErrNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
|
type featureTest struct {
|
||||||
|
sync.Mutex
|
||||||
|
successful bool
|
||||||
|
result error
|
||||||
|
}
|
||||||
|
|
||||||
|
// FeatureTestFn is used to determine whether the kernel supports
|
||||||
|
// a certain feature.
|
||||||
|
//
|
||||||
|
// The return values have the following semantics:
|
||||||
|
//
|
||||||
|
// err != nil: the test couldn't be executed
|
||||||
|
// err == nil && available: the feature is available
|
||||||
|
// err == nil && !available: the feature isn't available
|
||||||
|
type FeatureTestFn func() (available bool, err error)
|
||||||
|
|
||||||
// FeatureTest wraps a function so that it is run at most once.
|
// FeatureTest wraps a function so that it is run at most once.
|
||||||
//
|
//
|
||||||
// name should identify the tested feature, while version must be in the
|
// name should identify the tested feature, while version must be in the
|
||||||
// form Major.Minor[.Patch].
|
// form Major.Minor[.Patch].
|
||||||
//
|
//
|
||||||
// Returns a descriptive UnsupportedFeatureError if the feature is not available.
|
// Returns an error wrapping ErrNotSupported if the feature is not supported.
|
||||||
func FeatureTest(name, version string, fn func() bool) func() error {
|
func FeatureTest(name, version string, fn FeatureTestFn) func() error {
|
||||||
v, err := NewVersion(version)
|
v, err := NewVersion(version)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return func() error { return err }
|
return func() error { return err }
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
ft := new(featureTest)
|
||||||
once sync.Once
|
|
||||||
result error
|
|
||||||
)
|
|
||||||
|
|
||||||
return func() error {
|
return func() error {
|
||||||
once.Do(func() {
|
ft.Lock()
|
||||||
if !fn() {
|
defer ft.Unlock()
|
||||||
result = &UnsupportedFeatureError{
|
|
||||||
MinimumVersion: v,
|
if ft.successful {
|
||||||
Name: name,
|
return ft.result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
available, err := fn()
|
||||||
|
if errors.Is(err, ErrNotSupported) {
|
||||||
|
// The feature test aborted because a dependent feature
|
||||||
|
// is missing, which we should cache.
|
||||||
|
available = false
|
||||||
|
} else if err != nil {
|
||||||
|
// We couldn't execute the feature test to a point
|
||||||
|
// where it could make a determination.
|
||||||
|
// Don't cache the result, just return it.
|
||||||
|
return fmt.Errorf("can't detect support for %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ft.successful = true
|
||||||
|
if !available {
|
||||||
|
ft.result = &UnsupportedFeatureError{
|
||||||
|
MinimumVersion: v,
|
||||||
|
Name: name,
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
return result
|
return ft.result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +98,7 @@ func NewVersion(ver string) (Version, error) {
|
|||||||
var major, minor, patch uint16
|
var major, minor, patch uint16
|
||||||
n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
|
n, _ := fmt.Sscanf(ver, "%d.%d.%d", &major, &minor, &patch)
|
||||||
if n < 2 {
|
if n < 2 {
|
||||||
return Version{}, errors.Errorf("invalid version: %s", ver)
|
return Version{}, fmt.Errorf("invalid version: %s", ver)
|
||||||
}
|
}
|
||||||
return Version{major, minor, patch}, nil
|
return Version{major, minor, patch}, nil
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/cilium/ebpf/internal/io.go
generated
vendored
2
vendor/github.com/cilium/ebpf/internal/io.go
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import "github.com/pkg/errors"
|
import "errors"
|
||||||
|
|
||||||
// DiscardZeroes makes sure that all written bytes are zero
|
// DiscardZeroes makes sure that all written bytes are zero
|
||||||
// before discarding them.
|
// before discarding them.
|
||||||
|
6
vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
6
vendor/github.com/cilium/ebpf/internal/ptr.go
generated
vendored
@ -22,5 +22,9 @@ func NewStringPointer(str string) Pointer {
|
|||||||
return Pointer{}
|
return Pointer{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Pointer{ptr: unsafe.Pointer(&[]byte(str)[0])}
|
// The kernel expects strings to be zero terminated
|
||||||
|
buf := make([]byte, len(str)+1)
|
||||||
|
copy(buf, str)
|
||||||
|
|
||||||
|
return Pointer{ptr: unsafe.Pointer(&buf[0])}
|
||||||
}
|
}
|
||||||
|
118
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
118
vendor/github.com/cilium/ebpf/internal/syscall.go
generated
vendored
@ -1,16 +1,61 @@
|
|||||||
package internal
|
package internal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:generate stringer -output syscall_string.go -type=BPFCmd
|
||||||
|
|
||||||
|
// BPFCmd identifies a subcommand of the bpf syscall.
|
||||||
|
type BPFCmd int
|
||||||
|
|
||||||
|
// Well known BPF commands.
|
||||||
|
const (
|
||||||
|
BPF_MAP_CREATE BPFCmd = iota
|
||||||
|
BPF_MAP_LOOKUP_ELEM
|
||||||
|
BPF_MAP_UPDATE_ELEM
|
||||||
|
BPF_MAP_DELETE_ELEM
|
||||||
|
BPF_MAP_GET_NEXT_KEY
|
||||||
|
BPF_PROG_LOAD
|
||||||
|
BPF_OBJ_PIN
|
||||||
|
BPF_OBJ_GET
|
||||||
|
BPF_PROG_ATTACH
|
||||||
|
BPF_PROG_DETACH
|
||||||
|
BPF_PROG_TEST_RUN
|
||||||
|
BPF_PROG_GET_NEXT_ID
|
||||||
|
BPF_MAP_GET_NEXT_ID
|
||||||
|
BPF_PROG_GET_FD_BY_ID
|
||||||
|
BPF_MAP_GET_FD_BY_ID
|
||||||
|
BPF_OBJ_GET_INFO_BY_FD
|
||||||
|
BPF_PROG_QUERY
|
||||||
|
BPF_RAW_TRACEPOINT_OPEN
|
||||||
|
BPF_BTF_LOAD
|
||||||
|
BPF_BTF_GET_FD_BY_ID
|
||||||
|
BPF_TASK_FD_QUERY
|
||||||
|
BPF_MAP_LOOKUP_AND_DELETE_ELEM
|
||||||
|
BPF_MAP_FREEZE
|
||||||
|
BPF_BTF_GET_NEXT_ID
|
||||||
|
BPF_MAP_LOOKUP_BATCH
|
||||||
|
BPF_MAP_LOOKUP_AND_DELETE_BATCH
|
||||||
|
BPF_MAP_UPDATE_BATCH
|
||||||
|
BPF_MAP_DELETE_BATCH
|
||||||
|
BPF_LINK_CREATE
|
||||||
|
BPF_LINK_UPDATE
|
||||||
|
BPF_LINK_GET_FD_BY_ID
|
||||||
|
BPF_LINK_GET_NEXT_ID
|
||||||
|
BPF_ENABLE_STATS
|
||||||
|
BPF_ITER_CREATE
|
||||||
|
)
|
||||||
|
|
||||||
// BPF wraps SYS_BPF.
|
// BPF wraps SYS_BPF.
|
||||||
//
|
//
|
||||||
// Any pointers contained in attr must use the Pointer type from this package.
|
// Any pointers contained in attr must use the Pointer type from this package.
|
||||||
func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
func BPF(cmd BPFCmd, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
||||||
r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
|
r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
|
||||||
runtime.KeepAlive(attr)
|
runtime.KeepAlive(attr)
|
||||||
|
|
||||||
@ -21,3 +66,74 @@ func BPF(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
|
|||||||
|
|
||||||
return r1, err
|
return r1, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BPFProgAttachAttr struct {
|
||||||
|
TargetFd uint32
|
||||||
|
AttachBpfFd uint32
|
||||||
|
AttachType uint32
|
||||||
|
AttachFlags uint32
|
||||||
|
ReplaceBpfFd uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func BPFProgAttach(attr *BPFProgAttachAttr) error {
|
||||||
|
_, err := BPF(BPF_PROG_ATTACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type BPFProgDetachAttr struct {
|
||||||
|
TargetFd uint32
|
||||||
|
AttachBpfFd uint32
|
||||||
|
AttachType uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
func BPFProgDetach(attr *BPFProgDetachAttr) error {
|
||||||
|
_, err := BPF(BPF_PROG_DETACH, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
type bpfObjAttr struct {
|
||||||
|
fileName Pointer
|
||||||
|
fd uint32
|
||||||
|
fileFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const bpfFSType = 0xcafe4a11
|
||||||
|
|
||||||
|
// BPFObjPin wraps BPF_OBJ_PIN.
|
||||||
|
func BPFObjPin(fileName string, fd *FD) error {
|
||||||
|
dirName := filepath.Dir(fileName)
|
||||||
|
var statfs unix.Statfs_t
|
||||||
|
if err := unix.Statfs(dirName, &statfs); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if uint64(statfs.Type) != bpfFSType {
|
||||||
|
return fmt.Errorf("%s is not on a bpf filesystem", fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
value, err := fd.Value()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := bpfObjAttr{
|
||||||
|
fileName: NewStringPointer(fileName),
|
||||||
|
fd: value,
|
||||||
|
}
|
||||||
|
_, err = BPF(BPF_OBJ_PIN, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("pin object %s: %w", fileName, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BPFObjGet wraps BPF_OBJ_GET.
|
||||||
|
func BPFObjGet(fileName string) (*FD, error) {
|
||||||
|
attr := bpfObjAttr{
|
||||||
|
fileName: NewStringPointer(fileName),
|
||||||
|
}
|
||||||
|
ptr, err := BPF(BPF_OBJ_GET, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get object %s: %w", fileName, err)
|
||||||
|
}
|
||||||
|
return NewFD(uint32(ptr)), nil
|
||||||
|
}
|
||||||
|
56
vendor/github.com/cilium/ebpf/internal/syscall_string.go
generated
vendored
Normal file
56
vendor/github.com/cilium/ebpf/internal/syscall_string.go
generated
vendored
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Code generated by "stringer -output syscall_string.go -type=BPFCmd"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[BPF_MAP_CREATE-0]
|
||||||
|
_ = x[BPF_MAP_LOOKUP_ELEM-1]
|
||||||
|
_ = x[BPF_MAP_UPDATE_ELEM-2]
|
||||||
|
_ = x[BPF_MAP_DELETE_ELEM-3]
|
||||||
|
_ = x[BPF_MAP_GET_NEXT_KEY-4]
|
||||||
|
_ = x[BPF_PROG_LOAD-5]
|
||||||
|
_ = x[BPF_OBJ_PIN-6]
|
||||||
|
_ = x[BPF_OBJ_GET-7]
|
||||||
|
_ = x[BPF_PROG_ATTACH-8]
|
||||||
|
_ = x[BPF_PROG_DETACH-9]
|
||||||
|
_ = x[BPF_PROG_TEST_RUN-10]
|
||||||
|
_ = x[BPF_PROG_GET_NEXT_ID-11]
|
||||||
|
_ = x[BPF_MAP_GET_NEXT_ID-12]
|
||||||
|
_ = x[BPF_PROG_GET_FD_BY_ID-13]
|
||||||
|
_ = x[BPF_MAP_GET_FD_BY_ID-14]
|
||||||
|
_ = x[BPF_OBJ_GET_INFO_BY_FD-15]
|
||||||
|
_ = x[BPF_PROG_QUERY-16]
|
||||||
|
_ = x[BPF_RAW_TRACEPOINT_OPEN-17]
|
||||||
|
_ = x[BPF_BTF_LOAD-18]
|
||||||
|
_ = x[BPF_BTF_GET_FD_BY_ID-19]
|
||||||
|
_ = x[BPF_TASK_FD_QUERY-20]
|
||||||
|
_ = x[BPF_MAP_LOOKUP_AND_DELETE_ELEM-21]
|
||||||
|
_ = x[BPF_MAP_FREEZE-22]
|
||||||
|
_ = x[BPF_BTF_GET_NEXT_ID-23]
|
||||||
|
_ = x[BPF_MAP_LOOKUP_BATCH-24]
|
||||||
|
_ = x[BPF_MAP_LOOKUP_AND_DELETE_BATCH-25]
|
||||||
|
_ = x[BPF_MAP_UPDATE_BATCH-26]
|
||||||
|
_ = x[BPF_MAP_DELETE_BATCH-27]
|
||||||
|
_ = x[BPF_LINK_CREATE-28]
|
||||||
|
_ = x[BPF_LINK_UPDATE-29]
|
||||||
|
_ = x[BPF_LINK_GET_FD_BY_ID-30]
|
||||||
|
_ = x[BPF_LINK_GET_NEXT_ID-31]
|
||||||
|
_ = x[BPF_ENABLE_STATS-32]
|
||||||
|
_ = x[BPF_ITER_CREATE-33]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _BPFCmd_name = "BPF_MAP_CREATEBPF_MAP_LOOKUP_ELEMBPF_MAP_UPDATE_ELEMBPF_MAP_DELETE_ELEMBPF_MAP_GET_NEXT_KEYBPF_PROG_LOADBPF_OBJ_PINBPF_OBJ_GETBPF_PROG_ATTACHBPF_PROG_DETACHBPF_PROG_TEST_RUNBPF_PROG_GET_NEXT_IDBPF_MAP_GET_NEXT_IDBPF_PROG_GET_FD_BY_IDBPF_MAP_GET_FD_BY_IDBPF_OBJ_GET_INFO_BY_FDBPF_PROG_QUERYBPF_RAW_TRACEPOINT_OPENBPF_BTF_LOADBPF_BTF_GET_FD_BY_IDBPF_TASK_FD_QUERYBPF_MAP_LOOKUP_AND_DELETE_ELEMBPF_MAP_FREEZEBPF_BTF_GET_NEXT_IDBPF_MAP_LOOKUP_BATCHBPF_MAP_LOOKUP_AND_DELETE_BATCHBPF_MAP_UPDATE_BATCHBPF_MAP_DELETE_BATCHBPF_LINK_CREATEBPF_LINK_UPDATEBPF_LINK_GET_FD_BY_IDBPF_LINK_GET_NEXT_IDBPF_ENABLE_STATSBPF_ITER_CREATE"
|
||||||
|
|
||||||
|
var _BPFCmd_index = [...]uint16{0, 14, 33, 52, 71, 91, 104, 115, 126, 141, 156, 173, 193, 212, 233, 253, 275, 289, 312, 324, 344, 361, 391, 405, 424, 444, 475, 495, 515, 530, 545, 566, 586, 602, 617}
|
||||||
|
|
||||||
|
func (i BPFCmd) String() string {
|
||||||
|
if i < 0 || i >= BPFCmd(len(_BPFCmd_index)-1) {
|
||||||
|
return "BPFCmd(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _BPFCmd_name[_BPFCmd_index[i]:_BPFCmd_index[i+1]]
|
||||||
|
}
|
23
vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
23
vendor/github.com/cilium/ebpf/internal/unix/types_linux.go
generated
vendored
@ -10,10 +10,17 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ENOENT = linux.ENOENT
|
ENOENT = linux.ENOENT
|
||||||
|
EEXIST = linux.EEXIST
|
||||||
EAGAIN = linux.EAGAIN
|
EAGAIN = linux.EAGAIN
|
||||||
ENOSPC = linux.ENOSPC
|
ENOSPC = linux.ENOSPC
|
||||||
EINVAL = linux.EINVAL
|
EINVAL = linux.EINVAL
|
||||||
EPOLLIN = linux.EPOLLIN
|
EPOLLIN = linux.EPOLLIN
|
||||||
|
EINTR = linux.EINTR
|
||||||
|
EPERM = linux.EPERM
|
||||||
|
ESRCH = linux.ESRCH
|
||||||
|
ENODEV = linux.ENODEV
|
||||||
|
BPF_F_RDONLY_PROG = linux.BPF_F_RDONLY_PROG
|
||||||
|
BPF_F_WRONLY_PROG = linux.BPF_F_WRONLY_PROG
|
||||||
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
|
BPF_OBJ_NAME_LEN = linux.BPF_OBJ_NAME_LEN
|
||||||
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
|
BPF_TAG_SIZE = linux.BPF_TAG_SIZE
|
||||||
SYS_BPF = linux.SYS_BPF
|
SYS_BPF = linux.SYS_BPF
|
||||||
@ -31,6 +38,7 @@ const (
|
|||||||
PERF_SAMPLE_RAW = linux.PERF_SAMPLE_RAW
|
PERF_SAMPLE_RAW = linux.PERF_SAMPLE_RAW
|
||||||
PERF_FLAG_FD_CLOEXEC = linux.PERF_FLAG_FD_CLOEXEC
|
PERF_FLAG_FD_CLOEXEC = linux.PERF_FLAG_FD_CLOEXEC
|
||||||
RLIM_INFINITY = linux.RLIM_INFINITY
|
RLIM_INFINITY = linux.RLIM_INFINITY
|
||||||
|
RLIMIT_MEMLOCK = linux.RLIMIT_MEMLOCK
|
||||||
)
|
)
|
||||||
|
|
||||||
// Statfs_t is a wrapper
|
// Statfs_t is a wrapper
|
||||||
@ -125,3 +133,18 @@ type Utsname = linux.Utsname
|
|||||||
func Uname(buf *Utsname) (err error) {
|
func Uname(buf *Utsname) (err error) {
|
||||||
return linux.Uname(buf)
|
return linux.Uname(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getpid is a wrapper
|
||||||
|
func Getpid() int {
|
||||||
|
return linux.Getpid()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gettid is a wrapper
|
||||||
|
func Gettid() int {
|
||||||
|
return linux.Gettid()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tgkill is a wrapper
|
||||||
|
func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
|
||||||
|
return linux.Tgkill(tgid, tid, sig)
|
||||||
|
}
|
||||||
|
26
vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
26
vendor/github.com/cilium/ebpf/internal/unix/types_other.go
generated
vendored
@ -12,9 +12,16 @@ var errNonLinux = fmt.Errorf("unsupported platform %s/%s", runtime.GOOS, runtime
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ENOENT = syscall.ENOENT
|
ENOENT = syscall.ENOENT
|
||||||
|
EEXIST = syscall.EEXIST
|
||||||
EAGAIN = syscall.EAGAIN
|
EAGAIN = syscall.EAGAIN
|
||||||
ENOSPC = syscall.ENOSPC
|
ENOSPC = syscall.ENOSPC
|
||||||
EINVAL = syscall.EINVAL
|
EINVAL = syscall.EINVAL
|
||||||
|
EINTR = syscall.EINTR
|
||||||
|
EPERM = syscall.EPERM
|
||||||
|
ESRCH = syscall.ESRCH
|
||||||
|
ENODEV = syscall.ENODEV
|
||||||
|
BPF_F_RDONLY_PROG = 0
|
||||||
|
BPF_F_WRONLY_PROG = 0
|
||||||
BPF_OBJ_NAME_LEN = 0x10
|
BPF_OBJ_NAME_LEN = 0x10
|
||||||
BPF_TAG_SIZE = 0x8
|
BPF_TAG_SIZE = 0x8
|
||||||
SYS_BPF = 321
|
SYS_BPF = 321
|
||||||
@ -32,6 +39,8 @@ const (
|
|||||||
PerfBitWatermark = 0x4000
|
PerfBitWatermark = 0x4000
|
||||||
PERF_SAMPLE_RAW = 0x400
|
PERF_SAMPLE_RAW = 0x400
|
||||||
PERF_FLAG_FD_CLOEXEC = 0x8
|
PERF_FLAG_FD_CLOEXEC = 0x8
|
||||||
|
RLIM_INFINITY = 0x7fffffffffffffff
|
||||||
|
RLIMIT_MEMLOCK = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
// Statfs_t is a wrapper
|
// Statfs_t is a wrapper
|
||||||
@ -184,10 +193,25 @@ func PerfEventOpen(attr *PerfEventAttr, pid int, cpu int, groupFd int, flags int
|
|||||||
|
|
||||||
// Utsname is a wrapper
|
// Utsname is a wrapper
|
||||||
type Utsname struct {
|
type Utsname struct {
|
||||||
Release [65]byte
|
Release [65]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uname is a wrapper
|
// Uname is a wrapper
|
||||||
func Uname(buf *Utsname) (err error) {
|
func Uname(buf *Utsname) (err error) {
|
||||||
return errNonLinux
|
return errNonLinux
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Getpid is a wrapper
|
||||||
|
func Getpid() int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gettid is a wrapper
|
||||||
|
func Gettid() int {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tgkill is a wrapper
|
||||||
|
func Tgkill(tgid int, tid int, sig syscall.Signal) (err error) {
|
||||||
|
return errNonLinux
|
||||||
|
}
|
||||||
|
62
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
62
vendor/github.com/cilium/ebpf/linker.go
generated
vendored
@ -1,43 +1,60 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// link resolves bpf-to-bpf calls.
|
// link resolves bpf-to-bpf calls.
|
||||||
//
|
//
|
||||||
// Each library may contain multiple functions / labels, and is only linked
|
// Each library may contain multiple functions / labels, and is only linked
|
||||||
// if the program being edited references one of these functions.
|
// if prog references one of these functions.
|
||||||
//
|
//
|
||||||
// Libraries must not require linking themselves.
|
// Libraries also linked.
|
||||||
func link(prog *ProgramSpec, libs []*ProgramSpec) error {
|
func link(prog *ProgramSpec, libs []*ProgramSpec) error {
|
||||||
for _, lib := range libs {
|
var (
|
||||||
insns, err := linkSection(prog.Instructions, lib.Instructions)
|
linked = make(map[*ProgramSpec]bool)
|
||||||
if err != nil {
|
pending = []asm.Instructions{prog.Instructions}
|
||||||
return errors.Wrapf(err, "linking %s", lib.Name)
|
insns asm.Instructions
|
||||||
}
|
)
|
||||||
|
for len(pending) > 0 {
|
||||||
|
insns, pending = pending[0], pending[1:]
|
||||||
|
for _, lib := range libs {
|
||||||
|
if linked[lib] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if len(insns) == len(prog.Instructions) {
|
needed, err := needSection(insns, lib.Instructions)
|
||||||
continue
|
if err != nil {
|
||||||
}
|
return fmt.Errorf("linking %s: %w", lib.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
prog.Instructions = insns
|
if !needed {
|
||||||
if prog.BTF != nil && lib.BTF != nil {
|
continue
|
||||||
if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
|
}
|
||||||
return errors.Wrapf(err, "linking BTF of %s", lib.Name)
|
|
||||||
|
linked[lib] = true
|
||||||
|
prog.Instructions = append(prog.Instructions, lib.Instructions...)
|
||||||
|
pending = append(pending, lib.Instructions)
|
||||||
|
|
||||||
|
if prog.BTF != nil && lib.BTF != nil {
|
||||||
|
if err := btf.ProgramAppend(prog.BTF, lib.BTF); err != nil {
|
||||||
|
return fmt.Errorf("linking BTF of %s: %w", lib.Name, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
|
func needSection(insns, section asm.Instructions) (bool, error) {
|
||||||
// A map of symbols to the libraries which contain them.
|
// A map of symbols to the libraries which contain them.
|
||||||
symbols, err := section.SymbolOffsets()
|
symbols, err := section.SymbolOffsets()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ins := range insns {
|
for _, ins := range insns {
|
||||||
@ -45,7 +62,7 @@ func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if ins.OpCode.JumpOp() != asm.Call || ins.Src != asm.R1 {
|
if ins.OpCode.JumpOp() != asm.Call || ins.Src != asm.PseudoCall {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,11 +77,10 @@ func linkSection(insns, section asm.Instructions) (asm.Instructions, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// At this point we know that at least one function in the
|
// At this point we know that at least one function in the
|
||||||
// library is called from insns. Merge the two sections.
|
// library is called from insns, so we have to link it.
|
||||||
// The rewrite of ins.Constant happens in asm.Instruction.Marshal.
|
return true, nil
|
||||||
return append(insns, section...), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// None of the functions in the section are called. Do nothing.
|
// None of the functions in the section are called.
|
||||||
return insns, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
331
vendor/github.com/cilium/ebpf/map.go
generated
vendored
331
vendor/github.com/cilium/ebpf/map.go
generated
vendored
@ -1,15 +1,25 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Errors returned by Map and MapIterator methods.
|
||||||
|
var (
|
||||||
|
ErrKeyNotExist = errors.New("key does not exist")
|
||||||
|
ErrKeyExist = errors.New("key already exists")
|
||||||
|
ErrIterationAborted = errors.New("iteration aborted")
|
||||||
|
)
|
||||||
|
|
||||||
|
// MapID represents the unique ID of an eBPF map
|
||||||
|
type MapID uint32
|
||||||
|
|
||||||
// MapSpec defines a Map.
|
// MapSpec defines a Map.
|
||||||
type MapSpec struct {
|
type MapSpec struct {
|
||||||
// Name is passed to the kernel as a debug aid. Must only contain
|
// Name is passed to the kernel as a debug aid. Must only contain
|
||||||
@ -21,6 +31,12 @@ type MapSpec struct {
|
|||||||
MaxEntries uint32
|
MaxEntries uint32
|
||||||
Flags uint32
|
Flags uint32
|
||||||
|
|
||||||
|
// The initial contents of the map. May be nil.
|
||||||
|
Contents []MapKV
|
||||||
|
|
||||||
|
// Whether to freeze a map after setting its initial contents.
|
||||||
|
Freeze bool
|
||||||
|
|
||||||
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
|
||||||
InnerMap *MapSpec
|
InnerMap *MapSpec
|
||||||
|
|
||||||
@ -33,16 +49,26 @@ func (ms *MapSpec) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of the spec.
|
// Copy returns a copy of the spec.
|
||||||
|
//
|
||||||
|
// MapSpec.Contents is a shallow copy.
|
||||||
func (ms *MapSpec) Copy() *MapSpec {
|
func (ms *MapSpec) Copy() *MapSpec {
|
||||||
if ms == nil {
|
if ms == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
cpy := *ms
|
cpy := *ms
|
||||||
|
cpy.Contents = make([]MapKV, len(ms.Contents))
|
||||||
|
copy(cpy.Contents, ms.Contents)
|
||||||
cpy.InnerMap = ms.InnerMap.Copy()
|
cpy.InnerMap = ms.InnerMap.Copy()
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MapKV is used to initialize the contents of a Map.
|
||||||
|
type MapKV struct {
|
||||||
|
Key interface{}
|
||||||
|
Value interface{}
|
||||||
|
}
|
||||||
|
|
||||||
// Map represents a Map file descriptor.
|
// Map represents a Map file descriptor.
|
||||||
//
|
//
|
||||||
// It is not safe to close a map which is used by other goroutines.
|
// It is not safe to close a map which is used by other goroutines.
|
||||||
@ -81,14 +107,18 @@ func NewMapFromFD(fd int) (*Map, error) {
|
|||||||
//
|
//
|
||||||
// Creating a map for the first time will perform feature detection
|
// Creating a map for the first time will perform feature detection
|
||||||
// by creating small, temporary maps.
|
// by creating small, temporary maps.
|
||||||
|
//
|
||||||
|
// The caller is responsible for ensuring the process' rlimit is set
|
||||||
|
// sufficiently high for locking memory during map creation. This can be done
|
||||||
|
// by calling unix.Setrlimit with unix.RLIMIT_MEMLOCK prior to calling NewMap.
|
||||||
func NewMap(spec *MapSpec) (*Map, error) {
|
func NewMap(spec *MapSpec) (*Map, error) {
|
||||||
if spec.BTF == nil {
|
if spec.BTF == nil {
|
||||||
return newMapWithBTF(spec, nil)
|
return newMapWithBTF(spec, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
handle, err := btf.NewHandle(btf.MapSpec(spec.BTF))
|
handle, err := btf.NewHandle(btf.MapSpec(spec.BTF))
|
||||||
if err != nil && !btf.IsNotSupported(err) {
|
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
|
||||||
return nil, errors.Wrap(err, "can't load BTF")
|
return nil, fmt.Errorf("can't load BTF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newMapWithBTF(spec, handle)
|
return newMapWithBTF(spec, handle)
|
||||||
@ -100,7 +130,7 @@ func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if spec.InnerMap == nil {
|
if spec.InnerMap == nil {
|
||||||
return nil, errors.Errorf("%s requires InnerMap", spec.Type)
|
return nil, fmt.Errorf("%s requires InnerMap", spec.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
template, err := createMap(spec.InnerMap, nil, handle)
|
template, err := createMap(spec.InnerMap, nil, handle)
|
||||||
@ -113,7 +143,7 @@ func newMapWithBTF(spec *MapSpec, handle *btf.Handle) (*Map, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, error) {
|
func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, error) {
|
||||||
spec = spec.Copy()
|
abi := newMapABIFromSpec(spec)
|
||||||
|
|
||||||
switch spec.Type {
|
switch spec.Type {
|
||||||
case ArrayOfMaps:
|
case ArrayOfMaps:
|
||||||
@ -123,43 +153,50 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if spec.ValueSize != 0 && spec.ValueSize != 4 {
|
if abi.ValueSize != 0 && abi.ValueSize != 4 {
|
||||||
return nil, errors.Errorf("ValueSize must be zero or four for map of map")
|
return nil, errors.New("ValueSize must be zero or four for map of map")
|
||||||
}
|
}
|
||||||
spec.ValueSize = 4
|
abi.ValueSize = 4
|
||||||
|
|
||||||
case PerfEventArray:
|
case PerfEventArray:
|
||||||
if spec.KeySize != 0 {
|
if abi.KeySize != 0 && abi.KeySize != 4 {
|
||||||
return nil, errors.Errorf("KeySize must be zero for perf event array")
|
return nil, errors.New("KeySize must be zero or four for perf event array")
|
||||||
}
|
|
||||||
if spec.ValueSize != 0 {
|
|
||||||
return nil, errors.Errorf("ValueSize must be zero for perf event array")
|
|
||||||
}
|
|
||||||
if spec.MaxEntries == 0 {
|
|
||||||
n, err := internal.OnlineCPUs()
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "perf event array")
|
|
||||||
}
|
|
||||||
spec.MaxEntries = uint32(n)
|
|
||||||
}
|
}
|
||||||
|
abi.KeySize = 4
|
||||||
|
|
||||||
spec.KeySize = 4
|
if abi.ValueSize != 0 && abi.ValueSize != 4 {
|
||||||
spec.ValueSize = 4
|
return nil, errors.New("ValueSize must be zero or four for perf event array")
|
||||||
|
}
|
||||||
|
abi.ValueSize = 4
|
||||||
|
|
||||||
|
if abi.MaxEntries == 0 {
|
||||||
|
n, err := internal.PossibleCPUs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("perf event array: %w", err)
|
||||||
|
}
|
||||||
|
abi.MaxEntries = uint32(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if abi.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze {
|
||||||
|
if err := haveMapMutabilityModifiers(); err != nil {
|
||||||
|
return nil, fmt.Errorf("map create: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := bpfMapCreateAttr{
|
attr := bpfMapCreateAttr{
|
||||||
mapType: spec.Type,
|
mapType: abi.Type,
|
||||||
keySize: spec.KeySize,
|
keySize: abi.KeySize,
|
||||||
valueSize: spec.ValueSize,
|
valueSize: abi.ValueSize,
|
||||||
maxEntries: spec.MaxEntries,
|
maxEntries: abi.MaxEntries,
|
||||||
flags: spec.Flags,
|
flags: abi.Flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if inner != nil {
|
if inner != nil {
|
||||||
var err error
|
var err error
|
||||||
attr.innerMapFd, err = inner.Value()
|
attr.innerMapFd, err = inner.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "map create")
|
return nil, fmt.Errorf("map create: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,21 +206,33 @@ func createMap(spec *MapSpec, inner *internal.FD, handle *btf.Handle) (*Map, err
|
|||||||
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
|
attr.btfValueTypeID = btf.MapValue(spec.BTF).ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
name, err := newBPFObjName(spec.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "map create")
|
|
||||||
}
|
|
||||||
|
|
||||||
if haveObjName() == nil {
|
if haveObjName() == nil {
|
||||||
attr.mapName = name
|
attr.mapName = newBPFObjName(spec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := bpfMapCreate(&attr)
|
fd, err := bpfMapCreate(&attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "map create")
|
return nil, fmt.Errorf("map create: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newMap(fd, spec.Name, newMapABIFromSpec(spec))
|
m, err := newMap(fd, spec.Name, abi)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := m.populate(spec.Contents); err != nil {
|
||||||
|
m.Close()
|
||||||
|
return nil, fmt.Errorf("map create: can't set initial contents: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Freeze {
|
||||||
|
if err := m.Freeze(); err != nil {
|
||||||
|
m.Close()
|
||||||
|
return nil, fmt.Errorf("can't freeze map: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) {
|
func newMap(fd *internal.FD, name string, abi *MapABI) (*Map, error) {
|
||||||
@ -251,9 +300,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
|||||||
*value = m
|
*value = m
|
||||||
return nil
|
return nil
|
||||||
case *Map:
|
case *Map:
|
||||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||||
case Map:
|
case Map:
|
||||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Map)(nil))
|
||||||
|
|
||||||
case **Program:
|
case **Program:
|
||||||
p, err := unmarshalProgram(valueBytes)
|
p, err := unmarshalProgram(valueBytes)
|
||||||
@ -265,9 +314,9 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
|||||||
*value = p
|
*value = p
|
||||||
return nil
|
return nil
|
||||||
case *Program:
|
case *Program:
|
||||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||||
case Program:
|
case Program:
|
||||||
return errors.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
return fmt.Errorf("can't unmarshal into %T, need %T", value, (**Program)(nil))
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return unmarshalBytes(valueOut, valueBytes)
|
return unmarshalBytes(valueOut, valueBytes)
|
||||||
@ -275,16 +324,18 @@ func (m *Map) Lookup(key, valueOut interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LookupAndDelete retrieves and deletes a value from a Map.
|
// LookupAndDelete retrieves and deletes a value from a Map.
|
||||||
|
//
|
||||||
|
// Returns ErrKeyNotExist if the key doesn't exist.
|
||||||
func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
|
func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
|
||||||
valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
|
valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
|
||||||
|
|
||||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return fmt.Errorf("can't marshal key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil {
|
if err := bpfMapLookupAndDelete(m.fd, keyPtr, valuePtr); err != nil {
|
||||||
return errors.WithMessage(err, "lookup and delete and delete failed")
|
return fmt.Errorf("lookup and delete failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return unmarshalBytes(valueOut, valueBytes)
|
return unmarshalBytes(valueOut, valueBytes)
|
||||||
@ -298,7 +349,7 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
|||||||
valuePtr := internal.NewSlicePointer(valueBytes)
|
valuePtr := internal.NewSlicePointer(valueBytes)
|
||||||
|
|
||||||
err := m.lookup(key, valuePtr)
|
err := m.lookup(key, valuePtr)
|
||||||
if IsNotExist(err) {
|
if errors.Is(err, ErrKeyNotExist) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,11 +359,13 @@ func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
|
|||||||
func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error {
|
func (m *Map) lookup(key interface{}, valueOut internal.Pointer) error {
|
||||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return fmt.Errorf("can't marshal key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bpfMapLookupElem(m.fd, keyPtr, valueOut)
|
if err = bpfMapLookupElem(m.fd, keyPtr, valueOut); err != nil {
|
||||||
return errors.WithMessage(err, "lookup failed")
|
return fmt.Errorf("lookup failed: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MapUpdateFlags controls the behaviour of the Map.Update call.
|
// MapUpdateFlags controls the behaviour of the Map.Update call.
|
||||||
@ -340,7 +393,7 @@ func (m *Map) Put(key, value interface{}) error {
|
|||||||
func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
|
func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
|
||||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return fmt.Errorf("can't marshal key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var valuePtr internal.Pointer
|
var valuePtr internal.Pointer
|
||||||
@ -350,28 +403,36 @@ func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
|
|||||||
valuePtr, err = marshalPtr(value, int(m.abi.ValueSize))
|
valuePtr, err = marshalPtr(value, int(m.abi.ValueSize))
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal value")
|
return fmt.Errorf("can't marshal value: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags))
|
if err = bpfMapUpdateElem(m.fd, keyPtr, valuePtr, uint64(flags)); err != nil {
|
||||||
|
return fmt.Errorf("update failed: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete removes a value.
|
// Delete removes a value.
|
||||||
//
|
//
|
||||||
// Returns an error if the key does not exist, see IsNotExist.
|
// Returns ErrKeyNotExist if the key does not exist.
|
||||||
func (m *Map) Delete(key interface{}) error {
|
func (m *Map) Delete(key interface{}) error {
|
||||||
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err := marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return fmt.Errorf("can't marshal key: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bpfMapDeleteElem(m.fd, keyPtr)
|
if err = bpfMapDeleteElem(m.fd, keyPtr); err != nil {
|
||||||
return errors.WithMessage(err, "can't delete key")
|
return fmt.Errorf("delete failed: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextKey finds the key following an initial key.
|
// NextKey finds the key following an initial key.
|
||||||
//
|
//
|
||||||
// See NextKeyBytes for details.
|
// See NextKeyBytes for details.
|
||||||
|
//
|
||||||
|
// Returns ErrKeyNotExist if there is no next key.
|
||||||
func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
||||||
nextKeyPtr, nextKeyBytes := makeBuffer(nextKeyOut, int(m.abi.KeySize))
|
nextKeyPtr, nextKeyBytes := makeBuffer(nextKeyOut, int(m.abi.KeySize))
|
||||||
|
|
||||||
@ -383,8 +444,10 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
err := unmarshalBytes(nextKeyOut, nextKeyBytes)
|
if err := unmarshalBytes(nextKeyOut, nextKeyBytes); err != nil {
|
||||||
return errors.WithMessage(err, "can't unmarshal next key")
|
return fmt.Errorf("can't unmarshal next key: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NextKeyBytes returns the key following an initial key as a byte slice.
|
// NextKeyBytes returns the key following an initial key as a byte slice.
|
||||||
@ -392,12 +455,14 @@ func (m *Map) NextKey(key, nextKeyOut interface{}) error {
|
|||||||
// Passing nil will return the first key.
|
// Passing nil will return the first key.
|
||||||
//
|
//
|
||||||
// Use Iterate if you want to traverse all entries in the map.
|
// Use Iterate if you want to traverse all entries in the map.
|
||||||
|
//
|
||||||
|
// Returns nil if there are no more keys.
|
||||||
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
|
||||||
nextKey := make([]byte, m.abi.KeySize)
|
nextKey := make([]byte, m.abi.KeySize)
|
||||||
nextKeyPtr := internal.NewSlicePointer(nextKey)
|
nextKeyPtr := internal.NewSlicePointer(nextKey)
|
||||||
|
|
||||||
err := m.nextKey(key, nextKeyPtr)
|
err := m.nextKey(key, nextKeyPtr)
|
||||||
if IsNotExist(err) {
|
if errors.Is(err, ErrKeyNotExist) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -413,12 +478,14 @@ func (m *Map) nextKey(key interface{}, nextKeyOut internal.Pointer) error {
|
|||||||
if key != nil {
|
if key != nil {
|
||||||
keyPtr, err = marshalPtr(key, int(m.abi.KeySize))
|
keyPtr, err = marshalPtr(key, int(m.abi.KeySize))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.WithMessage(err, "can't marshal key")
|
return fmt.Errorf("can't marshal key: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut)
|
if err = bpfMapGetNextKey(m.fd, keyPtr, nextKeyOut); err != nil {
|
||||||
return errors.WithMessage(err, "can't get next key")
|
return fmt.Errorf("next key failed: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate traverses a map.
|
// Iterate traverses a map.
|
||||||
@ -469,7 +536,7 @@ func (m *Map) Clone() (*Map, error) {
|
|||||||
|
|
||||||
dup, err := m.fd.Dup()
|
dup, err := m.fd.Dup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't clone map")
|
return nil, fmt.Errorf("can't clone map: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newMap(dup, m.name, &m.abi)
|
return newMap(dup, m.name, &m.abi)
|
||||||
@ -479,7 +546,30 @@ func (m *Map) Clone() (*Map, error) {
|
|||||||
//
|
//
|
||||||
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
|
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
|
||||||
func (m *Map) Pin(fileName string) error {
|
func (m *Map) Pin(fileName string) error {
|
||||||
return bpfPinObject(fileName, m.fd)
|
return internal.BPFObjPin(fileName, m.fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Freeze prevents a map to be modified from user space.
|
||||||
|
//
|
||||||
|
// It makes no changes to kernel-side restrictions.
|
||||||
|
func (m *Map) Freeze() error {
|
||||||
|
if err := haveMapMutabilityModifiers(); err != nil {
|
||||||
|
return fmt.Errorf("can't freeze map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := bpfMapFreeze(m.fd); err != nil {
|
||||||
|
return fmt.Errorf("can't freeze map: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) populate(contents []MapKV) error {
|
||||||
|
for _, kv := range contents {
|
||||||
|
if err := m.Put(kv.Key, kv.Value); err != nil {
|
||||||
|
return fmt.Errorf("key %v: %w", kv.Key, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPinnedMap load a Map from a BPF file.
|
// LoadPinnedMap load a Map from a BPF file.
|
||||||
@ -487,7 +577,7 @@ func (m *Map) Pin(fileName string) error {
|
|||||||
// The function is not compatible with nested maps.
|
// The function is not compatible with nested maps.
|
||||||
// Use LoadPinnedMapExplicit in these situations.
|
// Use LoadPinnedMapExplicit in these situations.
|
||||||
func LoadPinnedMap(fileName string) (*Map, error) {
|
func LoadPinnedMap(fileName string) (*Map, error) {
|
||||||
fd, err := bpfGetObject(fileName)
|
fd, err := internal.BPFObjGet(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -501,7 +591,7 @@ func LoadPinnedMap(fileName string) (*Map, error) {
|
|||||||
|
|
||||||
// LoadPinnedMapExplicit loads a map with explicit parameters.
|
// LoadPinnedMapExplicit loads a map with explicit parameters.
|
||||||
func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
|
func LoadPinnedMapExplicit(fileName string, abi *MapABI) (*Map, error) {
|
||||||
fd, err := bpfGetObject(fileName)
|
fd, err := internal.BPFObjGet(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -516,18 +606,7 @@ func unmarshalMap(buf []byte) (*Map, error) {
|
|||||||
// Looking up an entry in a nested map or prog array returns an id,
|
// Looking up an entry in a nested map or prog array returns an id,
|
||||||
// not an fd.
|
// not an fd.
|
||||||
id := internal.NativeEndian.Uint32(buf)
|
id := internal.NativeEndian.Uint32(buf)
|
||||||
fd, err := bpfGetMapFDByID(id)
|
return NewMapFromID(MapID(id))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
name, abi, err := newMapABIFromFd(fd)
|
|
||||||
if err != nil {
|
|
||||||
_ = fd.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return newMap(fd, name, abi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary implements BinaryMarshaler.
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
@ -542,6 +621,60 @@ func (m *Map) MarshalBinary() ([]byte, error) {
|
|||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func patchValue(value []byte, typ btf.Type, replacements map[string]interface{}) error {
|
||||||
|
replaced := make(map[string]bool)
|
||||||
|
replace := func(name string, offset, size int, replacement interface{}) error {
|
||||||
|
if offset+size > len(value) {
|
||||||
|
return fmt.Errorf("%s: offset %d(+%d) is out of bounds", name, offset, size)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := marshalBytes(replacement, size)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("marshal %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(value[offset:offset+size], buf)
|
||||||
|
replaced[name] = true
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
switch parent := typ.(type) {
|
||||||
|
case *btf.Datasec:
|
||||||
|
for _, secinfo := range parent.Vars {
|
||||||
|
name := string(secinfo.Type.(*btf.Var).Name)
|
||||||
|
replacement, ok := replacements[name]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err := replace(name, int(secinfo.Offset), int(secinfo.Size), replacement)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("patching %T is not supported", typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(replaced) == len(replacements) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var missing []string
|
||||||
|
for name := range replacements {
|
||||||
|
if !replaced[name] {
|
||||||
|
missing = append(missing, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(missing) == 1 {
|
||||||
|
return fmt.Errorf("unknown field: %s", missing[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("unknown fields: %s", strings.Join(missing, ","))
|
||||||
|
}
|
||||||
|
|
||||||
// MapIterator iterates a Map.
|
// MapIterator iterates a Map.
|
||||||
//
|
//
|
||||||
// See Map.Iterate.
|
// See Map.Iterate.
|
||||||
@ -562,8 +695,6 @@ func newMapIterator(target *Map) *MapIterator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var errIterationAborted = errors.New("iteration aborted")
|
|
||||||
|
|
||||||
// Next decodes the next key and value.
|
// Next decodes the next key and value.
|
||||||
//
|
//
|
||||||
// Iterating a hash map from which keys are being deleted is not
|
// Iterating a hash map from which keys are being deleted is not
|
||||||
@ -599,7 +730,7 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
|
|||||||
mi.prevKey = mi.prevBytes
|
mi.prevKey = mi.prevBytes
|
||||||
|
|
||||||
mi.err = mi.target.Lookup(nextBytes, valueOut)
|
mi.err = mi.target.Lookup(nextBytes, valueOut)
|
||||||
if IsNotExist(mi.err) {
|
if errors.Is(mi.err, ErrKeyNotExist) {
|
||||||
// Even though the key should be valid, we couldn't look up
|
// Even though the key should be valid, we couldn't look up
|
||||||
// its value. If we're iterating a hash map this is probably
|
// its value. If we're iterating a hash map this is probably
|
||||||
// because a concurrent delete removed the value before we
|
// because a concurrent delete removed the value before we
|
||||||
@ -618,26 +749,50 @@ func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
|
|||||||
return mi.err == nil
|
return mi.err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
mi.err = errIterationAborted
|
mi.err = fmt.Errorf("%w", ErrIterationAborted)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Err returns any encountered error.
|
// Err returns any encountered error.
|
||||||
//
|
//
|
||||||
// The method must be called after Next returns nil.
|
// The method must be called after Next returns nil.
|
||||||
|
//
|
||||||
|
// Returns ErrIterationAborted if it wasn't possible to do a full iteration.
|
||||||
func (mi *MapIterator) Err() error {
|
func (mi *MapIterator) Err() error {
|
||||||
return mi.err
|
return mi.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotExist returns true if the error indicates that a
|
// MapGetNextID returns the ID of the next eBPF map.
|
||||||
// key doesn't exist.
|
//
|
||||||
func IsNotExist(err error) bool {
|
// Returns ErrNotExist, if there is no next eBPF map.
|
||||||
return errors.Cause(err) == unix.ENOENT
|
func MapGetNextID(startID MapID) (MapID, error) {
|
||||||
|
id, err := objGetNextID(internal.BPF_MAP_GET_NEXT_ID, uint32(startID))
|
||||||
|
return MapID(id), err
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsIterationAborted returns true if the iteration was aborted.
|
// NewMapFromID returns the map for a given id.
|
||||||
//
|
//
|
||||||
// This occurs when keys are deleted from a hash map during iteration.
|
// Returns ErrNotExist, if there is no eBPF map with the given id.
|
||||||
func IsIterationAborted(err error) bool {
|
func NewMapFromID(id MapID) (*Map, error) {
|
||||||
return errors.Cause(err) == errIterationAborted
|
fd, err := bpfObjGetFDByID(internal.BPF_MAP_GET_FD_BY_ID, uint32(id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name, abi, err := newMapABIFromFd(fd)
|
||||||
|
if err != nil {
|
||||||
|
_ = fd.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newMap(fd, name, abi)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the systemwide unique ID of the map.
|
||||||
|
func (m *Map) ID() (MapID, error) {
|
||||||
|
info, err := bpfGetMapInfoByFD(m.fd)
|
||||||
|
if err != nil {
|
||||||
|
return MapID(0), err
|
||||||
|
}
|
||||||
|
return MapID(info.id), nil
|
||||||
}
|
}
|
||||||
|
24
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
24
vendor/github.com/cilium/ebpf/marshalers.go
generated
vendored
@ -4,13 +4,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding"
|
"encoding"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
|
func marshalPtr(data interface{}, length int) (internal.Pointer, error) {
|
||||||
@ -46,7 +46,9 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
|||||||
default:
|
default:
|
||||||
var wr bytes.Buffer
|
var wr bytes.Buffer
|
||||||
err = binary.Write(&wr, internal.NativeEndian, value)
|
err = binary.Write(&wr, internal.NativeEndian, value)
|
||||||
err = errors.Wrapf(err, "encoding %T", value)
|
if err != nil {
|
||||||
|
err = fmt.Errorf("encoding %T: %v", value, err)
|
||||||
|
}
|
||||||
buf = wr.Bytes()
|
buf = wr.Bytes()
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -54,7 +56,7 @@ func marshalBytes(data interface{}, length int) (buf []byte, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(buf) != length {
|
if len(buf) != length {
|
||||||
return nil, errors.Errorf("%T doesn't marshal to %d bytes", data, length)
|
return nil, fmt.Errorf("%T doesn't marshal to %d bytes", data, length)
|
||||||
}
|
}
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
@ -95,8 +97,10 @@ func unmarshalBytes(data interface{}, buf []byte) error {
|
|||||||
return errors.New("require pointer to []byte")
|
return errors.New("require pointer to []byte")
|
||||||
default:
|
default:
|
||||||
rd := bytes.NewReader(buf)
|
rd := bytes.NewReader(buf)
|
||||||
err := binary.Read(rd, internal.NativeEndian, value)
|
if err := binary.Read(rd, internal.NativeEndian, value); err != nil {
|
||||||
return errors.Wrapf(err, "decoding %T", value)
|
return fmt.Errorf("decoding %T: %v", value, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +124,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
|
|||||||
sliceValue := reflect.ValueOf(slice)
|
sliceValue := reflect.ValueOf(slice)
|
||||||
sliceLen := sliceValue.Len()
|
sliceLen := sliceValue.Len()
|
||||||
if sliceLen > possibleCPUs {
|
if sliceLen > possibleCPUs {
|
||||||
return internal.Pointer{}, errors.Errorf("per-CPU value exceeds number of CPUs")
|
return internal.Pointer{}, fmt.Errorf("per-CPU value exceeds number of CPUs")
|
||||||
}
|
}
|
||||||
|
|
||||||
alignedElemLength := align(elemLength, 8)
|
alignedElemLength := align(elemLength, 8)
|
||||||
@ -147,7 +151,7 @@ func marshalPerCPUValue(slice interface{}, elemLength int) (internal.Pointer, er
|
|||||||
func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
|
func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) error {
|
||||||
slicePtrType := reflect.TypeOf(slicePtr)
|
slicePtrType := reflect.TypeOf(slicePtr)
|
||||||
if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
|
if slicePtrType.Kind() != reflect.Ptr || slicePtrType.Elem().Kind() != reflect.Slice {
|
||||||
return errors.Errorf("per-cpu value requires pointer to slice")
|
return fmt.Errorf("per-cpu value requires pointer to slice")
|
||||||
}
|
}
|
||||||
|
|
||||||
possibleCPUs, err := internal.PossibleCPUs()
|
possibleCPUs, err := internal.PossibleCPUs()
|
||||||
@ -166,7 +170,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
|
|||||||
|
|
||||||
step := len(buf) / possibleCPUs
|
step := len(buf) / possibleCPUs
|
||||||
if step < elemLength {
|
if step < elemLength {
|
||||||
return errors.Errorf("per-cpu element length is larger than available data")
|
return fmt.Errorf("per-cpu element length is larger than available data")
|
||||||
}
|
}
|
||||||
for i := 0; i < possibleCPUs; i++ {
|
for i := 0; i < possibleCPUs; i++ {
|
||||||
var elem interface{}
|
var elem interface{}
|
||||||
@ -184,7 +188,7 @@ func unmarshalPerCPUValue(slicePtr interface{}, elemLength int, buf []byte) erro
|
|||||||
|
|
||||||
err := unmarshalBytes(elem, elemBytes)
|
err := unmarshalBytes(elem, elemBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "cpu %d", i)
|
return fmt.Errorf("cpu %d: %w", i, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = buf[step:]
|
buf = buf[step:]
|
||||||
|
262
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
262
vendor/github.com/cilium/ebpf/prog.go
generated
vendored
@ -2,20 +2,25 @@ package ebpf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
|
|
||||||
"github.com/cilium/ebpf/asm"
|
"github.com/cilium/ebpf/asm"
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNotSupported is returned whenever the kernel doesn't support a feature.
|
||||||
|
var ErrNotSupported = internal.ErrNotSupported
|
||||||
|
|
||||||
|
// ProgramID represents the unique ID of an eBPF program
|
||||||
|
type ProgramID uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Number of bytes to pad the output buffer for BPF_PROG_TEST_RUN.
|
// Number of bytes to pad the output buffer for BPF_PROG_TEST_RUN.
|
||||||
// This is currently the maximum of spare space allocated for SKB
|
// This is currently the maximum of spare space allocated for SKB
|
||||||
@ -41,17 +46,33 @@ type ProgramOptions struct {
|
|||||||
type ProgramSpec struct {
|
type ProgramSpec struct {
|
||||||
// Name is passed to the kernel as a debug aid. Must only contain
|
// Name is passed to the kernel as a debug aid. Must only contain
|
||||||
// alpha numeric and '_' characters.
|
// alpha numeric and '_' characters.
|
||||||
Name string
|
Name string
|
||||||
Type ProgramType
|
// Type determines at which hook in the kernel a program will run.
|
||||||
AttachType AttachType
|
Type ProgramType
|
||||||
Instructions asm.Instructions
|
AttachType AttachType
|
||||||
License string
|
// Name of a kernel data structure to attach to. It's interpretation
|
||||||
|
// depends on Type and AttachType.
|
||||||
|
AttachTo string
|
||||||
|
Instructions asm.Instructions
|
||||||
|
|
||||||
|
// License of the program. Some helpers are only available if
|
||||||
|
// the license is deemed compatible with the GPL.
|
||||||
|
//
|
||||||
|
// See https://www.kernel.org/doc/html/latest/process/license-rules.html#id1
|
||||||
|
License string
|
||||||
|
|
||||||
|
// Version used by tracing programs.
|
||||||
|
//
|
||||||
|
// Deprecated: superseded by BTF.
|
||||||
KernelVersion uint32
|
KernelVersion uint32
|
||||||
|
|
||||||
// The BTF associated with this program. Changing Instructions
|
// The BTF associated with this program. Changing Instructions
|
||||||
// will most likely invalidate the contained data, and may
|
// will most likely invalidate the contained data, and may
|
||||||
// result in errors when attempting to load it into the kernel.
|
// result in errors when attempting to load it into the kernel.
|
||||||
BTF *btf.Program
|
BTF *btf.Program
|
||||||
|
|
||||||
|
// The byte order this program was compiled for, may be nil.
|
||||||
|
ByteOrder binary.ByteOrder
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy returns a copy of the spec.
|
// Copy returns a copy of the spec.
|
||||||
@ -74,9 +95,10 @@ type Program struct {
|
|||||||
// otherwise it is empty.
|
// otherwise it is empty.
|
||||||
VerifierLog string
|
VerifierLog string
|
||||||
|
|
||||||
fd *internal.FD
|
fd *internal.FD
|
||||||
name string
|
name string
|
||||||
abi ProgramABI
|
abi ProgramABI
|
||||||
|
attachType AttachType
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProgram creates a new Program.
|
// NewProgram creates a new Program.
|
||||||
@ -97,8 +119,8 @@ func NewProgramWithOptions(spec *ProgramSpec, opts ProgramOptions) (*Program, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF))
|
handle, err := btf.NewHandle(btf.ProgramSpec(spec.BTF))
|
||||||
if err != nil && !btf.IsNotSupported(err) {
|
if err != nil && !errors.Is(err, btf.ErrNotSupported) {
|
||||||
return nil, errors.Wrap(err, "can't load BTF")
|
return nil, fmt.Errorf("can't load BTF: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProgramWithBTF(spec, handle, opts)
|
return newProgramWithBTF(spec, handle, opts)
|
||||||
@ -130,6 +152,7 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions)
|
|||||||
return prog, nil
|
return prog, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logErr := err
|
||||||
if opts.LogLevel == 0 {
|
if opts.LogLevel == 0 {
|
||||||
// Re-run with the verifier enabled to get better error messages.
|
// Re-run with the verifier enabled to get better error messages.
|
||||||
logBuf = make([]byte, logSize)
|
logBuf = make([]byte, logSize)
|
||||||
@ -137,11 +160,11 @@ func newProgramWithBTF(spec *ProgramSpec, btf *btf.Handle, opts ProgramOptions)
|
|||||||
attr.logSize = uint32(len(logBuf))
|
attr.logSize = uint32(len(logBuf))
|
||||||
attr.logBuf = internal.NewSlicePointer(logBuf)
|
attr.logBuf = internal.NewSlicePointer(logBuf)
|
||||||
|
|
||||||
_, logErr := bpfProgLoad(attr)
|
_, logErr = bpfProgLoad(attr)
|
||||||
err = internal.ErrorWithLog(err, logBuf, logErr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.Wrap(err, "can't load program")
|
err = internal.ErrorWithLog(err, logBuf, logErr)
|
||||||
|
return nil, fmt.Errorf("can't load program: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProgramFromFD creates a program from a raw fd.
|
// NewProgramFromFD creates a program from a raw fd.
|
||||||
@ -181,6 +204,10 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
|
|||||||
return nil, errors.New("License cannot be empty")
|
return nil, errors.New("License cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if spec.ByteOrder != nil && spec.ByteOrder != internal.NativeEndian {
|
||||||
|
return nil, fmt.Errorf("can't load %s program on %s", spec.ByteOrder, internal.NativeEndian)
|
||||||
|
}
|
||||||
|
|
||||||
buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize))
|
buf := bytes.NewBuffer(make([]byte, 0, len(spec.Instructions)*asm.InstructionSize))
|
||||||
err := spec.Instructions.Marshal(buf, internal.NativeEndian)
|
err := spec.Instructions.Marshal(buf, internal.NativeEndian)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -195,15 +222,11 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
|
|||||||
insCount: insCount,
|
insCount: insCount,
|
||||||
instructions: internal.NewSlicePointer(bytecode),
|
instructions: internal.NewSlicePointer(bytecode),
|
||||||
license: internal.NewStringPointer(spec.License),
|
license: internal.NewStringPointer(spec.License),
|
||||||
}
|
kernelVersion: spec.KernelVersion,
|
||||||
|
|
||||||
name, err := newBPFObjName(spec.Name)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if haveObjName() == nil {
|
if haveObjName() == nil {
|
||||||
attr.progName = name
|
attr.progName = newBPFObjName(spec.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if handle != nil && spec.BTF != nil {
|
if handle != nil && spec.BTF != nil {
|
||||||
@ -211,7 +234,7 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
|
|||||||
|
|
||||||
recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
|
recSize, bytes, err := btf.ProgramLineInfos(spec.BTF)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get BTF line infos")
|
return nil, fmt.Errorf("can't get BTF line infos: %w", err)
|
||||||
}
|
}
|
||||||
attr.lineInfoRecSize = recSize
|
attr.lineInfoRecSize = recSize
|
||||||
attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
attr.lineInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
@ -219,13 +242,23 @@ func convertProgramSpec(spec *ProgramSpec, handle *btf.Handle) (*bpfProgLoadAttr
|
|||||||
|
|
||||||
recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
|
recSize, bytes, err = btf.ProgramFuncInfos(spec.BTF)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't get BTF function infos")
|
return nil, fmt.Errorf("can't get BTF function infos: %w", err)
|
||||||
}
|
}
|
||||||
attr.funcInfoRecSize = recSize
|
attr.funcInfoRecSize = recSize
|
||||||
attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
attr.funcInfoCnt = uint32(uint64(len(bytes)) / uint64(recSize))
|
||||||
attr.funcInfo = internal.NewSlicePointer(bytes)
|
attr.funcInfo = internal.NewSlicePointer(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if spec.AttachTo != "" {
|
||||||
|
target, err := resolveBTFType(spec.AttachTo, spec.Type, spec.AttachType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if target != nil {
|
||||||
|
attr.attachBTFID = target.ID()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return attr, nil
|
return attr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +300,7 @@ func (p *Program) Clone() (*Program, error) {
|
|||||||
|
|
||||||
dup, err := p.fd.Dup()
|
dup, err := p.fd.Dup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "can't clone program")
|
return nil, fmt.Errorf("can't clone program: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProgram(dup, p.name, &p.abi), nil
|
return newProgram(dup, p.name, &p.abi), nil
|
||||||
@ -277,7 +310,10 @@ func (p *Program) Clone() (*Program, error) {
|
|||||||
//
|
//
|
||||||
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
|
// This requires bpffs to be mounted above fileName. See http://cilium.readthedocs.io/en/doc-1.0/kubernetes/install/#mounting-the-bpf-fs-optional
|
||||||
func (p *Program) Pin(fileName string) error {
|
func (p *Program) Pin(fileName string) error {
|
||||||
return errors.Wrap(bpfPinObject(fileName, p.fd), "can't pin program")
|
if err := internal.BPFObjPin(fileName, p.fd); err != nil {
|
||||||
|
return fmt.Errorf("can't pin program: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close unloads the program from the kernel.
|
// Close unloads the program from the kernel.
|
||||||
@ -297,23 +333,33 @@ func (p *Program) Close() error {
|
|||||||
//
|
//
|
||||||
// This function requires at least Linux 4.12.
|
// This function requires at least Linux 4.12.
|
||||||
func (p *Program) Test(in []byte) (uint32, []byte, error) {
|
func (p *Program) Test(in []byte) (uint32, []byte, error) {
|
||||||
ret, out, _, err := p.testRun(in, 1)
|
ret, out, _, err := p.testRun(in, 1, nil)
|
||||||
return ret, out, errors.Wrap(err, "can't test program")
|
if err != nil {
|
||||||
|
return ret, nil, fmt.Errorf("can't test program: %w", err)
|
||||||
|
}
|
||||||
|
return ret, out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Benchmark runs the Program with the given input for a number of times
|
// Benchmark runs the Program with the given input for a number of times
|
||||||
// and returns the time taken per iteration.
|
// and returns the time taken per iteration.
|
||||||
//
|
//
|
||||||
// The returned value is the return value of the last execution of
|
// Returns the result of the last execution of the program and the time per
|
||||||
// the program.
|
// run or an error. reset is called whenever the benchmark syscall is
|
||||||
|
// interrupted, and should be set to testing.B.ResetTimer or similar.
|
||||||
|
//
|
||||||
|
// Note: profiling a call to this function will skew it's results, see
|
||||||
|
// https://github.com/cilium/ebpf/issues/24
|
||||||
//
|
//
|
||||||
// This function requires at least Linux 4.12.
|
// This function requires at least Linux 4.12.
|
||||||
func (p *Program) Benchmark(in []byte, repeat int) (uint32, time.Duration, error) {
|
func (p *Program) Benchmark(in []byte, repeat int, reset func()) (uint32, time.Duration, error) {
|
||||||
ret, _, total, err := p.testRun(in, repeat)
|
ret, _, total, err := p.testRun(in, repeat, reset)
|
||||||
return ret, total, errors.Wrap(err, "can't benchmark program")
|
if err != nil {
|
||||||
|
return ret, total, fmt.Errorf("can't benchmark program: %w", err)
|
||||||
|
}
|
||||||
|
return ret, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() bool {
|
var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() (bool, error) {
|
||||||
prog, err := NewProgram(&ProgramSpec{
|
prog, err := NewProgram(&ProgramSpec{
|
||||||
Type: SocketFilter,
|
Type: SocketFilter,
|
||||||
Instructions: asm.Instructions{
|
Instructions: asm.Instructions{
|
||||||
@ -324,31 +370,26 @@ var haveProgTestRun = internal.FeatureTest("BPF_PROG_TEST_RUN", "4.12", func() b
|
|||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This may be because we lack sufficient permissions, etc.
|
// This may be because we lack sufficient permissions, etc.
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
defer prog.Close()
|
defer prog.Close()
|
||||||
|
|
||||||
fd, err := prog.fd.Value()
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Programs require at least 14 bytes input
|
// Programs require at least 14 bytes input
|
||||||
in := make([]byte, 14)
|
in := make([]byte, 14)
|
||||||
attr := bpfProgTestRunAttr{
|
attr := bpfProgTestRunAttr{
|
||||||
fd: fd,
|
fd: uint32(prog.FD()),
|
||||||
dataSizeIn: uint32(len(in)),
|
dataSizeIn: uint32(len(in)),
|
||||||
dataIn: internal.NewSlicePointer(in),
|
dataIn: internal.NewSlicePointer(in),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
err = bpfProgTestRun(&attr)
|
||||||
|
|
||||||
// Check for EINVAL specifically, rather than err != nil since we
|
// Check for EINVAL specifically, rather than err != nil since we
|
||||||
// otherwise misdetect due to insufficient permissions.
|
// otherwise misdetect due to insufficient permissions.
|
||||||
return errors.Cause(err) != unix.EINVAL
|
return !errors.Is(err, unix.EINVAL), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration, error) {
|
func (p *Program) testRun(in []byte, repeat int, reset func()) (uint32, []byte, time.Duration, error) {
|
||||||
if uint(repeat) > math.MaxUint32 {
|
if uint(repeat) > math.MaxUint32 {
|
||||||
return 0, nil, 0, fmt.Errorf("repeat is too high")
|
return 0, nil, 0, fmt.Errorf("repeat is too high")
|
||||||
}
|
}
|
||||||
@ -386,9 +427,20 @@ func (p *Program) testRun(in []byte, repeat int) (uint32, []byte, time.Duration,
|
|||||||
repeat: uint32(repeat),
|
repeat: uint32(repeat),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = internal.BPF(_ProgTestRun, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
for {
|
||||||
if err != nil {
|
err = bpfProgTestRun(&attr)
|
||||||
return 0, nil, 0, errors.Wrap(err, "can't run test")
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, unix.EINTR) {
|
||||||
|
if reset != nil {
|
||||||
|
reset()
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, nil, 0, fmt.Errorf("can't run test: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if int(attr.dataSizeOut) > cap(out) {
|
if int(attr.dataSizeOut) > cap(out) {
|
||||||
@ -410,18 +462,7 @@ func unmarshalProgram(buf []byte) (*Program, error) {
|
|||||||
// Looking up an entry in a nested map or prog array returns an id,
|
// Looking up an entry in a nested map or prog array returns an id,
|
||||||
// not an fd.
|
// not an fd.
|
||||||
id := internal.NativeEndian.Uint32(buf)
|
id := internal.NativeEndian.Uint32(buf)
|
||||||
fd, err := bpfGetProgramFDByID(id)
|
return NewProgramFromID(ProgramID(id))
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
name, abi, err := newProgramABIFromFd(fd)
|
|
||||||
if err != nil {
|
|
||||||
_ = fd.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return newProgram(fd, name, abi), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalBinary implements BinaryMarshaler.
|
// MarshalBinary implements BinaryMarshaler.
|
||||||
@ -436,7 +477,9 @@ func (p *Program) MarshalBinary() ([]byte, error) {
|
|||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach a Program to a container object fd
|
// Attach a Program.
|
||||||
|
//
|
||||||
|
// Deprecated: use link.RawAttachProgram instead.
|
||||||
func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
|
func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return errors.New("invalid fd")
|
return errors.New("invalid fd")
|
||||||
@ -447,42 +490,47 @@ func (p *Program) Attach(fd int, typ AttachType, flags AttachFlags) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := bpfProgAlterAttr{
|
attr := internal.BPFProgAttachAttr{
|
||||||
targetFd: uint32(fd),
|
TargetFd: uint32(fd),
|
||||||
attachBpfFd: pfd,
|
AttachBpfFd: pfd,
|
||||||
attachType: uint32(typ),
|
AttachType: uint32(typ),
|
||||||
attachFlags: uint32(flags),
|
AttachFlags: uint32(flags),
|
||||||
}
|
}
|
||||||
|
|
||||||
return bpfProgAlter(_ProgAttach, &attr)
|
return internal.BPFProgAttach(&attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detach a Program from a container object fd
|
// Detach a Program.
|
||||||
|
//
|
||||||
|
// Deprecated: use link.RawDetachProgram instead.
|
||||||
func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
|
func (p *Program) Detach(fd int, typ AttachType, flags AttachFlags) error {
|
||||||
if fd < 0 {
|
if fd < 0 {
|
||||||
return errors.New("invalid fd")
|
return errors.New("invalid fd")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if flags != 0 {
|
||||||
|
return errors.New("flags must be zero")
|
||||||
|
}
|
||||||
|
|
||||||
pfd, err := p.fd.Value()
|
pfd, err := p.fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := bpfProgAlterAttr{
|
attr := internal.BPFProgDetachAttr{
|
||||||
targetFd: uint32(fd),
|
TargetFd: uint32(fd),
|
||||||
attachBpfFd: pfd,
|
AttachBpfFd: pfd,
|
||||||
attachType: uint32(typ),
|
AttachType: uint32(typ),
|
||||||
attachFlags: uint32(flags),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return bpfProgAlter(_ProgDetach, &attr)
|
return internal.BPFProgDetach(&attr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPinnedProgram loads a Program from a BPF file.
|
// LoadPinnedProgram loads a Program from a BPF file.
|
||||||
//
|
//
|
||||||
// Requires at least Linux 4.11.
|
// Requires at least Linux 4.11.
|
||||||
func LoadPinnedProgram(fileName string) (*Program, error) {
|
func LoadPinnedProgram(fileName string) (*Program, error) {
|
||||||
fd, err := bpfGetObject(fileName)
|
fd, err := internal.BPFObjGet(fileName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -490,7 +538,7 @@ func LoadPinnedProgram(fileName string) (*Program, error) {
|
|||||||
name, abi, err := newProgramABIFromFd(fd)
|
name, abi, err := newProgramABIFromFd(fd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = fd.Close()
|
_ = fd.Close()
|
||||||
return nil, errors.Wrapf(err, "can't get ABI for %s", fileName)
|
return nil, fmt.Errorf("can't get ABI for %s: %w", fileName, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newProgram(fd, name, abi), nil
|
return newProgram(fd, name, abi), nil
|
||||||
@ -512,9 +560,63 @@ func SanitizeName(name string, replacement rune) string {
|
|||||||
}, name)
|
}, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsNotSupported returns true if an error occurred because
|
// ProgramGetNextID returns the ID of the next eBPF program.
|
||||||
// the kernel does not have support for a specific feature.
|
//
|
||||||
func IsNotSupported(err error) bool {
|
// Returns ErrNotExist, if there is no next eBPF program.
|
||||||
_, notSupported := errors.Cause(err).(*internal.UnsupportedFeatureError)
|
func ProgramGetNextID(startID ProgramID) (ProgramID, error) {
|
||||||
return notSupported
|
id, err := objGetNextID(internal.BPF_PROG_GET_NEXT_ID, uint32(startID))
|
||||||
|
return ProgramID(id), err
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewProgramFromID returns the program for a given id.
|
||||||
|
//
|
||||||
|
// Returns ErrNotExist, if there is no eBPF program with the given id.
|
||||||
|
func NewProgramFromID(id ProgramID) (*Program, error) {
|
||||||
|
fd, err := bpfObjGetFDByID(internal.BPF_PROG_GET_FD_BY_ID, uint32(id))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
name, abi, err := newProgramABIFromFd(fd)
|
||||||
|
if err != nil {
|
||||||
|
_ = fd.Close()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newProgram(fd, name, abi), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ID returns the systemwide unique ID of the program.
|
||||||
|
func (p *Program) ID() (ProgramID, error) {
|
||||||
|
info, err := bpfGetProgInfoByFD(p.fd)
|
||||||
|
if err != nil {
|
||||||
|
return ProgramID(0), err
|
||||||
|
}
|
||||||
|
return ProgramID(info.id), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveBTFType(name string, progType ProgramType, attachType AttachType) (btf.Type, error) {
|
||||||
|
kernel, err := btf.LoadKernelSpec()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't resolve BTF type %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type match struct {
|
||||||
|
p ProgramType
|
||||||
|
a AttachType
|
||||||
|
}
|
||||||
|
|
||||||
|
target := match{progType, attachType}
|
||||||
|
switch target {
|
||||||
|
case match{Tracing, AttachTraceIter}:
|
||||||
|
var target btf.Func
|
||||||
|
if err := kernel.FindType("bpf_iter_"+name, &target); err != nil {
|
||||||
|
return nil, fmt.Errorf("can't resolve BTF for iterator %s: %w", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &target, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
5
vendor/github.com/cilium/ebpf/readme.md
generated
vendored
5
vendor/github.com/cilium/ebpf/readme.md
generated
vendored
@ -13,6 +13,11 @@ The library is maintained by [Cloudflare](https://www.cloudflare.com) and [Ciliu
|
|||||||
The package is production ready, but **the API is explicitly unstable
|
The package is production ready, but **the API is explicitly unstable
|
||||||
right now**. Expect to update your code if you want to follow along.
|
right now**. Expect to update your code if you want to follow along.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
* A version of Go that is [supported by upstream](https://golang.org/doc/devel/release.html#policy)
|
||||||
|
* Linux 4.9, 4.19 or 5.4 (versions in-between should work, but are not tested)
|
||||||
|
|
||||||
## Useful resources
|
## Useful resources
|
||||||
|
|
||||||
* [Cilium eBPF documentation](https://cilium.readthedocs.io/en/latest/bpf/#bpf-guide) (recommended)
|
* [Cilium eBPF documentation](https://cilium.readthedocs.io/en/latest/bpf/#bpf-guide) (recommended)
|
||||||
|
256
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
256
vendor/github.com/cilium/ebpf/syscalls.go
generated
vendored
@ -1,15 +1,19 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"errors"
|
||||||
"strings"
|
"fmt"
|
||||||
|
"os"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/cilium/ebpf/internal"
|
"github.com/cilium/ebpf/internal"
|
||||||
"github.com/cilium/ebpf/internal/btf"
|
"github.com/cilium/ebpf/internal/btf"
|
||||||
"github.com/cilium/ebpf/internal/unix"
|
"github.com/cilium/ebpf/internal/unix"
|
||||||
|
)
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
// Generic errors returned by BPF syscalls.
|
||||||
|
var (
|
||||||
|
ErrNotExist = errors.New("requested object does not exist")
|
||||||
)
|
)
|
||||||
|
|
||||||
// bpfObjName is a null-terminated string made up of
|
// bpfObjName is a null-terminated string made up of
|
||||||
@ -17,18 +21,15 @@ import (
|
|||||||
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
|
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
|
||||||
|
|
||||||
// newBPFObjName truncates the result if it is too long.
|
// newBPFObjName truncates the result if it is too long.
|
||||||
func newBPFObjName(name string) (bpfObjName, error) {
|
func newBPFObjName(name string) bpfObjName {
|
||||||
idx := strings.IndexFunc(name, invalidBPFObjNameChar)
|
|
||||||
if idx != -1 {
|
|
||||||
return bpfObjName{}, errors.Errorf("invalid character '%c' in name '%s'", name[idx], name)
|
|
||||||
}
|
|
||||||
|
|
||||||
var result bpfObjName
|
var result bpfObjName
|
||||||
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
|
copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
|
||||||
return result, nil
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func invalidBPFObjNameChar(char rune) bool {
|
func invalidBPFObjNameChar(char rune) bool {
|
||||||
|
dotAllowed := objNameAllowsDot() == nil
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case char >= 'A' && char <= 'Z':
|
case char >= 'A' && char <= 'Z':
|
||||||
fallthrough
|
fallthrough
|
||||||
@ -36,6 +37,8 @@ func invalidBPFObjNameChar(char rune) bool {
|
|||||||
fallthrough
|
fallthrough
|
||||||
case char >= '0' && char <= '9':
|
case char >= '0' && char <= '9':
|
||||||
fallthrough
|
fallthrough
|
||||||
|
case dotAllowed && char == '.':
|
||||||
|
fallthrough
|
||||||
case char == '_':
|
case char == '_':
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
@ -76,12 +79,6 @@ type bpfMapInfo struct {
|
|||||||
mapName bpfObjName // since 4.15 ad5b177bd73f
|
mapName bpfObjName // since 4.15 ad5b177bd73f
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfPinObjAttr struct {
|
|
||||||
fileName internal.Pointer
|
|
||||||
fd uint32
|
|
||||||
padding uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type bpfProgLoadAttr struct {
|
type bpfProgLoadAttr struct {
|
||||||
progType ProgramType
|
progType ProgramType
|
||||||
insCount uint32
|
insCount uint32
|
||||||
@ -102,6 +99,8 @@ type bpfProgLoadAttr struct {
|
|||||||
lineInfoRecSize uint32
|
lineInfoRecSize uint32
|
||||||
lineInfo internal.Pointer
|
lineInfo internal.Pointer
|
||||||
lineInfoCnt uint32
|
lineInfoCnt uint32
|
||||||
|
attachBTFID btf.TypeID
|
||||||
|
attachProgFd uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfProgInfo struct {
|
type bpfProgInfo struct {
|
||||||
@ -130,13 +129,6 @@ type bpfProgTestRunAttr struct {
|
|||||||
duration uint32
|
duration uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
type bpfProgAlterAttr struct {
|
|
||||||
targetFd uint32
|
|
||||||
attachBpfFd uint32
|
|
||||||
attachType uint32
|
|
||||||
attachFlags uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
type bpfObjGetInfoByFDAttr struct {
|
type bpfObjGetInfoByFDAttr struct {
|
||||||
fd uint32
|
fd uint32
|
||||||
infoLen uint32
|
infoLen uint32
|
||||||
@ -148,9 +140,19 @@ type bpfGetFDByIDAttr struct {
|
|||||||
next uint32
|
next uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type bpfMapFreezeAttr struct {
|
||||||
|
mapFd uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type bpfObjGetNextIDAttr struct {
|
||||||
|
startID uint32
|
||||||
|
nextID uint32
|
||||||
|
openFlags uint32
|
||||||
|
}
|
||||||
|
|
||||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
||||||
for {
|
for {
|
||||||
fd, err := internal.BPF(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
fd, err := internal.BPF(internal.BPF_PROG_LOAD, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
// As of ~4.20 the verifier can be interrupted by a signal,
|
// As of ~4.20 the verifier can be interrupted by a signal,
|
||||||
// and returns EAGAIN in that case.
|
// and returns EAGAIN in that case.
|
||||||
if err == unix.EAGAIN {
|
if err == unix.EAGAIN {
|
||||||
@ -165,13 +167,17 @@ func bpfProgLoad(attr *bpfProgLoadAttr) (*internal.FD, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error {
|
func bpfProgTestRun(attr *bpfProgTestRunAttr) error {
|
||||||
_, err := internal.BPF(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
_, err := internal.BPF(internal.BPF_PROG_TEST_RUN, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
|
func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
|
||||||
fd, err := internal.BPF(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
fd, err := internal.BPF(internal.BPF_MAP_CREATE, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
|
||||||
|
if errors.Is(err, os.ErrPermission) {
|
||||||
|
return nil, errors.New("permission denied or insufficient rlimit to lock memory for map")
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -179,7 +185,7 @@ func bpfMapCreate(attr *bpfMapCreateAttr) (*internal.FD, error) {
|
|||||||
return internal.NewFD(uint32(fd)), nil
|
return internal.NewFD(uint32(fd)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() (bool, error) {
|
||||||
inner, err := bpfMapCreate(&bpfMapCreateAttr{
|
inner, err := bpfMapCreate(&bpfMapCreateAttr{
|
||||||
mapType: Array,
|
mapType: Array,
|
||||||
keySize: 4,
|
keySize: 4,
|
||||||
@ -187,7 +193,7 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
|||||||
maxEntries: 1,
|
maxEntries: 1,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, err
|
||||||
}
|
}
|
||||||
defer inner.Close()
|
defer inner.Close()
|
||||||
|
|
||||||
@ -200,11 +206,28 @@ var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
|
|||||||
innerMapFd: innerFd,
|
innerMapFd: innerFd,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = nested.Close()
|
_ = nested.Close()
|
||||||
return true
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
var haveMapMutabilityModifiers = internal.FeatureTest("read- and write-only maps", "5.2", func() (bool, error) {
|
||||||
|
// This checks BPF_F_RDONLY_PROG and BPF_F_WRONLY_PROG. Since
|
||||||
|
// BPF_MAP_FREEZE appeared in 5.2 as well we don't do a separate check.
|
||||||
|
m, err := bpfMapCreate(&bpfMapCreateAttr{
|
||||||
|
mapType: Array,
|
||||||
|
keySize: 4,
|
||||||
|
valueSize: 4,
|
||||||
|
maxEntries: 1,
|
||||||
|
flags: unix.BPF_F_RDONLY_PROG,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
_ = m.Close()
|
||||||
|
return true, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
|
func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
|
||||||
@ -218,8 +241,8 @@ func bpfMapLookupElem(m *internal.FD, key, valueOut internal.Pointer) error {
|
|||||||
key: key,
|
key: key,
|
||||||
value: valueOut,
|
value: valueOut,
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_MAP_LOOKUP_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return wrapMapError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error {
|
func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error {
|
||||||
@ -233,8 +256,8 @@ func bpfMapLookupAndDelete(m *internal.FD, key, valueOut internal.Pointer) error
|
|||||||
key: key,
|
key: key,
|
||||||
value: valueOut,
|
value: valueOut,
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_MapLookupAndDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_MAP_LOOKUP_AND_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return wrapMapError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint64) error {
|
func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint64) error {
|
||||||
@ -249,8 +272,8 @@ func bpfMapUpdateElem(m *internal.FD, key, valueOut internal.Pointer, flags uint
|
|||||||
value: valueOut,
|
value: valueOut,
|
||||||
flags: flags,
|
flags: flags,
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_MAP_UPDATE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return wrapMapError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
|
func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
|
||||||
@ -263,8 +286,8 @@ func bpfMapDeleteElem(m *internal.FD, key internal.Pointer) error {
|
|||||||
mapFd: fd,
|
mapFd: fd,
|
||||||
key: key,
|
key: key,
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_MAP_DELETE_ELEM, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return wrapMapError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
|
func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
|
||||||
@ -278,44 +301,58 @@ func bpfMapGetNextKey(m *internal.FD, key, nextKeyOut internal.Pointer) error {
|
|||||||
key: key,
|
key: key,
|
||||||
value: nextKeyOut,
|
value: nextKeyOut,
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_MAP_GET_NEXT_KEY, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
return wrapMapError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func objGetNextID(cmd internal.BPFCmd, start uint32) (uint32, error) {
|
||||||
|
attr := bpfObjGetNextIDAttr{
|
||||||
|
startID: start,
|
||||||
|
}
|
||||||
|
_, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
|
return attr.nextID, wrapObjError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapObjError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if errors.Is(err, unix.ENOENT) {
|
||||||
|
return fmt.Errorf("%w", ErrNotExist)
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func wrapMapError(err error) error {
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, unix.ENOENT) {
|
||||||
|
return ErrKeyNotExist
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.Is(err, unix.EEXIST) {
|
||||||
|
return ErrKeyExist
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.New(err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func bpfMapFreeze(m *internal.FD) error {
|
||||||
|
fd, err := m.Value()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
attr := bpfMapFreezeAttr{
|
||||||
|
mapFd: fd,
|
||||||
|
}
|
||||||
|
_, err = internal.BPF(internal.BPF_MAP_FREEZE, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
const bpfFSType = 0xcafe4a11
|
|
||||||
|
|
||||||
func bpfPinObject(fileName string, fd *internal.FD) error {
|
|
||||||
dirName := filepath.Dir(fileName)
|
|
||||||
var statfs unix.Statfs_t
|
|
||||||
if err := unix.Statfs(dirName, &statfs); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if uint64(statfs.Type) != bpfFSType {
|
|
||||||
return errors.Errorf("%s is not on a bpf filesystem", fileName)
|
|
||||||
}
|
|
||||||
|
|
||||||
value, err := fd.Value()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = internal.BPF(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
|
|
||||||
fileName: internal.NewStringPointer(fileName),
|
|
||||||
fd: value,
|
|
||||||
}), 16)
|
|
||||||
return errors.Wrapf(err, "pin object %s", fileName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func bpfGetObject(fileName string) (*internal.FD, error) {
|
|
||||||
ptr, err := internal.BPF(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
|
|
||||||
fileName: internal.NewStringPointer(fileName),
|
|
||||||
}), 16)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "get object %s", fileName)
|
|
||||||
}
|
|
||||||
return internal.NewFD(uint32(ptr)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error {
|
func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) error {
|
||||||
value, err := fd.Value()
|
value, err := fd.Value()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -328,28 +365,51 @@ func bpfGetObjectInfoByFD(fd *internal.FD, info unsafe.Pointer, size uintptr) er
|
|||||||
infoLen: uint32(size),
|
infoLen: uint32(size),
|
||||||
info: internal.NewPointer(info),
|
info: internal.NewPointer(info),
|
||||||
}
|
}
|
||||||
_, err = internal.BPF(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
_, err = internal.BPF(internal.BPF_OBJ_GET_INFO_BY_FD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
return errors.Wrapf(err, "fd %d", fd)
|
if err != nil {
|
||||||
|
return fmt.Errorf("fd %d: %w", fd, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
|
func bpfGetProgInfoByFD(fd *internal.FD) (*bpfProgInfo, error) {
|
||||||
var info bpfProgInfo
|
var info bpfProgInfo
|
||||||
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
if err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info)); err != nil {
|
||||||
return &info, errors.Wrap(err, "can't get program info")
|
return nil, fmt.Errorf("can't get program info: %w", err)
|
||||||
|
}
|
||||||
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
|
func bpfGetMapInfoByFD(fd *internal.FD) (*bpfMapInfo, error) {
|
||||||
var info bpfMapInfo
|
var info bpfMapInfo
|
||||||
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
|
||||||
return &info, errors.Wrap(err, "can't get map info")
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("can't get map info: %w", err)
|
||||||
|
}
|
||||||
|
return &info, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
|
var haveObjName = internal.FeatureTest("object names", "4.15", func() (bool, error) {
|
||||||
name, err := newBPFObjName("feature_test")
|
attr := bpfMapCreateAttr{
|
||||||
|
mapType: Array,
|
||||||
|
keySize: 4,
|
||||||
|
valueSize: 4,
|
||||||
|
maxEntries: 1,
|
||||||
|
mapName: newBPFObjName("feature_test"),
|
||||||
|
}
|
||||||
|
|
||||||
|
fd, err := bpfMapCreate(&attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// This really is a fatal error, but it should be caught
|
return false, nil
|
||||||
// by the unit tests not working.
|
}
|
||||||
return false
|
|
||||||
|
_ = fd.Close()
|
||||||
|
return true, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
var objNameAllowsDot = internal.FeatureTest("dot in object names", "5.2", func() (bool, error) {
|
||||||
|
if err := haveObjName(); err != nil {
|
||||||
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
attr := bpfMapCreateAttr{
|
attr := bpfMapCreateAttr{
|
||||||
@ -357,38 +417,22 @@ var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
|
|||||||
keySize: 4,
|
keySize: 4,
|
||||||
valueSize: 4,
|
valueSize: 4,
|
||||||
maxEntries: 1,
|
maxEntries: 1,
|
||||||
mapName: name,
|
mapName: newBPFObjName(".test"),
|
||||||
}
|
}
|
||||||
|
|
||||||
fd, err := bpfMapCreate(&attr)
|
fd, err := bpfMapCreate(&attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = fd.Close()
|
_ = fd.Close()
|
||||||
return true
|
return true, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
func bpfGetMapFDByID(id uint32) (*internal.FD, error) {
|
func bpfObjGetFDByID(cmd internal.BPFCmd, id uint32) (*internal.FD, error) {
|
||||||
// available from 4.13
|
|
||||||
attr := bpfGetFDByIDAttr{
|
attr := bpfGetFDByIDAttr{
|
||||||
id: id,
|
id: id,
|
||||||
}
|
}
|
||||||
ptr, err := internal.BPF(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
ptr, err := internal.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
||||||
if err != nil {
|
return internal.NewFD(uint32(ptr)), wrapObjError(err)
|
||||||
return nil, errors.Wrapf(err, "can't get fd for map id %d", id)
|
|
||||||
}
|
|
||||||
return internal.NewFD(uint32(ptr)), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bpfGetProgramFDByID(id uint32) (*internal.FD, error) {
|
|
||||||
// available from 4.13
|
|
||||||
attr := bpfGetFDByIDAttr{
|
|
||||||
id: id,
|
|
||||||
}
|
|
||||||
ptr, err := internal.BPF(_ProgGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "can't get fd for program id %d", id)
|
|
||||||
}
|
|
||||||
return internal.NewFD(uint32(ptr)), nil
|
|
||||||
}
|
}
|
||||||
|
39
vendor/github.com/cilium/ebpf/types.go
generated
vendored
39
vendor/github.com/cilium/ebpf/types.go
generated
vendored
@ -1,6 +1,6 @@
|
|||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
//go:generate stringer -output types_string.go -type=MapType,ProgramType
|
//go:generate stringer -output types_string.go -type=MapType,ProgramType,AttachType
|
||||||
|
|
||||||
// MapType indicates the type map structure
|
// MapType indicates the type map structure
|
||||||
// that will be initialized in the kernel.
|
// that will be initialized in the kernel.
|
||||||
@ -85,44 +85,12 @@ const (
|
|||||||
|
|
||||||
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
// hasPerCPUValue returns true if the Map stores a value per CPU.
|
||||||
func (mt MapType) hasPerCPUValue() bool {
|
func (mt MapType) hasPerCPUValue() bool {
|
||||||
if mt == PerCPUHash || mt == PerCPUArray {
|
if mt == PerCPUHash || mt == PerCPUArray || mt == LRUCPUHash {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
_MapCreate = iota
|
|
||||||
_MapLookupElem
|
|
||||||
_MapUpdateElem
|
|
||||||
_MapDeleteElem
|
|
||||||
_MapGetNextKey
|
|
||||||
_ProgLoad
|
|
||||||
_ObjPin
|
|
||||||
_ObjGet
|
|
||||||
_ProgAttach
|
|
||||||
_ProgDetach
|
|
||||||
_ProgTestRun
|
|
||||||
_ProgGetNextID
|
|
||||||
_MapGetNextID
|
|
||||||
_ProgGetFDByID
|
|
||||||
_MapGetFDByID
|
|
||||||
_ObjGetInfoByFD
|
|
||||||
_ProgQuery
|
|
||||||
_RawTracepointOpen
|
|
||||||
_BTFLoad
|
|
||||||
_BTFGetFDByID
|
|
||||||
_TaskFDQuery
|
|
||||||
_MapLookupAndDeleteElem
|
|
||||||
_MapFreeze
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
_Any = iota
|
|
||||||
_NoExist
|
|
||||||
_Exist
|
|
||||||
)
|
|
||||||
|
|
||||||
// ProgramType of the eBPF program
|
// ProgramType of the eBPF program
|
||||||
type ProgramType uint32
|
type ProgramType uint32
|
||||||
|
|
||||||
@ -219,6 +187,9 @@ const (
|
|||||||
AttachTraceRawTp
|
AttachTraceRawTp
|
||||||
AttachTraceFEntry
|
AttachTraceFEntry
|
||||||
AttachTraceFExit
|
AttachTraceFExit
|
||||||
|
AttachModifyReturn
|
||||||
|
AttachLSMMac
|
||||||
|
AttachTraceIter
|
||||||
)
|
)
|
||||||
|
|
||||||
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
// AttachFlags of the eBPF program used in BPF_PROG_ATTACH command
|
||||||
|
48
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
48
vendor/github.com/cilium/ebpf/types_string.go
generated
vendored
@ -1,4 +1,4 @@
|
|||||||
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType"; DO NOT EDIT.
|
// Code generated by "stringer -output types_string.go -type=MapType,ProgramType,AttachType"; DO NOT EDIT.
|
||||||
|
|
||||||
package ebpf
|
package ebpf
|
||||||
|
|
||||||
@ -89,3 +89,49 @@ func (i ProgramType) String() string {
|
|||||||
}
|
}
|
||||||
return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
|
return _ProgramType_name[_ProgramType_index[i]:_ProgramType_index[i+1]]
|
||||||
}
|
}
|
||||||
|
func _() {
|
||||||
|
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||||
|
// Re-run the stringer command to generate them again.
|
||||||
|
var x [1]struct{}
|
||||||
|
_ = x[AttachNone-0]
|
||||||
|
_ = x[AttachCGroupInetIngress-0]
|
||||||
|
_ = x[AttachCGroupInetEgress-1]
|
||||||
|
_ = x[AttachCGroupInetSockCreate-2]
|
||||||
|
_ = x[AttachCGroupSockOps-3]
|
||||||
|
_ = x[AttachSkSKBStreamParser-4]
|
||||||
|
_ = x[AttachSkSKBStreamVerdict-5]
|
||||||
|
_ = x[AttachCGroupDevice-6]
|
||||||
|
_ = x[AttachSkMsgVerdict-7]
|
||||||
|
_ = x[AttachCGroupInet4Bind-8]
|
||||||
|
_ = x[AttachCGroupInet6Bind-9]
|
||||||
|
_ = x[AttachCGroupInet4Connect-10]
|
||||||
|
_ = x[AttachCGroupInet6Connect-11]
|
||||||
|
_ = x[AttachCGroupInet4PostBind-12]
|
||||||
|
_ = x[AttachCGroupInet6PostBind-13]
|
||||||
|
_ = x[AttachCGroupUDP4Sendmsg-14]
|
||||||
|
_ = x[AttachCGroupUDP6Sendmsg-15]
|
||||||
|
_ = x[AttachLircMode2-16]
|
||||||
|
_ = x[AttachFlowDissector-17]
|
||||||
|
_ = x[AttachCGroupSysctl-18]
|
||||||
|
_ = x[AttachCGroupUDP4Recvmsg-19]
|
||||||
|
_ = x[AttachCGroupUDP6Recvmsg-20]
|
||||||
|
_ = x[AttachCGroupGetsockopt-21]
|
||||||
|
_ = x[AttachCGroupSetsockopt-22]
|
||||||
|
_ = x[AttachTraceRawTp-23]
|
||||||
|
_ = x[AttachTraceFEntry-24]
|
||||||
|
_ = x[AttachTraceFExit-25]
|
||||||
|
_ = x[AttachModifyReturn-26]
|
||||||
|
_ = x[AttachLSMMac-27]
|
||||||
|
_ = x[AttachTraceIter-28]
|
||||||
|
}
|
||||||
|
|
||||||
|
const _AttachType_name = "AttachNoneAttachCGroupInetEgressAttachCGroupInetSockCreateAttachCGroupSockOpsAttachSkSKBStreamParserAttachSkSKBStreamVerdictAttachCGroupDeviceAttachSkMsgVerdictAttachCGroupInet4BindAttachCGroupInet6BindAttachCGroupInet4ConnectAttachCGroupInet6ConnectAttachCGroupInet4PostBindAttachCGroupInet6PostBindAttachCGroupUDP4SendmsgAttachCGroupUDP6SendmsgAttachLircMode2AttachFlowDissectorAttachCGroupSysctlAttachCGroupUDP4RecvmsgAttachCGroupUDP6RecvmsgAttachCGroupGetsockoptAttachCGroupSetsockoptAttachTraceRawTpAttachTraceFEntryAttachTraceFExitAttachModifyReturnAttachLSMMacAttachTraceIter"
|
||||||
|
|
||||||
|
var _AttachType_index = [...]uint16{0, 10, 32, 58, 77, 100, 124, 142, 160, 181, 202, 226, 250, 275, 300, 323, 346, 361, 380, 398, 421, 444, 466, 488, 504, 521, 537, 555, 567, 582}
|
||||||
|
|
||||||
|
func (i AttachType) String() string {
|
||||||
|
if i >= AttachType(len(_AttachType_index)-1) {
|
||||||
|
return "AttachType(" + strconv.FormatInt(int64(i), 10) + ")"
|
||||||
|
}
|
||||||
|
return _AttachType_name[_AttachType_index[i]:_AttachType_index[i+1]]
|
||||||
|
}
|
||||||
|
2
vendor/github.com/containerd/cri/README.md
generated
vendored
2
vendor/github.com/containerd/cri/README.md
generated
vendored
@ -78,7 +78,7 @@ specifications as appropriate.
|
|||||||
backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
|
backport version of `libseccomp-dev` is required. See [travis.yml](.travis.yml) for an example on trusty.
|
||||||
* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
|
* **btrfs development library.** Required by containerd btrfs support. `btrfs-tools`(Ubuntu, Debian) / `btrfs-progs-devel`(Fedora, CentOS, RHEL)
|
||||||
2. Install **`pkg-config`** (required for linking with `libseccomp`).
|
2. Install **`pkg-config`** (required for linking with `libseccomp`).
|
||||||
3. Install and setup a Go 1.13.11 development environment.
|
3. Install and setup a Go 1.13.12 development environment.
|
||||||
4. Make a local clone of this repository.
|
4. Make a local clone of this repository.
|
||||||
5. Install binary dependencies by running the following command from your cloned `cri/` project directory:
|
5. Install binary dependencies by running the following command from your cloned `cri/` project directory:
|
||||||
```bash
|
```bash
|
||||||
|
2
vendor/github.com/containerd/cri/cri.go
generated
vendored
2
vendor/github.com/containerd/cri/cri.go
generated
vendored
@ -37,7 +37,7 @@ import (
|
|||||||
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
imagespec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
criconfig "github.com/containerd/cri/pkg/config"
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
"github.com/containerd/cri/pkg/constants"
|
"github.com/containerd/cri/pkg/constants"
|
||||||
|
4
vendor/github.com/containerd/cri/pkg/config/config.go
generated
vendored
4
vendor/github.com/containerd/cri/pkg/config/config.go
generated
vendored
@ -232,10 +232,10 @@ type PluginConfig struct {
|
|||||||
// UnsetSeccompProfile is the profile containerd/cri will use If the provided seccomp profile is
|
// UnsetSeccompProfile is the profile containerd/cri will use If the provided seccomp profile is
|
||||||
// unset (`""`) for a container (default is `unconfined`)
|
// unset (`""`) for a container (default is `unconfined`)
|
||||||
UnsetSeccompProfile string `toml:"unset_seccomp_profile" json:"unsetSeccompProfile"`
|
UnsetSeccompProfile string `toml:"unset_seccomp_profile" json:"unsetSeccompProfile"`
|
||||||
// TolerateMissingHugePagesCgroupController if set to false will error out on create/update
|
// TolerateMissingHugetlbController if set to false will error out on create/update
|
||||||
// container requests with huge page limits if the cgroup controller for hugepages is not present.
|
// container requests with huge page limits if the cgroup controller for hugepages is not present.
|
||||||
// This helps with supporting Kubernetes <=1.18 out of the box. (default is `true`)
|
// This helps with supporting Kubernetes <=1.18 out of the box. (default is `true`)
|
||||||
TolerateMissingHugePagesCgroupController bool `toml:"tolerate_missing_hugepages_controller" json:"tolerateMissingHugePagesCgroupController"`
|
TolerateMissingHugetlbController bool `toml:"tolerate_missing_hugetlb_controller" json:"tolerateMissingHugetlbController"`
|
||||||
// IgnoreImageDefinedVolumes ignores volumes defined by the image. Useful for better resource
|
// IgnoreImageDefinedVolumes ignores volumes defined by the image. Useful for better resource
|
||||||
// isolation, security and early detection of issues in the mount configuration when using
|
// isolation, security and early detection of issues in the mount configuration when using
|
||||||
// ReadOnlyRootFilesystem since containers won't silently mount a temporary volume.
|
// ReadOnlyRootFilesystem since containers won't silently mount a temporary volume.
|
||||||
|
10
vendor/github.com/containerd/cri/pkg/config/config_unix.go
generated
vendored
10
vendor/github.com/containerd/cri/pkg/config/config_unix.go
generated
vendored
@ -20,7 +20,7 @@ package config
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
"github.com/containerd/cri/pkg/streaming"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConfig returns default configurations of cri plugin.
|
// DefaultConfig returns default configurations of cri plugin.
|
||||||
@ -63,9 +63,9 @@ func DefaultConfig() PluginConfig {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MaxConcurrentDownloads: 3,
|
MaxConcurrentDownloads: 3,
|
||||||
DisableProcMount: false,
|
DisableProcMount: false,
|
||||||
TolerateMissingHugePagesCgroupController: true,
|
TolerateMissingHugetlbController: true,
|
||||||
IgnoreImageDefinedVolumes: false,
|
IgnoreImageDefinedVolumes: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/config/config_windows.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/config/config_windows.go
generated
vendored
@ -23,7 +23,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
"github.com/containerd/cri/pkg/streaming"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultConfig returns default configurations of cri plugin.
|
// DefaultConfig returns default configurations of cri plugin.
|
||||||
|
12
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go
generated
vendored
12
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_unix.go
generated
vendored
@ -324,7 +324,7 @@ func WithDevices(osi osinterface.OS, config *runtime.ContainerConfig) oci.SpecOp
|
|||||||
Type: string(dev.Type),
|
Type: string(dev.Type),
|
||||||
Major: &dev.Major,
|
Major: &dev.Major,
|
||||||
Minor: &dev.Minor,
|
Minor: &dev.Minor,
|
||||||
Access: dev.Permissions,
|
Access: string(dev.Permissions),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -408,7 +408,7 @@ func WithSelinuxLabels(process, mount string) oci.SpecOpts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WithResources sets the provided resource restrictions
|
// WithResources sets the provided resource restrictions
|
||||||
func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHugePagesCgroupController bool) oci.SpecOpts {
|
func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHugetlbController bool) oci.SpecOpts {
|
||||||
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
return func(ctx context.Context, client oci.Client, c *containers.Container, s *runtimespec.Spec) (err error) {
|
||||||
if resources == nil {
|
if resources == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -451,7 +451,7 @@ func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHu
|
|||||||
if limit != 0 {
|
if limit != 0 {
|
||||||
s.Linux.Resources.Memory.Limit = &limit
|
s.Linux.Resources.Memory.Limit = &limit
|
||||||
}
|
}
|
||||||
if isHugePagesControllerPresent() {
|
if isHugetlbControllerPresent() {
|
||||||
for _, limit := range hugepages {
|
for _, limit := range hugepages {
|
||||||
s.Linux.Resources.HugepageLimits = append(s.Linux.Resources.HugepageLimits, runtimespec.LinuxHugepageLimit{
|
s.Linux.Resources.HugepageLimits = append(s.Linux.Resources.HugepageLimits, runtimespec.LinuxHugepageLimit{
|
||||||
Pagesize: limit.PageSize,
|
Pagesize: limit.PageSize,
|
||||||
@ -459,9 +459,9 @@ func WithResources(resources *runtime.LinuxContainerResources, tolerateMissingHu
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !tolerateMissingHugePagesCgroupController {
|
if !tolerateMissingHugetlbController {
|
||||||
return errors.Errorf("huge pages limits are specified but hugetlb cgroup controller is missing. " +
|
return errors.Errorf("huge pages limits are specified but hugetlb cgroup controller is missing. " +
|
||||||
"Please set tolerate_missing_hugepages_controller to `true` to ignore this error")
|
"Please set tolerate_missing_hugetlb_controller to `true` to ignore this error")
|
||||||
}
|
}
|
||||||
logrus.Warn("hugetlb cgroup controller is absent. skipping huge pages limits")
|
logrus.Warn("hugetlb cgroup controller is absent. skipping huge pages limits")
|
||||||
}
|
}
|
||||||
@ -474,7 +474,7 @@ var (
|
|||||||
supportsHugetlb bool
|
supportsHugetlb bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func isHugePagesControllerPresent() bool {
|
func isHugetlbControllerPresent() bool {
|
||||||
supportsHugetlbOnce.Do(func() {
|
supportsHugetlbOnce.Do(func() {
|
||||||
supportsHugetlb = false
|
supportsHugetlb = false
|
||||||
if IsCgroup2UnifiedMode() {
|
if IsCgroup2UnifiedMode() {
|
||||||
|
56
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go
generated
vendored
56
vendor/github.com/containerd/cri/pkg/containerd/opts/spec_windows.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
"github.com/containerd/containerd/containers"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
@ -47,6 +48,20 @@ func WithWindowsNetworkNamespace(path string) oci.SpecOpts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// namedPipePath returns true if the given path is to a named pipe.
|
||||||
|
func namedPipePath(p string) bool {
|
||||||
|
return strings.HasPrefix(p, `\\.\pipe\`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cleanMount returns a cleaned version of the mount path. The input is returned
|
||||||
|
// as-is if it is a named pipe path.
|
||||||
|
func cleanMount(p string) string {
|
||||||
|
if namedPipePath(p) {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return filepath.Clean(p)
|
||||||
|
}
|
||||||
|
|
||||||
// WithWindowsMounts sorts and adds runtime and CRI mounts to the spec for
|
// WithWindowsMounts sorts and adds runtime and CRI mounts to the spec for
|
||||||
// windows container.
|
// windows container.
|
||||||
func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount) oci.SpecOpts {
|
func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extra []*runtime.Mount) oci.SpecOpts {
|
||||||
@ -62,7 +77,7 @@ func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extr
|
|||||||
for _, e := range extra {
|
for _, e := range extra {
|
||||||
found := false
|
found := false
|
||||||
for _, c := range criMounts {
|
for _, c := range criMounts {
|
||||||
if filepath.Clean(e.ContainerPath) == filepath.Clean(c.ContainerPath) {
|
if cleanMount(e.ContainerPath) == cleanMount(c.ContainerPath) {
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -80,14 +95,14 @@ func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extr
|
|||||||
// mounts overridden by supplied mount;
|
// mounts overridden by supplied mount;
|
||||||
mountSet := make(map[string]struct{})
|
mountSet := make(map[string]struct{})
|
||||||
for _, m := range mounts {
|
for _, m := range mounts {
|
||||||
mountSet[filepath.Clean(m.ContainerPath)] = struct{}{}
|
mountSet[cleanMount(m.ContainerPath)] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultMounts := s.Mounts
|
defaultMounts := s.Mounts
|
||||||
s.Mounts = nil
|
s.Mounts = nil
|
||||||
|
|
||||||
for _, m := range defaultMounts {
|
for _, m := range defaultMounts {
|
||||||
dst := filepath.Clean(m.Destination)
|
dst := cleanMount(m.Destination)
|
||||||
if _, ok := mountSet[dst]; ok {
|
if _, ok := mountSet[dst]; ok {
|
||||||
// filter out mount overridden by a supplied mount
|
// filter out mount overridden by a supplied mount
|
||||||
continue
|
continue
|
||||||
@ -100,17 +115,25 @@ func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extr
|
|||||||
dst = mount.GetContainerPath()
|
dst = mount.GetContainerPath()
|
||||||
src = mount.GetHostPath()
|
src = mount.GetHostPath()
|
||||||
)
|
)
|
||||||
// TODO(windows): Support special mount sources, e.g. named pipe.
|
// In the case of a named pipe mount on Windows, don't stat the file
|
||||||
// Create the host path if it doesn't exist.
|
// or do other operations that open it, as that could interfere with
|
||||||
if _, err := osi.Stat(src); err != nil {
|
// the listening process. filepath.Clean also breaks named pipe
|
||||||
// If the source doesn't exist, return an error instead
|
// paths, so don't use it.
|
||||||
// of creating the source. This aligns with Docker's
|
if !namedPipePath(src) {
|
||||||
// behavior on windows.
|
if _, err := osi.Stat(src); err != nil {
|
||||||
return errors.Wrapf(err, "failed to stat %q", src)
|
// If the source doesn't exist, return an error instead
|
||||||
}
|
// of creating the source. This aligns with Docker's
|
||||||
src, err := osi.ResolveSymbolicLink(src)
|
// behavior on windows.
|
||||||
if err != nil {
|
return errors.Wrapf(err, "failed to stat %q", src)
|
||||||
return errors.Wrapf(err, "failed to resolve symlink %q", src)
|
}
|
||||||
|
var err error
|
||||||
|
src, err = osi.ResolveSymbolicLink(src)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "failed to resolve symlink %q", src)
|
||||||
|
}
|
||||||
|
// hcsshim requires clean path, especially '/' -> '\'.
|
||||||
|
src = filepath.Clean(src)
|
||||||
|
dst = filepath.Clean(dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
var options []string
|
var options []string
|
||||||
@ -122,9 +145,8 @@ func WithWindowsMounts(osi osinterface.OS, config *runtime.ContainerConfig, extr
|
|||||||
options = append(options, "rw")
|
options = append(options, "rw")
|
||||||
}
|
}
|
||||||
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
s.Mounts = append(s.Mounts, runtimespec.Mount{
|
||||||
// hcsshim requires clean path, especially '/' -> '\'.
|
Source: src,
|
||||||
Source: filepath.Clean(src),
|
Destination: dst,
|
||||||
Destination: filepath.Clean(dst),
|
|
||||||
Options: options,
|
Options: options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -15,4 +31,4 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Package bandwidth provides utilities for bandwidth shaping
|
// Package bandwidth provides utilities for bandwidth shaping
|
||||||
package bandwidth // import "k8s.io/kubernetes/pkg/util/bandwidth"
|
package bandwidth
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
@ -1,5 +1,21 @@
|
|||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -31,7 +47,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/utils/exec"
|
"k8s.io/utils/exec"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
@ -1,5 +1,21 @@
|
|||||||
// +build !linux
|
// +build !linux
|
||||||
|
|
||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
2
vendor/github.com/containerd/cri/pkg/server/container_create_unix.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/container_create_unix.go
generated
vendored
@ -225,7 +225,7 @@ func (c *criService) containerSpec(id string, sandboxID string, sandboxPid uint3
|
|||||||
if c.config.DisableCgroup {
|
if c.config.DisableCgroup {
|
||||||
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
specOpts = append(specOpts, customopts.WithDisabledCgroups)
|
||||||
} else {
|
} else {
|
||||||
specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources(), c.config.TolerateMissingHugePagesCgroupController))
|
specOpts = append(specOpts, customopts.WithResources(config.GetLinux().GetResources(), c.config.TolerateMissingHugetlbController))
|
||||||
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
if sandboxConfig.GetLinux().GetCgroupParent() != "" {
|
||||||
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id)
|
cgroupsPath := getCgroupsPath(sandboxConfig.GetLinux().GetCgroupParent(), id)
|
||||||
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
specOpts = append(specOpts, oci.WithCgroup(cgroupsPath))
|
||||||
|
6
vendor/github.com/containerd/cri/pkg/server/container_update_resources_unix.go
generated
vendored
6
vendor/github.com/containerd/cri/pkg/server/container_update_resources_unix.go
generated
vendored
@ -73,7 +73,7 @@ func (c *criService) updateContainerResources(ctx context.Context,
|
|||||||
return errors.Wrap(err, "failed to get container spec")
|
return errors.Wrap(err, "failed to get container spec")
|
||||||
}
|
}
|
||||||
newSpec, err := updateOCILinuxResource(ctx, oldSpec, resources,
|
newSpec, err := updateOCILinuxResource(ctx, oldSpec, resources,
|
||||||
c.config.TolerateMissingHugePagesCgroupController)
|
c.config.TolerateMissingHugetlbController)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to update resource in spec")
|
return errors.Wrap(err, "failed to update resource in spec")
|
||||||
}
|
}
|
||||||
@ -134,7 +134,7 @@ func updateContainerSpec(ctx context.Context, cntr containerd.Container, spec *r
|
|||||||
|
|
||||||
// updateOCILinuxResource updates container resource limit.
|
// updateOCILinuxResource updates container resource limit.
|
||||||
func updateOCILinuxResource(ctx context.Context, spec *runtimespec.Spec, new *runtime.LinuxContainerResources,
|
func updateOCILinuxResource(ctx context.Context, spec *runtimespec.Spec, new *runtime.LinuxContainerResources,
|
||||||
tolerateMissingHugePagesCgroupController bool) (*runtimespec.Spec, error) {
|
tolerateMissingHugetlbController bool) (*runtimespec.Spec, error) {
|
||||||
// Copy to make sure old spec is not changed.
|
// Copy to make sure old spec is not changed.
|
||||||
var cloned runtimespec.Spec
|
var cloned runtimespec.Spec
|
||||||
if err := util.DeepCopy(&cloned, spec); err != nil {
|
if err := util.DeepCopy(&cloned, spec); err != nil {
|
||||||
@ -143,7 +143,7 @@ func updateOCILinuxResource(ctx context.Context, spec *runtimespec.Spec, new *ru
|
|||||||
if cloned.Linux == nil {
|
if cloned.Linux == nil {
|
||||||
cloned.Linux = &runtimespec.Linux{}
|
cloned.Linux = &runtimespec.Linux{}
|
||||||
}
|
}
|
||||||
if err := opts.WithResources(new, tolerateMissingHugePagesCgroupController)(ctx, nil, nil, &cloned); err != nil {
|
if err := opts.WithResources(new, tolerateMissingHugetlbController)(ctx, nil, nil, &cloned); err != nil {
|
||||||
return nil, errors.Wrap(err, "unable to set linux container resources")
|
return nil, errors.Wrap(err, "unable to set linux container resources")
|
||||||
}
|
}
|
||||||
return &cloned, nil
|
return &cloned, nil
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/server/image_pull.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/image_pull.go
generated
vendored
@ -284,7 +284,7 @@ func (c *criService) getTLSConfig(registryTLSConfig criconfig.TLSConfig) (*tls.C
|
|||||||
if len(cert.Certificate) != 0 {
|
if len(cert.Certificate) != 0 {
|
||||||
tlsConfig.Certificates = []tls.Certificate{cert}
|
tlsConfig.Certificates = []tls.Certificate{cert}
|
||||||
}
|
}
|
||||||
tlsConfig.BuildNameToCertificate()
|
tlsConfig.BuildNameToCertificate() // nolint:staticcheck
|
||||||
}
|
}
|
||||||
|
|
||||||
if registryTLSConfig.CAFile != "" {
|
if registryTLSConfig.CAFile != "" {
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/server/sandbox_run.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/sandbox_run.go
generated
vendored
@ -33,13 +33,13 @@ import (
|
|||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
"k8s.io/kubernetes/pkg/util/bandwidth"
|
|
||||||
|
|
||||||
"github.com/containerd/cri/pkg/annotations"
|
"github.com/containerd/cri/pkg/annotations"
|
||||||
criconfig "github.com/containerd/cri/pkg/config"
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
customopts "github.com/containerd/cri/pkg/containerd/opts"
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
"github.com/containerd/cri/pkg/netns"
|
"github.com/containerd/cri/pkg/netns"
|
||||||
|
"github.com/containerd/cri/pkg/server/bandwidth"
|
||||||
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
|
sandboxstore "github.com/containerd/cri/pkg/store/sandbox"
|
||||||
"github.com/containerd/cri/pkg/util"
|
"github.com/containerd/cri/pkg/util"
|
||||||
selinux "github.com/opencontainers/selinux/go-selinux"
|
selinux "github.com/opencontainers/selinux/go-selinux"
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/server/service.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/service.go
generated
vendored
@ -28,12 +28,12 @@ import (
|
|||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/oci"
|
"github.com/containerd/containerd/oci"
|
||||||
"github.com/containerd/containerd/plugin"
|
"github.com/containerd/containerd/plugin"
|
||||||
|
"github.com/containerd/cri/pkg/streaming"
|
||||||
cni "github.com/containerd/go-cni"
|
cni "github.com/containerd/go-cni"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
|
||||||
|
|
||||||
"github.com/containerd/cri/pkg/store/label"
|
"github.com/containerd/cri/pkg/store/label"
|
||||||
|
|
||||||
|
2
vendor/github.com/containerd/cri/pkg/server/streaming.go
generated
vendored
2
vendor/github.com/containerd/cri/pkg/server/streaming.go
generated
vendored
@ -30,10 +30,10 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
k8scert "k8s.io/client-go/util/cert"
|
k8scert "k8s.io/client-go/util/cert"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
|
||||||
"k8s.io/utils/exec"
|
"k8s.io/utils/exec"
|
||||||
|
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
|
"github.com/containerd/cri/pkg/streaming"
|
||||||
)
|
)
|
||||||
|
|
||||||
type streamListenerMode int
|
type streamListenerMode int
|
||||||
|
20
vendor/github.com/containerd/cri/pkg/store/sandbox/status.go
generated
vendored
20
vendor/github.com/containerd/cri/pkg/store/sandbox/status.go
generated
vendored
@ -17,8 +17,11 @@
|
|||||||
package sandbox
|
package sandbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The sandbox state machine in the CRI plugin:
|
// The sandbox state machine in the CRI plugin:
|
||||||
@ -63,7 +66,7 @@ type State uint32
|
|||||||
const (
|
const (
|
||||||
// StateReady is ready state, it means sandbox container
|
// StateReady is ready state, it means sandbox container
|
||||||
// is running.
|
// is running.
|
||||||
StateReady = iota
|
StateReady State = iota
|
||||||
// StateNotReady is notready state, it ONLY means sandbox
|
// StateNotReady is notready state, it ONLY means sandbox
|
||||||
// container is not running.
|
// container is not running.
|
||||||
// StopPodSandbox should still be called for NOTREADY sandbox to
|
// StopPodSandbox should still be called for NOTREADY sandbox to
|
||||||
@ -75,6 +78,21 @@ const (
|
|||||||
StateUnknown
|
StateUnknown
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// String returns the string representation of the state
|
||||||
|
func (s State) String() string {
|
||||||
|
switch s {
|
||||||
|
case StateReady:
|
||||||
|
return runtime.PodSandboxState_SANDBOX_READY.String()
|
||||||
|
case StateNotReady:
|
||||||
|
return runtime.PodSandboxState_SANDBOX_NOTREADY.String()
|
||||||
|
case StateUnknown:
|
||||||
|
// PodSandboxState doesn't have an unknown state, but State does, so return a string using the same convention
|
||||||
|
return "SANDBOX_UNKNOWN"
|
||||||
|
default:
|
||||||
|
return "invalid sandbox state value: " + strconv.Itoa(int(s))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Status is the status of a sandbox.
|
// Status is the status of a sandbox.
|
||||||
type Status struct {
|
type Status struct {
|
||||||
// Pid is the init process id of the sandbox container.
|
// Pid is the init process id of the sandbox container.
|
||||||
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2015 The Kubernetes Authors.
|
Copyright 2015 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -24,13 +40,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||||
"k8s.io/apimachinery/pkg/util/httpstream/spdy"
|
"k8s.io/apimachinery/pkg/util/httpstream/spdy"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func handleHTTPStreams(req *http.Request, w http.ResponseWriter, portForwarder PortForwarder, podName string, uid types.UID, supportedPortForwardProtocols []string, idleTimeout, streamCreationTimeout time.Duration) error {
|
func handleHTTPStreams(req *http.Request, w http.ResponseWriter, portForwarder PortForwarder, podName string, uid types.UID, supportedPortForwardProtocols []string, idleTimeout, streamCreationTimeout time.Duration) error {
|
||||||
@ -148,16 +164,6 @@ func (h *httpStreamHandler) monitorStreamPair(p *httpStreamPair, timeout <-chan
|
|||||||
h.removeStreamPair(p.requestID)
|
h.removeStreamPair(p.requestID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hasStreamPair returns a bool indicating if a stream pair for requestID
|
|
||||||
// exists.
|
|
||||||
func (h *httpStreamHandler) hasStreamPair(requestID string) bool {
|
|
||||||
h.streamPairsLock.RLock()
|
|
||||||
defer h.streamPairsLock.RUnlock()
|
|
||||||
|
|
||||||
_, ok := h.streamPairs[requestID]
|
|
||||||
return ok
|
|
||||||
}
|
|
||||||
|
|
||||||
// removeStreamPair removes the stream pair identified by requestID from streamPairs.
|
// removeStreamPair removes the stream pair identified by requestID from streamPairs.
|
||||||
func (h *httpStreamHandler) removeStreamPair(requestID string) {
|
func (h *httpStreamHandler) removeStreamPair(requestID string) {
|
||||||
h.streamPairsLock.Lock()
|
h.streamPairsLock.Lock()
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -26,13 +42,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apiserver/pkg/server/httplog"
|
"k8s.io/apiserver/pkg/server/httplog"
|
||||||
"k8s.io/apiserver/pkg/util/wsstream"
|
"k8s.io/apiserver/pkg/util/wsstream"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -15,4 +31,4 @@ limitations under the License.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Package remotecommand contains functions related to executing commands in and attaching to pods.
|
// Package remotecommand contains functions related to executing commands in and attaching to pods.
|
||||||
package remotecommand // import "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
|
package remotecommand
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -24,6 +40,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
api "k8s.io/api/core/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/httpstream"
|
"k8s.io/apimachinery/pkg/util/httpstream"
|
||||||
@ -32,9 +49,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/runtime"
|
"k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apiserver/pkg/util/wsstream"
|
"k8s.io/apiserver/pkg/util/wsstream"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
|
||||||
|
|
||||||
"k8s.io/klog"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Options contains details about which streams are required for
|
// Options contains details about which streams are required for
|
||||||
@ -411,6 +427,7 @@ func (*v1ProtocolHandler) supportsTerminalResizing() bool { return false }
|
|||||||
|
|
||||||
func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalSize) {
|
func handleResizeEvents(stream io.Reader, channel chan<- remotecommand.TerminalSize) {
|
||||||
defer runtime.HandleCrash()
|
defer runtime.HandleCrash()
|
||||||
|
defer close(channel)
|
||||||
|
|
||||||
decoder := json.NewDecoder(stream)
|
decoder := json.NewDecoder(stream)
|
||||||
for {
|
for {
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
@ -1,3 +1,19 @@
|
|||||||
|
/*
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright 2016 The Kubernetes Authors.
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
@ -35,8 +51,9 @@ import (
|
|||||||
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
|
remotecommandconsts "k8s.io/apimachinery/pkg/util/remotecommand"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/portforward"
|
|
||||||
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
|
"github.com/containerd/cri/pkg/streaming/portforward"
|
||||||
|
remotecommandserver "github.com/containerd/cri/pkg/streaming/remotecommand"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Server is the library interface to serve the stream requests.
|
// Server is the library interface to serve the stream requests.
|
54
vendor/github.com/containerd/cri/vendor.conf
generated
vendored
54
vendor/github.com/containerd/cri/vendor.conf
generated
vendored
@ -1,13 +1,13 @@
|
|||||||
# cri dependencies
|
# cri dependencies
|
||||||
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
github.com/docker/docker 4634ce647cf2ce2c6031129ccd109e557244986f
|
||||||
github.com/opencontainers/selinux bb88c45a3863dc4c38320d71b890bb30ef9feba4
|
github.com/opencontainers/selinux v1.5.1
|
||||||
github.com/tchap/go-patricia v2.2.6
|
github.com/tchap/go-patricia v2.2.6
|
||||||
|
|
||||||
# containerd dependencies
|
# containerd dependencies
|
||||||
github.com/beorn7/perks v1.0.1
|
github.com/beorn7/perks v1.0.1
|
||||||
github.com/BurntSushi/toml v0.3.1
|
github.com/BurntSushi/toml v0.3.1
|
||||||
github.com/cespare/xxhash/v2 v2.1.1
|
github.com/cespare/xxhash/v2 v2.1.1
|
||||||
github.com/containerd/cgroups b4448137398923af7f4918b8b2ad8249172ca7a6
|
github.com/containerd/cgroups e9676da73eddf8ed2433f77aaf3b9cf8f0f75b8c
|
||||||
github.com/containerd/console v1.0.0
|
github.com/containerd/console v1.0.0
|
||||||
github.com/containerd/containerd v1.4.0-beta.0
|
github.com/containerd/containerd v1.4.0-beta.0
|
||||||
github.com/containerd/continuity d3ef23f19fbb106bb73ffde425d07a9187e30745
|
github.com/containerd/continuity d3ef23f19fbb106bb73ffde425d07a9187e30745
|
||||||
@ -16,14 +16,14 @@ github.com/containerd/go-runc 7016d3ce2328dd2cb1192b2076eb
|
|||||||
github.com/containerd/ttrpc v1.0.1
|
github.com/containerd/ttrpc v1.0.1
|
||||||
github.com/containerd/typeurl v1.0.1
|
github.com/containerd/typeurl v1.0.1
|
||||||
github.com/coreos/go-systemd/v22 v22.0.0
|
github.com/coreos/go-systemd/v22 v22.0.0
|
||||||
github.com/cpuguy83/go-md2man v1.0.10
|
github.com/cpuguy83/go-md2man/v2 v2.0.0
|
||||||
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
github.com/docker/go-events e31b211e4f1cd09aa76fe4ac244571fab96ae47f
|
||||||
github.com/docker/go-metrics v0.0.1
|
github.com/docker/go-metrics v0.0.1
|
||||||
github.com/docker/go-units v0.4.0
|
github.com/docker/go-units v0.4.0
|
||||||
github.com/godbus/dbus/v5 v5.0.3
|
github.com/godbus/dbus/v5 v5.0.3
|
||||||
github.com/gogo/googleapis v1.3.2
|
github.com/gogo/googleapis v1.3.2
|
||||||
github.com/gogo/protobuf v1.3.1
|
github.com/gogo/protobuf v1.3.1
|
||||||
github.com/golang/protobuf v1.3.3
|
github.com/golang/protobuf v1.3.5
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||||
github.com/hashicorp/errwrap v1.0.0
|
github.com/hashicorp/errwrap v1.0.0
|
||||||
@ -36,53 +36,55 @@ github.com/Microsoft/go-winio v0.4.14
|
|||||||
github.com/Microsoft/hcsshim v0.8.9
|
github.com/Microsoft/hcsshim v0.8.9
|
||||||
github.com/opencontainers/go-digest v1.0.0
|
github.com/opencontainers/go-digest v1.0.0
|
||||||
github.com/opencontainers/image-spec v1.0.1
|
github.com/opencontainers/image-spec v1.0.1
|
||||||
github.com/opencontainers/runc v1.0.0-rc10
|
github.com/opencontainers/runc v1.0.0-rc91
|
||||||
github.com/opencontainers/runtime-spec v1.0.2
|
github.com/opencontainers/runtime-spec 237cc4f519e2e8f9b235bacccfa8ef5a84df2875 # v1.0.2-14-g8e2f17c
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.3.0
|
github.com/prometheus/client_golang v1.6.0
|
||||||
github.com/prometheus/client_model v0.1.0
|
github.com/prometheus/client_model v0.2.0
|
||||||
github.com/prometheus/common v0.7.0
|
github.com/prometheus/common v0.9.1
|
||||||
github.com/prometheus/procfs v0.0.8
|
github.com/prometheus/procfs v0.0.11
|
||||||
github.com/russross/blackfriday v1.5.2
|
github.com/russross/blackfriday/v2 v2.0.1
|
||||||
|
github.com/shurcooL/sanitized_anchor_name v1.0.0
|
||||||
github.com/sirupsen/logrus v1.6.0
|
github.com/sirupsen/logrus v1.6.0
|
||||||
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
||||||
github.com/urfave/cli v1.22.0
|
github.com/urfave/cli v1.22.1 # NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||||
go.etcd.io/bbolt v1.3.3
|
go.etcd.io/bbolt v1.3.3
|
||||||
go.opencensus.io v0.22.0
|
go.opencensus.io v0.22.0
|
||||||
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
golang.org/x/net f3200d17e092c607f615320ecaad13d87ad9a2b3
|
||||||
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
golang.org/x/sync 42b317875d0fa942474b76e1b46a6060d720ae6e
|
||||||
golang.org/x/sys 5c8b2ff67527cb88b770f693cebf3799036d8bc0
|
golang.org/x/sys 9dae0f8f577553e0f21298e18926efc9644c281d
|
||||||
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4
|
||||||
google.golang.org/genproto e50cd9704f63023d62cd06a1994b98227fc4d21a
|
google.golang.org/genproto e50cd9704f63023d62cd06a1994b98227fc4d21a
|
||||||
google.golang.org/grpc v1.27.1
|
google.golang.org/grpc v1.27.1
|
||||||
|
|
||||||
# cgroups dependencies
|
# cgroups dependencies
|
||||||
github.com/cilium/ebpf 4032b1d8aae306b7bb94a2a11002932caf88c644
|
github.com/cilium/ebpf 1c8d4c9ef7759622653a1d319284a44652333b28
|
||||||
|
|
||||||
# kubernetes dependencies
|
# kubernetes dependencies
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
github.com/docker/spdystream 449fdfce4d962303d702fec724ef0ad181c92528
|
||||||
github.com/emicklei/go-restful v2.9.5
|
github.com/emicklei/go-restful v2.9.5
|
||||||
|
github.com/go-logr/logr v0.2.0
|
||||||
github.com/google/gofuzz v1.1.0
|
github.com/google/gofuzz v1.1.0
|
||||||
github.com/json-iterator/go v1.1.8
|
github.com/json-iterator/go v1.1.9
|
||||||
github.com/modern-go/concurrent 1.0.3
|
github.com/modern-go/concurrent 1.0.3
|
||||||
github.com/modern-go/reflect2 v1.0.1
|
github.com/modern-go/reflect2 v1.0.1
|
||||||
github.com/pmezard/go-difflib v1.0.0
|
github.com/pmezard/go-difflib v1.0.0
|
||||||
github.com/seccomp/libseccomp-golang v0.9.1
|
github.com/seccomp/libseccomp-golang v0.9.1
|
||||||
github.com/stretchr/testify v1.4.0
|
github.com/stretchr/testify v1.4.0
|
||||||
golang.org/x/crypto bac4c82f69751a6dd76e702d54b3ceb88adab236
|
golang.org/x/crypto bac4c82f69751a6dd76e702d54b3ceb88adab236
|
||||||
golang.org/x/oauth2 0f29369cfe4552d0e4bcddc57cc75f4d7e672a33
|
golang.org/x/oauth2 858c2ad4c8b6c5d10852cb89079f6ca1c7309787
|
||||||
golang.org/x/time 9d24e82272b4f38b78bc8cff74fa936d31ccd8ef
|
golang.org/x/time 555d28b269f0569763d25dbe1a237ae74c6bcc82
|
||||||
gopkg.in/inf.v0 v0.9.1
|
gopkg.in/inf.v0 v0.9.1
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
k8s.io/api v0.18.2
|
k8s.io/api v0.19.0-beta.2
|
||||||
k8s.io/apimachinery v0.18.2
|
k8s.io/apiserver v0.19.0-beta.2
|
||||||
k8s.io/apiserver v0.18.2
|
k8s.io/apimachinery v0.19.0-beta.2
|
||||||
k8s.io/client-go v0.18.2
|
k8s.io/client-go v0.19.0-beta.2
|
||||||
k8s.io/cri-api v0.18.2
|
k8s.io/component-base v0.19.0-beta.2
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/cri-api v0.19.0-beta.2
|
||||||
k8s.io/kubernetes v1.18.2
|
k8s.io/klog/v2 v2.2.0
|
||||||
k8s.io/utils a9aa75ae1b89e1b992c33383f48e942d97e52dae
|
k8s.io/utils 2df71ebbae66f39338aed4cd0bb82d2212ee33cc
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0
|
||||||
sigs.k8s.io/yaml v1.2.0
|
sigs.k8s.io/yaml v1.2.0
|
||||||
|
|
||||||
@ -90,7 +92,7 @@ sigs.k8s.io/yaml v1.2.0
|
|||||||
github.com/containerd/go-cni v1.0.0
|
github.com/containerd/go-cni v1.0.0
|
||||||
github.com/containernetworking/cni v0.7.1
|
github.com/containernetworking/cni v0.7.1
|
||||||
github.com/containernetworking/plugins v0.7.6
|
github.com/containernetworking/plugins v0.7.6
|
||||||
github.com/fsnotify/fsnotify v1.4.8
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
|
|
||||||
# image decrypt depedencies
|
# image decrypt depedencies
|
||||||
github.com/containerd/imgcrypt v1.0.1
|
github.com/containerd/imgcrypt v1.0.1
|
||||||
|
47
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
47
vendor/github.com/fsnotify/fsnotify/README.md
generated
vendored
@ -33,6 +33,53 @@ All [releases](https://github.com/fsnotify/fsnotify/releases) are tagged based o
|
|||||||
|
|
||||||
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
|
Go 1.6 supports dependencies located in the `vendor/` folder. Unless you are creating a library, it is recommended that you copy fsnotify into `vendor/github.com/fsnotify/fsnotify` within your project, and likewise for `golang.org/x/sys`.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/fsnotify/fsnotify"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
watcher, err := fsnotify.NewWatcher()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer watcher.Close()
|
||||||
|
|
||||||
|
done := make(chan bool)
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case event, ok := <-watcher.Events:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("event:", event)
|
||||||
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
log.Println("modified file:", event.Name)
|
||||||
|
}
|
||||||
|
case err, ok := <-watcher.Errors:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Println("error:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = watcher.Add("/tmp/foo")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
Please refer to [CONTRIBUTING][] before opening an issue or pull request.
|
||||||
|
5
vendor/k8s.io/kubernetes/LICENSE → vendor/github.com/go-logr/logr/LICENSE
generated
vendored
5
vendor/k8s.io/kubernetes/LICENSE → vendor/github.com/go-logr/logr/LICENSE
generated
vendored
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
Apache License
|
Apache License
|
||||||
Version 2.0, January 2004
|
Version 2.0, January 2004
|
||||||
http://www.apache.org/licenses/
|
http://www.apache.org/licenses/
|
||||||
@ -179,7 +178,7 @@
|
|||||||
APPENDIX: How to apply the Apache License to your work.
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
To apply the Apache License to your work, attach the following
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
replaced with your own identifying information. (Don't include
|
replaced with your own identifying information. (Don't include
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
comment syntax for the file format. We also recommend that a
|
comment syntax for the file format. We also recommend that a
|
||||||
@ -187,7 +186,7 @@
|
|||||||
same "printed page" as the copyright notice for easier
|
same "printed page" as the copyright notice for easier
|
||||||
identification within third-party archives.
|
identification within third-party archives.
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
181
vendor/github.com/go-logr/logr/README.md
generated
vendored
Normal file
181
vendor/github.com/go-logr/logr/README.md
generated
vendored
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# A more minimal logging API for Go
|
||||||
|
|
||||||
|
Before you consider this package, please read [this blog post by the
|
||||||
|
inimitable Dave Cheney][warning-makes-no-sense]. I really appreciate what
|
||||||
|
he has to say, and it largely aligns with my own experiences. Too many
|
||||||
|
choices of levels means inconsistent logs.
|
||||||
|
|
||||||
|
This package offers a purely abstract interface, based on these ideas but with
|
||||||
|
a few twists. Code can depend on just this interface and have the actual
|
||||||
|
logging implementation be injected from callers. Ideally only `main()` knows
|
||||||
|
what logging implementation is being used.
|
||||||
|
|
||||||
|
# Differences from Dave's ideas
|
||||||
|
|
||||||
|
The main differences are:
|
||||||
|
|
||||||
|
1) Dave basically proposes doing away with the notion of a logging API in favor
|
||||||
|
of `fmt.Printf()`. I disagree, especially when you consider things like output
|
||||||
|
locations, timestamps, file and line decorations, and structured logging. I
|
||||||
|
restrict the API to just 2 types of logs: info and error.
|
||||||
|
|
||||||
|
Info logs are things you want to tell the user which are not errors. Error
|
||||||
|
logs are, well, errors. If your code receives an `error` from a subordinate
|
||||||
|
function call and is logging that `error` *and not returning it*, use error
|
||||||
|
logs.
|
||||||
|
|
||||||
|
2) Verbosity-levels on info logs. This gives developers a chance to indicate
|
||||||
|
arbitrary grades of importance for info logs, without assigning names with
|
||||||
|
semantic meaning such as "warning", "trace", and "debug". Superficially this
|
||||||
|
may feel very similar, but the primary difference is the lack of semantics.
|
||||||
|
Because verbosity is a numerical value, it's safe to assume that an app running
|
||||||
|
with higher verbosity means more (and less important) logs will be generated.
|
||||||
|
|
||||||
|
This is a BETA grade API.
|
||||||
|
|
||||||
|
There are implementations for the following logging libraries:
|
||||||
|
|
||||||
|
- **github.com/google/glog**: [glogr](https://github.com/go-logr/glogr)
|
||||||
|
- **k8s.io/klog**: [klogr](https://git.k8s.io/klog/klogr)
|
||||||
|
- **go.uber.org/zap**: [zapr](https://github.com/go-logr/zapr)
|
||||||
|
- **log** (the Go standard library logger):
|
||||||
|
[stdr](https://github.com/go-logr/stdr)
|
||||||
|
- **github.com/sirupsen/logrus**: [logrusr](https://github.com/bombsimon/logrusr)
|
||||||
|
|
||||||
|
# FAQ
|
||||||
|
|
||||||
|
## Conceptual
|
||||||
|
|
||||||
|
## Why structured logging?
|
||||||
|
|
||||||
|
- **Structured logs are more easily queriable**: Since you've got
|
||||||
|
key-value pairs, it's much easier to query your structured logs for
|
||||||
|
particular values by filtering on the contents of a particular key --
|
||||||
|
think searching request logs for error codes, Kubernetes reconcilers for
|
||||||
|
the name and namespace of the reconciled object, etc
|
||||||
|
|
||||||
|
- **Structured logging makes it easier to have cross-referencable logs**:
|
||||||
|
Similarly to searchability, if you maintain conventions around your
|
||||||
|
keys, it becomes easy to gather all log lines related to a particular
|
||||||
|
concept.
|
||||||
|
|
||||||
|
- **Structured logs allow better dimensions of filtering**: if you have
|
||||||
|
structure to your logs, you've got more precise control over how much
|
||||||
|
information is logged -- you might choose in a particular configuration
|
||||||
|
to log certain keys but not others, only log lines where a certain key
|
||||||
|
matches a certain value, etc, instead of just having v-levels and names
|
||||||
|
to key off of.
|
||||||
|
|
||||||
|
- **Structured logs better represent structured data**: sometimes, the
|
||||||
|
data that you want to log is inherently structured (think tuple-link
|
||||||
|
objects). Structured logs allow you to preserve that structure when
|
||||||
|
outputting.
|
||||||
|
|
||||||
|
## Why V-levels?
|
||||||
|
|
||||||
|
**V-levels give operators an easy way to control the chattiness of log
|
||||||
|
operations**. V-levels provide a way for a given package to distinguish
|
||||||
|
the relative importance or verbosity of a given log message. Then, if
|
||||||
|
a particular logger or package is logging too many messages, the user
|
||||||
|
of the package can simply change the v-levels for that library.
|
||||||
|
|
||||||
|
## Why not more named levels, like Warning?
|
||||||
|
|
||||||
|
Read [Dave Cheney's post][warning-makes-no-sense]. Then read [Differences
|
||||||
|
from Dave's ideas](#differences-from-daves-ideas).
|
||||||
|
|
||||||
|
## Why not allow format strings, too?
|
||||||
|
|
||||||
|
**Format strings negate many of the benefits of structured logs**:
|
||||||
|
|
||||||
|
- They're not easily searchable without resorting to fuzzy searching,
|
||||||
|
regular expressions, etc
|
||||||
|
|
||||||
|
- They don't store structured data well, since contents are flattened into
|
||||||
|
a string
|
||||||
|
|
||||||
|
- They're not cross-referencable
|
||||||
|
|
||||||
|
- They don't compress easily, since the message is not constant
|
||||||
|
|
||||||
|
(unless you turn positional parameters into key-value pairs with numerical
|
||||||
|
keys, at which point you've gotten key-value logging with meaningless
|
||||||
|
keys)
|
||||||
|
|
||||||
|
## Practical
|
||||||
|
|
||||||
|
## Why key-value pairs, and not a map?
|
||||||
|
|
||||||
|
Key-value pairs are *much* easier to optimize, especially around
|
||||||
|
allocations. Zap (a structured logger that inspired logr's interface) has
|
||||||
|
[performance measurements](https://github.com/uber-go/zap#performance)
|
||||||
|
that show this quite nicely.
|
||||||
|
|
||||||
|
While the interface ends up being a little less obvious, you get
|
||||||
|
potentially better performance, plus avoid making users type
|
||||||
|
`map[string]string{}` every time they want to log.
|
||||||
|
|
||||||
|
## What if my V-levels differ between libraries?
|
||||||
|
|
||||||
|
That's fine. Control your V-levels on a per-logger basis, and use the
|
||||||
|
`WithName` function to pass different loggers to different libraries.
|
||||||
|
|
||||||
|
Generally, you should take care to ensure that you have relatively
|
||||||
|
consistent V-levels within a given logger, however, as this makes deciding
|
||||||
|
on what verbosity of logs to request easier.
|
||||||
|
|
||||||
|
## But I *really* want to use a format string!
|
||||||
|
|
||||||
|
That's not actually a question. Assuming your question is "how do
|
||||||
|
I convert my mental model of logging with format strings to logging with
|
||||||
|
constant messages":
|
||||||
|
|
||||||
|
1. figure out what the error actually is, as you'd write in a TL;DR style,
|
||||||
|
and use that as a message
|
||||||
|
|
||||||
|
2. For every place you'd write a format specifier, look to the word before
|
||||||
|
it, and add that as a key value pair
|
||||||
|
|
||||||
|
For instance, consider the following examples (all taken from spots in the
|
||||||
|
Kubernetes codebase):
|
||||||
|
|
||||||
|
- `klog.V(4).Infof("Client is returning errors: code %v, error %v",
|
||||||
|
responseCode, err)` becomes `logger.Error(err, "client returned an
|
||||||
|
error", "code", responseCode)`
|
||||||
|
|
||||||
|
- `klog.V(4).Infof("Got a Retry-After %ds response for attempt %d to %v",
|
||||||
|
seconds, retries, url)` becomes `logger.V(4).Info("got a retry-after
|
||||||
|
response when requesting url", "attempt", retries, "after
|
||||||
|
seconds", seconds, "url", url)`
|
||||||
|
|
||||||
|
If you *really* must use a format string, place it as a key value, and
|
||||||
|
call `fmt.Sprintf` yourself -- for instance, `log.Printf("unable to
|
||||||
|
reflect over type %T")` becomes `logger.Info("unable to reflect over
|
||||||
|
type", "type", fmt.Sprintf("%T"))`. In general though, the cases where
|
||||||
|
this is necessary should be few and far between.
|
||||||
|
|
||||||
|
## How do I choose my V-levels?
|
||||||
|
|
||||||
|
This is basically the only hard constraint: increase V-levels to denote
|
||||||
|
more verbose or more debug-y logs.
|
||||||
|
|
||||||
|
Otherwise, you can start out with `0` as "you always want to see this",
|
||||||
|
`1` as "common logging that you might *possibly* want to turn off", and
|
||||||
|
`10` as "I would like to performance-test your log collection stack".
|
||||||
|
|
||||||
|
Then gradually choose levels in between as you need them, working your way
|
||||||
|
down from 10 (for debug and trace style logs) and up from 1 (for chattier
|
||||||
|
info-type logs).
|
||||||
|
|
||||||
|
## How do I choose my keys
|
||||||
|
|
||||||
|
- make your keys human-readable
|
||||||
|
- constant keys are generally a good idea
|
||||||
|
- be consistent across your codebase
|
||||||
|
- keys should naturally match parts of the message string
|
||||||
|
|
||||||
|
While key names are mostly unrestricted (and spaces are acceptable),
|
||||||
|
it's generally a good idea to stick to printable ascii characters, or at
|
||||||
|
least match the general character set of your log lines.
|
||||||
|
|
||||||
|
[warning-makes-no-sense]: http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
3
vendor/github.com/go-logr/logr/go.mod
generated
vendored
Normal file
3
vendor/github.com/go-logr/logr/go.mod
generated
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module github.com/go-logr/logr
|
||||||
|
|
||||||
|
go 1.14
|
178
vendor/github.com/go-logr/logr/logr.go
generated
vendored
Normal file
178
vendor/github.com/go-logr/logr/logr.go
generated
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2019 The logr 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 logr defines abstract interfaces for logging. Packages can depend on
|
||||||
|
// these interfaces and callers can implement logging in whatever way is
|
||||||
|
// appropriate.
|
||||||
|
//
|
||||||
|
// This design derives from Dave Cheney's blog:
|
||||||
|
// http://dave.cheney.net/2015/11/05/lets-talk-about-logging
|
||||||
|
//
|
||||||
|
// This is a BETA grade API. Until there is a significant 2nd implementation,
|
||||||
|
// I don't really know how it will change.
|
||||||
|
//
|
||||||
|
// The logging specifically makes it non-trivial to use format strings, to encourage
|
||||||
|
// attaching structured information instead of unstructured format strings.
|
||||||
|
//
|
||||||
|
// Usage
|
||||||
|
//
|
||||||
|
// Logging is done using a Logger. Loggers can have name prefixes and named
|
||||||
|
// values attached, so that all log messages logged with that Logger have some
|
||||||
|
// base context associated.
|
||||||
|
//
|
||||||
|
// The term "key" is used to refer to the name associated with a particular
|
||||||
|
// value, to disambiguate it from the general Logger name.
|
||||||
|
//
|
||||||
|
// For instance, suppose we're trying to reconcile the state of an object, and
|
||||||
|
// we want to log that we've made some decision.
|
||||||
|
//
|
||||||
|
// With the traditional log package, we might write:
|
||||||
|
// log.Printf(
|
||||||
|
// "decided to set field foo to value %q for object %s/%s",
|
||||||
|
// targetValue, object.Namespace, object.Name)
|
||||||
|
//
|
||||||
|
// With logr's structured logging, we'd write:
|
||||||
|
// // elsewhere in the file, set up the logger to log with the prefix of "reconcilers",
|
||||||
|
// // and the named value target-type=Foo, for extra context.
|
||||||
|
// log := mainLogger.WithName("reconcilers").WithValues("target-type", "Foo")
|
||||||
|
//
|
||||||
|
// // later on...
|
||||||
|
// log.Info("setting field foo on object", "value", targetValue, "object", object)
|
||||||
|
//
|
||||||
|
// Depending on our logging implementation, we could then make logging decisions
|
||||||
|
// based on field values (like only logging such events for objects in a certain
|
||||||
|
// namespace), or copy the structured information into a structured log store.
|
||||||
|
//
|
||||||
|
// For logging errors, Logger has a method called Error. Suppose we wanted to
|
||||||
|
// log an error while reconciling. With the traditional log package, we might
|
||||||
|
// write:
|
||||||
|
// log.Errorf("unable to reconcile object %s/%s: %v", object.Namespace, object.Name, err)
|
||||||
|
//
|
||||||
|
// With logr, we'd instead write:
|
||||||
|
// // assuming the above setup for log
|
||||||
|
// log.Error(err, "unable to reconcile object", "object", object)
|
||||||
|
//
|
||||||
|
// This functions similarly to:
|
||||||
|
// log.Info("unable to reconcile object", "error", err, "object", object)
|
||||||
|
//
|
||||||
|
// However, it ensures that a standard key for the error value ("error") is used
|
||||||
|
// across all error logging. Furthermore, certain implementations may choose to
|
||||||
|
// attach additional information (such as stack traces) on calls to Error, so
|
||||||
|
// it's preferred to use Error to log errors.
|
||||||
|
//
|
||||||
|
// Parts of a log line
|
||||||
|
//
|
||||||
|
// Each log message from a Logger has four types of context:
|
||||||
|
// logger name, log verbosity, log message, and the named values.
|
||||||
|
//
|
||||||
|
// The Logger name constists of a series of name "segments" added by successive
|
||||||
|
// calls to WithName. These name segments will be joined in some way by the
|
||||||
|
// underlying implementation. It is strongly reccomended that name segements
|
||||||
|
// contain simple identifiers (letters, digits, and hyphen), and do not contain
|
||||||
|
// characters that could muddle the log output or confuse the joining operation
|
||||||
|
// (e.g. whitespace, commas, periods, slashes, brackets, quotes, etc).
|
||||||
|
//
|
||||||
|
// Log verbosity represents how little a log matters. Level zero, the default,
|
||||||
|
// matters most. Increasing levels matter less and less. Try to avoid lots of
|
||||||
|
// different verbosity levels, and instead provide useful keys, logger names,
|
||||||
|
// and log messages for users to filter on. It's illegal to pass a log level
|
||||||
|
// below zero.
|
||||||
|
//
|
||||||
|
// The log message consists of a constant message attached to the the log line.
|
||||||
|
// This should generally be a simple description of what's occuring, and should
|
||||||
|
// never be a format string.
|
||||||
|
//
|
||||||
|
// Variable information can then be attached using named values (key/value
|
||||||
|
// pairs). Keys are arbitrary strings, while values may be any Go value.
|
||||||
|
//
|
||||||
|
// Key Naming Conventions
|
||||||
|
//
|
||||||
|
// Keys are not strictly required to conform to any specification or regex, but
|
||||||
|
// it is recommended that they:
|
||||||
|
// * be human-readable and meaningful (not auto-generated or simple ordinals)
|
||||||
|
// * be constant (not dependent on input data)
|
||||||
|
// * contain only printable characters
|
||||||
|
// * not contain whitespace or punctuation
|
||||||
|
//
|
||||||
|
// These guidelines help ensure that log data is processed properly regardless
|
||||||
|
// of the log implementation. For example, log implementations will try to
|
||||||
|
// output JSON data or will store data for later database (e.g. SQL) queries.
|
||||||
|
//
|
||||||
|
// While users are generally free to use key names of their choice, it's
|
||||||
|
// generally best to avoid using the following keys, as they're frequently used
|
||||||
|
// by implementations:
|
||||||
|
//
|
||||||
|
// - `"caller"`: the calling information (file/line) of a particular log line.
|
||||||
|
// - `"error"`: the underlying error value in the `Error` method.
|
||||||
|
// - `"level"`: the log level.
|
||||||
|
// - `"logger"`: the name of the associated logger.
|
||||||
|
// - `"msg"`: the log message.
|
||||||
|
// - `"stacktrace"`: the stack trace associated with a particular log line or
|
||||||
|
// error (often from the `Error` message).
|
||||||
|
// - `"ts"`: the timestamp for a log line.
|
||||||
|
//
|
||||||
|
// Implementations are encouraged to make use of these keys to represent the
|
||||||
|
// above concepts, when neccessary (for example, in a pure-JSON output form, it
|
||||||
|
// would be necessary to represent at least message and timestamp as ordinary
|
||||||
|
// named values).
|
||||||
|
package logr
|
||||||
|
|
||||||
|
// TODO: consider adding back in format strings if they're really needed
|
||||||
|
// TODO: consider other bits of zap/zapcore functionality like ObjectMarshaller (for arbitrary objects)
|
||||||
|
// TODO: consider other bits of glog functionality like Flush, InfoDepth, OutputStats
|
||||||
|
|
||||||
|
// Logger represents the ability to log messages, both errors and not.
|
||||||
|
type Logger interface {
|
||||||
|
// Enabled tests whether this Logger is enabled. For example, commandline
|
||||||
|
// flags might be used to set the logging verbosity and disable some info
|
||||||
|
// logs.
|
||||||
|
Enabled() bool
|
||||||
|
|
||||||
|
// Info logs a non-error message with the given key/value pairs as context.
|
||||||
|
//
|
||||||
|
// The msg argument should be used to add some constant description to
|
||||||
|
// the log line. The key/value pairs can then be used to add additional
|
||||||
|
// variable information. The key/value pairs should alternate string
|
||||||
|
// keys and arbitrary values.
|
||||||
|
Info(msg string, keysAndValues ...interface{})
|
||||||
|
|
||||||
|
// Error logs an error, with the given message and key/value pairs as context.
|
||||||
|
// It functions similarly to calling Info with the "error" named value, but may
|
||||||
|
// have unique behavior, and should be preferred for logging errors (see the
|
||||||
|
// package documentations for more information).
|
||||||
|
//
|
||||||
|
// The msg field should be used to add context to any underlying error,
|
||||||
|
// while the err field should be used to attach the actual error that
|
||||||
|
// triggered this log line, if present.
|
||||||
|
Error(err error, msg string, keysAndValues ...interface{})
|
||||||
|
|
||||||
|
// V returns an Logger value for a specific verbosity level, relative to
|
||||||
|
// this Logger. In other words, V values are additive. V higher verbosity
|
||||||
|
// level means a log message is less important. It's illegal to pass a log
|
||||||
|
// level less than zero.
|
||||||
|
V(level int) Logger
|
||||||
|
|
||||||
|
// WithValues adds some key-value pairs of context to a logger.
|
||||||
|
// See Info for documentation on how key/value pairs work.
|
||||||
|
WithValues(keysAndValues ...interface{}) Logger
|
||||||
|
|
||||||
|
// WithName adds a new element to the logger's name.
|
||||||
|
// Successive calls with WithName continue to append
|
||||||
|
// suffixes to the logger's name. It's strongly reccomended
|
||||||
|
// that name segments contain only letters, digits, and hyphens
|
||||||
|
// (see the package documentation for more information).
|
||||||
|
WithName(name string) Logger
|
||||||
|
}
|
2
vendor/github.com/golang/protobuf/go.mod
generated
vendored
2
vendor/github.com/golang/protobuf/go.mod
generated
vendored
@ -1,3 +1,3 @@
|
|||||||
module github.com/golang/protobuf
|
module github.com/golang/protobuf
|
||||||
|
|
||||||
go 1.12
|
go 1.9
|
||||||
|
7
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
generated
vendored
7
vendor/github.com/golang/protobuf/ptypes/any/any.pb.go
generated
vendored
@ -102,7 +102,8 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
|||||||
//
|
//
|
||||||
type Any struct {
|
type Any struct {
|
||||||
// A URL/resource name that uniquely identifies the type of the serialized
|
// A URL/resource name that uniquely identifies the type of the serialized
|
||||||
// protocol buffer message. The last segment of the URL's path must represent
|
// protocol buffer message. This string must contain at least
|
||||||
|
// one "/" character. The last segment of the URL's path must represent
|
||||||
// the fully qualified name of the type (as in
|
// the fully qualified name of the type (as in
|
||||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||||
// (e.g., leading "." is not accepted).
|
// (e.g., leading "." is not accepted).
|
||||||
@ -181,7 +182,9 @@ func init() {
|
|||||||
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
proto.RegisterType((*Any)(nil), "google.protobuf.Any")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4) }
|
func init() {
|
||||||
|
proto.RegisterFile("google/protobuf/any.proto", fileDescriptor_b53526c13ae22eb4)
|
||||||
|
}
|
||||||
|
|
||||||
var fileDescriptor_b53526c13ae22eb4 = []byte{
|
var fileDescriptor_b53526c13ae22eb4 = []byte{
|
||||||
// 185 bytes of a gzipped FileDescriptorProto
|
// 185 bytes of a gzipped FileDescriptorProto
|
||||||
|
3
vendor/github.com/golang/protobuf/ptypes/any/any.proto
generated
vendored
3
vendor/github.com/golang/protobuf/ptypes/any/any.proto
generated
vendored
@ -121,7 +121,8 @@ option objc_class_prefix = "GPB";
|
|||||||
//
|
//
|
||||||
message Any {
|
message Any {
|
||||||
// A URL/resource name that uniquely identifies the type of the serialized
|
// A URL/resource name that uniquely identifies the type of the serialized
|
||||||
// protocol buffer message. The last segment of the URL's path must represent
|
// protocol buffer message. This string must contain at least
|
||||||
|
// one "/" character. The last segment of the URL's path must represent
|
||||||
// the fully qualified name of the type (as in
|
// the fully qualified name of the type (as in
|
||||||
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
// `path/google.protobuf.Duration`). The name should be in a canonical form
|
||||||
// (e.g., leading "." is not accepted).
|
// (e.g., leading "." is not accepted).
|
||||||
|
6
vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
generated
vendored
6
vendor/github.com/golang/protobuf/ptypes/duration/duration.pb.go
generated
vendored
@ -41,7 +41,7 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
|||||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||||
// duration.seconds += 1;
|
// duration.seconds += 1;
|
||||||
// duration.nanos -= 1000000000;
|
// duration.nanos -= 1000000000;
|
||||||
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
// } else if (duration.seconds > 0 && duration.nanos < 0) {
|
||||||
// duration.seconds -= 1;
|
// duration.seconds -= 1;
|
||||||
// duration.nanos += 1000000000;
|
// duration.nanos += 1000000000;
|
||||||
// }
|
// }
|
||||||
@ -142,7 +142,9 @@ func init() {
|
|||||||
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
proto.RegisterType((*Duration)(nil), "google.protobuf.Duration")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5) }
|
func init() {
|
||||||
|
proto.RegisterFile("google/protobuf/duration.proto", fileDescriptor_23597b2ebd7ac6c5)
|
||||||
|
}
|
||||||
|
|
||||||
var fileDescriptor_23597b2ebd7ac6c5 = []byte{
|
var fileDescriptor_23597b2ebd7ac6c5 = []byte{
|
||||||
// 190 bytes of a gzipped FileDescriptorProto
|
// 190 bytes of a gzipped FileDescriptorProto
|
||||||
|
3
vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
generated
vendored
3
vendor/github.com/golang/protobuf/ptypes/duration/duration.proto
generated
vendored
@ -61,7 +61,7 @@ option objc_class_prefix = "GPB";
|
|||||||
// if (duration.seconds < 0 && duration.nanos > 0) {
|
// if (duration.seconds < 0 && duration.nanos > 0) {
|
||||||
// duration.seconds += 1;
|
// duration.seconds += 1;
|
||||||
// duration.nanos -= 1000000000;
|
// duration.nanos -= 1000000000;
|
||||||
// } else if (durations.seconds > 0 && duration.nanos < 0) {
|
// } else if (duration.seconds > 0 && duration.nanos < 0) {
|
||||||
// duration.seconds -= 1;
|
// duration.seconds -= 1;
|
||||||
// duration.nanos += 1000000000;
|
// duration.nanos += 1000000000;
|
||||||
// }
|
// }
|
||||||
@ -101,7 +101,6 @@ option objc_class_prefix = "GPB";
|
|||||||
//
|
//
|
||||||
//
|
//
|
||||||
message Duration {
|
message Duration {
|
||||||
|
|
||||||
// Signed seconds of the span of time. Must be from -315,576,000,000
|
// Signed seconds of the span of time. Must be from -315,576,000,000
|
||||||
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
|
||||||
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
|
||||||
|
40
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
40
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.pb.go
generated
vendored
@ -20,17 +20,19 @@ var _ = math.Inf
|
|||||||
// proto package needs to be updated.
|
// proto package needs to be updated.
|
||||||
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||||
|
|
||||||
// A Timestamp represents a point in time independent of any time zone
|
// A Timestamp represents a point in time independent of any time zone or local
|
||||||
// or calendar, represented as seconds and fractions of seconds at
|
// calendar, encoded as a count of seconds and fractions of seconds at
|
||||||
// nanosecond resolution in UTC Epoch time. It is encoded using the
|
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||||
// Proleptic Gregorian Calendar which extends the Gregorian calendar
|
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||||
// backwards to year one. It is encoded assuming all minutes are 60
|
// Gregorian calendar backwards to year one.
|
||||||
// seconds long, i.e. leap seconds are "smeared" so that no leap second
|
//
|
||||||
// table is needed for interpretation. Range is from
|
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||||
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
|
// second table is needed for interpretation, using a [24-hour linear
|
||||||
// By restricting to that range, we ensure that we can convert to
|
// smear](https://developers.google.com/time/smear).
|
||||||
// and from RFC 3339 date strings.
|
//
|
||||||
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
|
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||||
|
// restricting to that range, we ensure that we can convert to and from [RFC
|
||||||
|
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
||||||
//
|
//
|
||||||
// # Examples
|
// # Examples
|
||||||
//
|
//
|
||||||
@ -91,12 +93,14 @@ const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
|||||||
// 01:30 UTC on January 15, 2017.
|
// 01:30 UTC on January 15, 2017.
|
||||||
//
|
//
|
||||||
// In JavaScript, one can convert a Date object to this format using the
|
// In JavaScript, one can convert a Date object to this format using the
|
||||||
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
|
// standard
|
||||||
|
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
||||||
// method. In Python, a standard `datetime.datetime` object can be converted
|
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
// to this format using
|
||||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
||||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
||||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
|
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
|
||||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
@ -160,7 +164,9 @@ func init() {
|
|||||||
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
proto.RegisterType((*Timestamp)(nil), "google.protobuf.Timestamp")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e) }
|
func init() {
|
||||||
|
proto.RegisterFile("google/protobuf/timestamp.proto", fileDescriptor_292007bbfe81227e)
|
||||||
|
}
|
||||||
|
|
||||||
var fileDescriptor_292007bbfe81227e = []byte{
|
var fileDescriptor_292007bbfe81227e = []byte{
|
||||||
// 191 bytes of a gzipped FileDescriptorProto
|
// 191 bytes of a gzipped FileDescriptorProto
|
||||||
|
37
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
37
vendor/github.com/golang/protobuf/ptypes/timestamp/timestamp.proto
generated
vendored
@ -40,17 +40,19 @@ option java_outer_classname = "TimestampProto";
|
|||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
option objc_class_prefix = "GPB";
|
option objc_class_prefix = "GPB";
|
||||||
|
|
||||||
// A Timestamp represents a point in time independent of any time zone
|
// A Timestamp represents a point in time independent of any time zone or local
|
||||||
// or calendar, represented as seconds and fractions of seconds at
|
// calendar, encoded as a count of seconds and fractions of seconds at
|
||||||
// nanosecond resolution in UTC Epoch time. It is encoded using the
|
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
|
||||||
// Proleptic Gregorian Calendar which extends the Gregorian calendar
|
// January 1, 1970, in the proleptic Gregorian calendar which extends the
|
||||||
// backwards to year one. It is encoded assuming all minutes are 60
|
// Gregorian calendar backwards to year one.
|
||||||
// seconds long, i.e. leap seconds are "smeared" so that no leap second
|
//
|
||||||
// table is needed for interpretation. Range is from
|
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
|
||||||
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
|
// second table is needed for interpretation, using a [24-hour linear
|
||||||
// By restricting to that range, we ensure that we can convert to
|
// smear](https://developers.google.com/time/smear).
|
||||||
// and from RFC 3339 date strings.
|
//
|
||||||
// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
|
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
|
||||||
|
// restricting to that range, we ensure that we can convert to and from [RFC
|
||||||
|
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
|
||||||
//
|
//
|
||||||
// # Examples
|
// # Examples
|
||||||
//
|
//
|
||||||
@ -111,17 +113,18 @@ option objc_class_prefix = "GPB";
|
|||||||
// 01:30 UTC on January 15, 2017.
|
// 01:30 UTC on January 15, 2017.
|
||||||
//
|
//
|
||||||
// In JavaScript, one can convert a Date object to this format using the
|
// In JavaScript, one can convert a Date object to this format using the
|
||||||
// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString]
|
// standard
|
||||||
|
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
|
||||||
// method. In Python, a standard `datetime.datetime` object can be converted
|
// method. In Python, a standard `datetime.datetime` object can be converted
|
||||||
// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime)
|
// to this format using
|
||||||
// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one
|
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
|
||||||
// can use the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
|
||||||
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime--
|
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
|
||||||
|
// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D
|
||||||
// ) to obtain a formatter capable of generating timestamps in this format.
|
// ) to obtain a formatter capable of generating timestamps in this format.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
message Timestamp {
|
message Timestamp {
|
||||||
|
|
||||||
// Represents seconds of UTC time since Unix epoch
|
// Represents seconds of UTC time since Unix epoch
|
||||||
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
|
||||||
// 9999-12-31T23:59:59Z inclusive.
|
// 9999-12-31T23:59:59Z inclusive.
|
||||||
|
2
vendor/github.com/json-iterator/go/reflect_extension.go
generated
vendored
2
vendor/github.com/json-iterator/go/reflect_extension.go
generated
vendored
@ -341,7 +341,7 @@ func describeStruct(ctx *ctx, typ reflect2.Type) *StructDescriptor {
|
|||||||
if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
|
if ctx.onlyTaggedField && !hastag && !field.Anonymous() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if tag == "-" {
|
if tag == "-" || field.Name() == "_" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tagParts := strings.Split(tag, ",")
|
tagParts := strings.Split(tag, ",")
|
||||||
|
10
vendor/github.com/json-iterator/go/reflect_map.go
generated
vendored
10
vendor/github.com/json-iterator/go/reflect_map.go
generated
vendored
@ -290,16 +290,17 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
stream.WriteObjectStart()
|
stream.WriteObjectStart()
|
||||||
mapIter := encoder.mapType.UnsafeIterate(ptr)
|
mapIter := encoder.mapType.UnsafeIterate(ptr)
|
||||||
subStream := stream.cfg.BorrowStream(nil)
|
subStream := stream.cfg.BorrowStream(nil)
|
||||||
|
subStream.Attachment = stream.Attachment
|
||||||
subIter := stream.cfg.BorrowIterator(nil)
|
subIter := stream.cfg.BorrowIterator(nil)
|
||||||
keyValues := encodedKeyValues{}
|
keyValues := encodedKeyValues{}
|
||||||
for mapIter.HasNext() {
|
for mapIter.HasNext() {
|
||||||
subStream.buf = make([]byte, 0, 64)
|
|
||||||
key, elem := mapIter.UnsafeNext()
|
key, elem := mapIter.UnsafeNext()
|
||||||
|
subStreamIndex := subStream.Buffered()
|
||||||
encoder.keyEncoder.Encode(key, subStream)
|
encoder.keyEncoder.Encode(key, subStream)
|
||||||
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
|
if subStream.Error != nil && subStream.Error != io.EOF && stream.Error == nil {
|
||||||
stream.Error = subStream.Error
|
stream.Error = subStream.Error
|
||||||
}
|
}
|
||||||
encodedKey := subStream.Buffer()
|
encodedKey := subStream.Buffer()[subStreamIndex:]
|
||||||
subIter.ResetBytes(encodedKey)
|
subIter.ResetBytes(encodedKey)
|
||||||
decodedKey := subIter.ReadString()
|
decodedKey := subIter.ReadString()
|
||||||
if stream.indention > 0 {
|
if stream.indention > 0 {
|
||||||
@ -310,7 +311,7 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
encoder.elemEncoder.Encode(elem, subStream)
|
encoder.elemEncoder.Encode(elem, subStream)
|
||||||
keyValues = append(keyValues, encodedKV{
|
keyValues = append(keyValues, encodedKV{
|
||||||
key: decodedKey,
|
key: decodedKey,
|
||||||
keyValue: subStream.Buffer(),
|
keyValue: subStream.Buffer()[subStreamIndex:],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.Sort(keyValues)
|
sort.Sort(keyValues)
|
||||||
@ -320,6 +321,9 @@ func (encoder *sortKeysMapEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
|||||||
}
|
}
|
||||||
stream.Write(keyValue.keyValue)
|
stream.Write(keyValue.keyValue)
|
||||||
}
|
}
|
||||||
|
if subStream.Error != nil && stream.Error == nil {
|
||||||
|
stream.Error = subStream.Error
|
||||||
|
}
|
||||||
stream.WriteObjectEnd()
|
stream.WriteObjectEnd()
|
||||||
stream.cfg.ReturnStream(subStream)
|
stream.cfg.ReturnStream(subStream)
|
||||||
stream.cfg.ReturnIterator(subIter)
|
stream.cfg.ReturnIterator(subIter)
|
||||||
|
1
vendor/github.com/json-iterator/go/reflect_struct_encoder.go
generated
vendored
1
vendor/github.com/json-iterator/go/reflect_struct_encoder.go
generated
vendored
@ -200,6 +200,7 @@ type stringModeStringEncoder struct {
|
|||||||
|
|
||||||
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) {
|
||||||
tempStream := encoder.cfg.BorrowStream(nil)
|
tempStream := encoder.cfg.BorrowStream(nil)
|
||||||
|
tempStream.Attachment = stream.Attachment
|
||||||
defer encoder.cfg.ReturnStream(tempStream)
|
defer encoder.cfg.ReturnStream(tempStream)
|
||||||
encoder.elemEncoder.Encode(ptr, tempStream)
|
encoder.elemEncoder.Encode(ptr, tempStream)
|
||||||
stream.WriteString(string(tempStream.Buffer()))
|
stream.WriteString(string(tempStream.Buffer()))
|
||||||
|
58
vendor/github.com/opencontainers/runc/README.md
generated
vendored
58
vendor/github.com/opencontainers/runc/README.md
generated
vendored
@ -3,6 +3,7 @@
|
|||||||
[](https://travis-ci.org/opencontainers/runc)
|
[](https://travis-ci.org/opencontainers/runc)
|
||||||
[](https://goreportcard.com/report/github.com/opencontainers/runc)
|
[](https://goreportcard.com/report/github.com/opencontainers/runc)
|
||||||
[](https://godoc.org/github.com/opencontainers/runc)
|
[](https://godoc.org/github.com/opencontainers/runc)
|
||||||
|
[](https://bestpractices.coreinfrastructure.org/projects/588)
|
||||||
|
|
||||||
## Introduction
|
## Introduction
|
||||||
|
|
||||||
@ -18,22 +19,23 @@ You can find official releases of `runc` on the [release](https://github.com/ope
|
|||||||
|
|
||||||
Currently, the following features are not considered to be production-ready:
|
Currently, the following features are not considered to be production-ready:
|
||||||
|
|
||||||
* Support for cgroup v2
|
* [Support for cgroup v2](./docs/cgroup-v2.md)
|
||||||
|
|
||||||
## Security
|
## Security
|
||||||
|
|
||||||
The reporting process and disclosure communications are outlined in [/org/security](https://github.com/opencontainers/org/blob/master/security/).
|
The reporting process and disclosure communications are outlined [here](https://github.com/opencontainers/org/blob/master/SECURITY.md).
|
||||||
|
|
||||||
|
### Security Audit
|
||||||
|
A third party security audit was performed by Cure53, you can see the full report [here](https://github.com/opencontainers/runc/blob/master/docs/Security-Audit.pdf).
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
`runc` currently supports the Linux platform with various architecture support.
|
`runc` currently supports the Linux platform with various architecture support.
|
||||||
It must be built with Go version 1.6 or higher in order for some features to function properly.
|
It must be built with Go version 1.13 or higher.
|
||||||
|
|
||||||
In order to enable seccomp support you will need to install `libseccomp` on your platform.
|
In order to enable seccomp support you will need to install `libseccomp` on your platform.
|
||||||
> e.g. `libseccomp-devel` for CentOS, or `libseccomp-dev` for Ubuntu
|
> e.g. `libseccomp-devel` for CentOS, or `libseccomp-dev` for Ubuntu
|
||||||
|
|
||||||
Otherwise, if you do not want to build `runc` with seccomp support you can add `BUILDTAGS=""` when running make.
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# create a 'github.com/opencontainers' in your GOPATH/src
|
# create a 'github.com/opencontainers' in your GOPATH/src
|
||||||
cd github.com/opencontainers
|
cd github.com/opencontainers
|
||||||
@ -58,20 +60,22 @@ sudo make install
|
|||||||
|
|
||||||
#### Build Tags
|
#### Build Tags
|
||||||
|
|
||||||
`runc` supports optional build tags for compiling support of various features.
|
`runc` supports optional build tags for compiling support of various features,
|
||||||
To add build tags to the make option the `BUILDTAGS` variable must be set.
|
with some of them enabled by default (see `BUILDTAGS` in top-level `Makefile`).
|
||||||
|
|
||||||
|
To change build tags from the default, set the `BUILDTAGS` variable for make,
|
||||||
|
e.g.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
make BUILDTAGS='seccomp apparmor'
|
make BUILDTAGS='seccomp apparmor'
|
||||||
```
|
```
|
||||||
|
|
||||||
| Build Tag | Feature | Dependency |
|
| Build Tag | Feature | Enabled by default | Dependency |
|
||||||
|-----------|------------------------------------|-------------|
|
|-----------|------------------------------------|--------------------|------------|
|
||||||
| seccomp | Syscall filtering | libseccomp |
|
| seccomp | Syscall filtering | yes | libseccomp |
|
||||||
| selinux | selinux process and mount labeling | <none> |
|
| selinux | selinux process and mount labeling | yes | <none> |
|
||||||
| apparmor | apparmor profile support | <none> |
|
| apparmor | apparmor profile support | yes | <none> |
|
||||||
| ambient | ambient capability support | kernel 4.3 |
|
| nokmem | disable kernel memory accounting | no | <none> |
|
||||||
| nokmem | disable kernel memory account | <none> |
|
|
||||||
|
|
||||||
|
|
||||||
### Running the test suite
|
### Running the test suite
|
||||||
@ -97,17 +101,30 @@ You can run a specific integration test by setting the `TESTPATH` variable.
|
|||||||
# make test TESTPATH="/checkpoint.bats"
|
# make test TESTPATH="/checkpoint.bats"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can run a test in your proxy environment by setting `DOCKER_BUILD_PROXY` and `DOCKER_RUN_PROXY` variables.
|
You can run a specific rootless integration test by setting the `ROOTLESS_TESTPATH` variable.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# make test DOCKER_BUILD_PROXY="--build-arg HTTP_PROXY=http://yourproxy/" DOCKER_RUN_PROXY="-e HTTP_PROXY=http://yourproxy/"
|
# make test ROOTLESS_TESTPATH="/checkpoint.bats"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can run a test using your container engine's flags by setting `CONTAINER_ENGINE_BUILD_FLAGS` and `CONTAINER_ENGINE_RUN_FLAGS` variables.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# make test CONTAINER_ENGINE_BUILD_FLAGS="--build-arg http_proxy=http://yourproxy/" CONTAINER_ENGINE_RUN_FLAGS="-e http_proxy=http://yourproxy/"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Dependencies Management
|
### Dependencies Management
|
||||||
|
|
||||||
`runc` uses [vndr](https://github.com/LK4D4/vndr) for dependencies management.
|
`runc` uses [Go Modules](https://github.com/golang/go/wiki/Modules) for dependencies management.
|
||||||
Please refer to [vndr](https://github.com/LK4D4/vndr) for how to add or update
|
Please refer to [Go Modules](https://github.com/golang/go/wiki/Modules) for how to add or update
|
||||||
new dependencies.
|
new dependencies. When updating dependencies, be sure that you are running Go `1.14` or newer.
|
||||||
|
|
||||||
|
```
|
||||||
|
# Update vendored dependencies
|
||||||
|
make vendor
|
||||||
|
# Verify all dependencies
|
||||||
|
make verify-dependencies
|
||||||
|
```
|
||||||
|
|
||||||
## Using runc
|
## Using runc
|
||||||
|
|
||||||
@ -275,6 +292,9 @@ PIDFile=/run/mycontainerid.pid
|
|||||||
WantedBy=multi-user.target
|
WantedBy=multi-user.target
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### cgroup v2
|
||||||
|
See [`./docs/cgroup-v2.md`](./docs/cgroup-v2.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
The code and docs are released under the [Apache 2.0 license](LICENSE).
|
The code and docs are released under the [Apache 2.0 license](LICENSE).
|
||||||
|
26
vendor/github.com/opencontainers/runc/go.mod
generated
vendored
Normal file
26
vendor/github.com/opencontainers/runc/go.mod
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
module github.com/opencontainers/runc
|
||||||
|
|
||||||
|
go 1.14
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/checkpoint-restore/go-criu/v4 v4.0.2
|
||||||
|
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3
|
||||||
|
github.com/containerd/console v1.0.0
|
||||||
|
github.com/coreos/go-systemd/v22 v22.0.0
|
||||||
|
github.com/cyphar/filepath-securejoin v0.2.2
|
||||||
|
github.com/docker/go-units v0.4.0
|
||||||
|
github.com/godbus/dbus/v5 v5.0.3
|
||||||
|
github.com/golang/protobuf v1.3.5
|
||||||
|
github.com/moby/sys/mountinfo v0.1.3
|
||||||
|
github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618
|
||||||
|
github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2
|
||||||
|
github.com/opencontainers/selinux v1.5.1
|
||||||
|
github.com/pkg/errors v0.9.1
|
||||||
|
github.com/seccomp/libseccomp-golang v0.9.1
|
||||||
|
github.com/sirupsen/logrus v1.6.0
|
||||||
|
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||||
|
// NOTE: urfave/cli must be <= v1.22.1 due to a regression: https://github.com/urfave/cli/issues/1092
|
||||||
|
github.com/urfave/cli v1.22.1
|
||||||
|
github.com/vishvananda/netlink v1.1.0
|
||||||
|
golang.org/x/sys v0.0.0-20200327173247-9dae0f8f5775
|
||||||
|
)
|
5
vendor/github.com/opencontainers/runc/libcontainer/README.md
generated
vendored
5
vendor/github.com/opencontainers/runc/libcontainer/README.md
generated
vendored
@ -155,8 +155,7 @@ config := &configs.Config{
|
|||||||
Parent: "system",
|
Parent: "system",
|
||||||
Resources: &configs.Resources{
|
Resources: &configs.Resources{
|
||||||
MemorySwappiness: nil,
|
MemorySwappiness: nil,
|
||||||
AllowAllDevices: nil,
|
Devices: specconv.AllowedDevices,
|
||||||
AllowedDevices: configs.DefaultAllowedDevices,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
MaskPaths: []string{
|
MaskPaths: []string{
|
||||||
@ -166,7 +165,7 @@ config := &configs.Config{
|
|||||||
ReadonlyPaths: []string{
|
ReadonlyPaths: []string{
|
||||||
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
|
"/proc/sys", "/proc/sysrq-trigger", "/proc/irq", "/proc/bus",
|
||||||
},
|
},
|
||||||
Devices: configs.DefaultAutoCreatedDevices,
|
Devices: specconv.AllowedDevices,
|
||||||
Hostname: "testing",
|
Hostname: "testing",
|
||||||
Mounts: []*configs.Mount{
|
Mounts: []*configs.Mount{
|
||||||
{
|
{
|
||||||
|
23
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
23
vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
generated
vendored
@ -1,5 +1,9 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
|
import (
|
||||||
|
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
|
||||||
|
)
|
||||||
|
|
||||||
type FreezerState string
|
type FreezerState string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -29,18 +33,16 @@ type Cgroup struct {
|
|||||||
|
|
||||||
// Resources contains various cgroups settings to apply
|
// Resources contains various cgroups settings to apply
|
||||||
*Resources
|
*Resources
|
||||||
|
|
||||||
|
// SystemdProps are any additional properties for systemd,
|
||||||
|
// derived from org.systemd.property.xxx annotations.
|
||||||
|
// Ignored unless systemd is used for managing cgroups.
|
||||||
|
SystemdProps []systemdDbus.Property `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Resources struct {
|
type Resources struct {
|
||||||
// If this is true allow access to any kind of device within the container. If false, allow access only to devices explicitly listed in the allowed_devices list.
|
// Devices is the set of access rules for devices in the container.
|
||||||
// Deprecated
|
Devices []*DeviceRule `json:"devices"`
|
||||||
AllowAllDevices *bool `json:"allow_all_devices,omitempty"`
|
|
||||||
// Deprecated
|
|
||||||
AllowedDevices []*Device `json:"allowed_devices,omitempty"`
|
|
||||||
// Deprecated
|
|
||||||
DeniedDevices []*Device `json:"denied_devices,omitempty"`
|
|
||||||
|
|
||||||
Devices []*Device `json:"devices"`
|
|
||||||
|
|
||||||
// Memory limit (in bytes)
|
// Memory limit (in bytes)
|
||||||
Memory int64 `json:"memory"`
|
Memory int64 `json:"memory"`
|
||||||
@ -124,7 +126,4 @@ type Resources struct {
|
|||||||
|
|
||||||
// CpuWeight sets a proportional bandwidth limit.
|
// CpuWeight sets a proportional bandwidth limit.
|
||||||
CpuWeight uint64 `json:"cpu_weight"`
|
CpuWeight uint64 `json:"cpu_weight"`
|
||||||
|
|
||||||
// CpuMax sets she maximum bandwidth limit (format: max period).
|
|
||||||
CpuMax string `json:"cpu_max"`
|
|
||||||
}
|
}
|
||||||
|
96
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
96
vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
generated
vendored
@ -8,7 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
"github.com/opencontainers/runtime-spec/specs-go"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,9 +70,10 @@ type Arg struct {
|
|||||||
|
|
||||||
// Syscall is a rule to match a syscall in Seccomp
|
// Syscall is a rule to match a syscall in Seccomp
|
||||||
type Syscall struct {
|
type Syscall struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Action Action `json:"action"`
|
Action Action `json:"action"`
|
||||||
Args []*Arg `json:"args"`
|
ErrnoRet *uint `json:"errnoRet"`
|
||||||
|
Args []*Arg `json:"args"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Windows. Many of these fields should be factored out into those parts
|
// TODO Windows. Many of these fields should be factored out into those parts
|
||||||
@ -175,7 +176,7 @@ type Config struct {
|
|||||||
|
|
||||||
// Hooks are a collection of actions to perform at various container lifecycle events.
|
// Hooks are a collection of actions to perform at various container lifecycle events.
|
||||||
// CommandHooks are serialized to JSON, but other hooks are not.
|
// CommandHooks are serialized to JSON, but other hooks are not.
|
||||||
Hooks *Hooks
|
Hooks Hooks
|
||||||
|
|
||||||
// Version is the version of opencontainer specification that is supported.
|
// Version is the version of opencontainer specification that is supported.
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
@ -202,17 +203,50 @@ type Config struct {
|
|||||||
RootlessCgroups bool `json:"rootless_cgroups,omitempty"`
|
RootlessCgroups bool `json:"rootless_cgroups,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Hooks struct {
|
type HookName string
|
||||||
|
type HookList []Hook
|
||||||
|
type Hooks map[HookName]HookList
|
||||||
|
|
||||||
|
const (
|
||||||
// Prestart commands are executed after the container namespaces are created,
|
// Prestart commands are executed after the container namespaces are created,
|
||||||
// but before the user supplied command is executed from init.
|
// but before the user supplied command is executed from init.
|
||||||
Prestart []Hook
|
// Note: This hook is now deprecated
|
||||||
|
// Prestart commands are called in the Runtime namespace.
|
||||||
|
Prestart HookName = "prestart"
|
||||||
|
|
||||||
|
// CreateRuntime commands MUST be called as part of the create operation after
|
||||||
|
// the runtime environment has been created but before the pivot_root has been executed.
|
||||||
|
// CreateRuntime is called immediately after the deprecated Prestart hook.
|
||||||
|
// CreateRuntime commands are called in the Runtime Namespace.
|
||||||
|
CreateRuntime = "createRuntime"
|
||||||
|
|
||||||
|
// CreateContainer commands MUST be called as part of the create operation after
|
||||||
|
// the runtime environment has been created but before the pivot_root has been executed.
|
||||||
|
// CreateContainer commands are called in the Container namespace.
|
||||||
|
CreateContainer = "createContainer"
|
||||||
|
|
||||||
|
// StartContainer commands MUST be called as part of the start operation and before
|
||||||
|
// the container process is started.
|
||||||
|
// StartContainer commands are called in the Container namespace.
|
||||||
|
StartContainer = "startContainer"
|
||||||
|
|
||||||
// Poststart commands are executed after the container init process starts.
|
// Poststart commands are executed after the container init process starts.
|
||||||
Poststart []Hook
|
// Poststart commands are called in the Runtime Namespace.
|
||||||
|
Poststart = "poststart"
|
||||||
|
|
||||||
// Poststop commands are executed after the container init process exits.
|
// Poststop commands are executed after the container init process exits.
|
||||||
Poststop []Hook
|
// Poststop commands are called in the Runtime Namespace.
|
||||||
}
|
Poststop = "poststop"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO move this to runtime-spec
|
||||||
|
// See: https://github.com/opencontainers/runtime-spec/pull/1046
|
||||||
|
const (
|
||||||
|
Creating = "creating"
|
||||||
|
Created = "created"
|
||||||
|
Running = "running"
|
||||||
|
Stopped = "stopped"
|
||||||
|
)
|
||||||
|
|
||||||
type Capabilities struct {
|
type Capabilities struct {
|
||||||
// Bounding is the set of capabilities checked by the kernel.
|
// Bounding is the set of capabilities checked by the kernel.
|
||||||
@ -227,32 +261,39 @@ type Capabilities struct {
|
|||||||
Ambient []string
|
Ambient []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hooks *Hooks) UnmarshalJSON(b []byte) error {
|
func (hooks HookList) RunHooks(state *specs.State) error {
|
||||||
var state struct {
|
for i, h := range hooks {
|
||||||
Prestart []CommandHook
|
if err := h.Run(state); err != nil {
|
||||||
Poststart []CommandHook
|
return errors.Wrapf(err, "Running hook #%d:", i)
|
||||||
Poststop []CommandHook
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hooks *Hooks) UnmarshalJSON(b []byte) error {
|
||||||
|
var state map[HookName][]CommandHook
|
||||||
|
|
||||||
if err := json.Unmarshal(b, &state); err != nil {
|
if err := json.Unmarshal(b, &state); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize := func(shooks []CommandHook) (hooks []Hook) {
|
*hooks = Hooks{}
|
||||||
for _, shook := range shooks {
|
for n, commandHooks := range state {
|
||||||
hooks = append(hooks, shook)
|
if len(commandHooks) == 0 {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
return hooks
|
(*hooks)[n] = HookList{}
|
||||||
|
for _, h := range commandHooks {
|
||||||
|
(*hooks)[n] = append((*hooks)[n], h)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.Prestart = deserialize(state.Prestart)
|
|
||||||
hooks.Poststart = deserialize(state.Poststart)
|
|
||||||
hooks.Poststop = deserialize(state.Poststop)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hooks Hooks) MarshalJSON() ([]byte, error) {
|
func (hooks *Hooks) MarshalJSON() ([]byte, error) {
|
||||||
serialize := func(hooks []Hook) (serializableHooks []CommandHook) {
|
serialize := func(hooks []Hook) (serializableHooks []CommandHook) {
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
switch chook := hook.(type) {
|
switch chook := hook.(type) {
|
||||||
@ -267,9 +308,12 @@ func (hooks Hooks) MarshalJSON() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return json.Marshal(map[string]interface{}{
|
return json.Marshal(map[string]interface{}{
|
||||||
"prestart": serialize(hooks.Prestart),
|
"prestart": serialize((*hooks)[Prestart]),
|
||||||
"poststart": serialize(hooks.Poststart),
|
"createRuntime": serialize((*hooks)[CreateRuntime]),
|
||||||
"poststop": serialize(hooks.Poststop),
|
"createContainer": serialize((*hooks)[CreateContainer]),
|
||||||
|
"startContainer": serialize((*hooks)[StartContainer]),
|
||||||
|
"poststart": serialize((*hooks)[Poststart]),
|
||||||
|
"poststop": serialize((*hooks)[Poststop]),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
175
vendor/github.com/opencontainers/runc/libcontainer/configs/device.go
generated
vendored
175
vendor/github.com/opencontainers/runc/libcontainer/configs/device.go
generated
vendored
@ -1,8 +1,12 @@
|
|||||||
package configs
|
package configs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -12,21 +16,11 @@ const (
|
|||||||
// TODO Windows: This can be factored out in the future
|
// TODO Windows: This can be factored out in the future
|
||||||
|
|
||||||
type Device struct {
|
type Device struct {
|
||||||
// Device type, block, char, etc.
|
DeviceRule
|
||||||
Type rune `json:"type"`
|
|
||||||
|
|
||||||
// Path to the device.
|
// Path to the device.
|
||||||
Path string `json:"path"`
|
Path string `json:"path"`
|
||||||
|
|
||||||
// Major is the device's major number.
|
|
||||||
Major int64 `json:"major"`
|
|
||||||
|
|
||||||
// Minor is the device's minor number.
|
|
||||||
Minor int64 `json:"minor"`
|
|
||||||
|
|
||||||
// Cgroup permissions format, rwm.
|
|
||||||
Permissions string `json:"permissions"`
|
|
||||||
|
|
||||||
// FileMode permission bits for the device.
|
// FileMode permission bits for the device.
|
||||||
FileMode os.FileMode `json:"file_mode"`
|
FileMode os.FileMode `json:"file_mode"`
|
||||||
|
|
||||||
@ -35,23 +29,154 @@ type Device struct {
|
|||||||
|
|
||||||
// Gid of the device.
|
// Gid of the device.
|
||||||
Gid uint32 `json:"gid"`
|
Gid uint32 `json:"gid"`
|
||||||
|
}
|
||||||
|
|
||||||
// Write the file to the allowed list
|
// DevicePermissions is a cgroupv1-style string to represent device access. It
|
||||||
|
// has to be a string for backward compatibility reasons, hence why it has
|
||||||
|
// methods to do set operations.
|
||||||
|
type DevicePermissions string
|
||||||
|
|
||||||
|
const (
|
||||||
|
deviceRead uint = (1 << iota)
|
||||||
|
deviceWrite
|
||||||
|
deviceMknod
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p DevicePermissions) toSet() uint {
|
||||||
|
var set uint
|
||||||
|
for _, perm := range p {
|
||||||
|
switch perm {
|
||||||
|
case 'r':
|
||||||
|
set |= deviceRead
|
||||||
|
case 'w':
|
||||||
|
set |= deviceWrite
|
||||||
|
case 'm':
|
||||||
|
set |= deviceMknod
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
|
func fromSet(set uint) DevicePermissions {
|
||||||
|
var perm string
|
||||||
|
if set&deviceRead == deviceRead {
|
||||||
|
perm += "r"
|
||||||
|
}
|
||||||
|
if set&deviceWrite == deviceWrite {
|
||||||
|
perm += "w"
|
||||||
|
}
|
||||||
|
if set&deviceMknod == deviceMknod {
|
||||||
|
perm += "m"
|
||||||
|
}
|
||||||
|
return DevicePermissions(perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union returns the union of the two sets of DevicePermissions.
|
||||||
|
func (p DevicePermissions) Union(o DevicePermissions) DevicePermissions {
|
||||||
|
lhs := p.toSet()
|
||||||
|
rhs := o.toSet()
|
||||||
|
return fromSet(lhs | rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Difference returns the set difference of the two sets of DevicePermissions.
|
||||||
|
// In set notation, A.Difference(B) gives you A\B.
|
||||||
|
func (p DevicePermissions) Difference(o DevicePermissions) DevicePermissions {
|
||||||
|
lhs := p.toSet()
|
||||||
|
rhs := o.toSet()
|
||||||
|
return fromSet(lhs &^ rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intersection computes the intersection of the two sets of DevicePermissions.
|
||||||
|
func (p DevicePermissions) Intersection(o DevicePermissions) DevicePermissions {
|
||||||
|
lhs := p.toSet()
|
||||||
|
rhs := o.toSet()
|
||||||
|
return fromSet(lhs & rhs)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsEmpty returns whether the set of permissions in a DevicePermissions is
|
||||||
|
// empty.
|
||||||
|
func (p DevicePermissions) IsEmpty() bool {
|
||||||
|
return p == DevicePermissions("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsValid returns whether the set of permissions is a subset of valid
|
||||||
|
// permissions (namely, {r,w,m}).
|
||||||
|
func (p DevicePermissions) IsValid() bool {
|
||||||
|
return p == fromSet(p.toSet())
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceType rune
|
||||||
|
|
||||||
|
const (
|
||||||
|
WildcardDevice DeviceType = 'a'
|
||||||
|
BlockDevice DeviceType = 'b'
|
||||||
|
CharDevice DeviceType = 'c' // or 'u'
|
||||||
|
FifoDevice DeviceType = 'p'
|
||||||
|
)
|
||||||
|
|
||||||
|
func (t DeviceType) IsValid() bool {
|
||||||
|
switch t {
|
||||||
|
case WildcardDevice, BlockDevice, CharDevice, FifoDevice:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t DeviceType) CanMknod() bool {
|
||||||
|
switch t {
|
||||||
|
case BlockDevice, CharDevice, FifoDevice:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t DeviceType) CanCgroup() bool {
|
||||||
|
switch t {
|
||||||
|
case WildcardDevice, BlockDevice, CharDevice:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceRule struct {
|
||||||
|
// Type of device ('c' for char, 'b' for block). If set to 'a', this rule
|
||||||
|
// acts as a wildcard and all fields other than Allow are ignored.
|
||||||
|
Type DeviceType `json:"type"`
|
||||||
|
|
||||||
|
// Major is the device's major number.
|
||||||
|
Major int64 `json:"major"`
|
||||||
|
|
||||||
|
// Minor is the device's minor number.
|
||||||
|
Minor int64 `json:"minor"`
|
||||||
|
|
||||||
|
// Permissions is the set of permissions that this rule applies to (in the
|
||||||
|
// cgroupv1 format -- any combination of "rwm").
|
||||||
|
Permissions DevicePermissions `json:"permissions"`
|
||||||
|
|
||||||
|
// Allow specifies whether this rule is allowed.
|
||||||
Allow bool `json:"allow"`
|
Allow bool `json:"allow"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Device) CgroupString() string {
|
func (d *DeviceRule) CgroupString() string {
|
||||||
return fmt.Sprintf("%c %s:%s %s", d.Type, deviceNumberString(d.Major), deviceNumberString(d.Minor), d.Permissions)
|
var (
|
||||||
}
|
major = strconv.FormatInt(d.Major, 10)
|
||||||
|
minor = strconv.FormatInt(d.Minor, 10)
|
||||||
func (d *Device) Mkdev() int {
|
)
|
||||||
return int((d.Major << 8) | (d.Minor & 0xff) | ((d.Minor & 0xfff00) << 12))
|
if d.Major == Wildcard {
|
||||||
}
|
major = "*"
|
||||||
|
|
||||||
// deviceNumberString converts the device number to a string return result.
|
|
||||||
func deviceNumberString(number int64) string {
|
|
||||||
if number == Wildcard {
|
|
||||||
return "*"
|
|
||||||
}
|
}
|
||||||
return fmt.Sprint(number)
|
if d.Minor == Wildcard {
|
||||||
|
minor = "*"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%c %s:%s %s", d.Type, major, minor, d.Permissions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DeviceRule) Mkdev() (uint64, error) {
|
||||||
|
if d.Major == Wildcard || d.Minor == Wildcard {
|
||||||
|
return 0, errors.New("cannot mkdev() device with wildcards")
|
||||||
|
}
|
||||||
|
return unix.Mkdev(uint32(d.Major), uint32(d.Minor)), nil
|
||||||
}
|
}
|
||||||
|
111
vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go
generated
vendored
111
vendor/github.com/opencontainers/runc/libcontainer/configs/device_defaults.go
generated
vendored
@ -1,111 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
package configs
|
|
||||||
|
|
||||||
var (
|
|
||||||
// DefaultSimpleDevices are devices that are to be both allowed and created.
|
|
||||||
DefaultSimpleDevices = []*Device{
|
|
||||||
// /dev/null and zero
|
|
||||||
{
|
|
||||||
Path: "/dev/null",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 1,
|
|
||||||
Minor: 3,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Path: "/dev/zero",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 1,
|
|
||||||
Minor: 5,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
Path: "/dev/full",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 1,
|
|
||||||
Minor: 7,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
|
|
||||||
// consoles and ttys
|
|
||||||
{
|
|
||||||
Path: "/dev/tty",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 5,
|
|
||||||
Minor: 0,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
|
|
||||||
// /dev/urandom,/dev/random
|
|
||||||
{
|
|
||||||
Path: "/dev/urandom",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 1,
|
|
||||||
Minor: 9,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Path: "/dev/random",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 1,
|
|
||||||
Minor: 8,
|
|
||||||
Permissions: "rwm",
|
|
||||||
FileMode: 0666,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
DefaultAllowedDevices = append([]*Device{
|
|
||||||
// allow mknod for any device
|
|
||||||
{
|
|
||||||
Type: 'c',
|
|
||||||
Major: Wildcard,
|
|
||||||
Minor: Wildcard,
|
|
||||||
Permissions: "m",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Type: 'b',
|
|
||||||
Major: Wildcard,
|
|
||||||
Minor: Wildcard,
|
|
||||||
Permissions: "m",
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
Path: "/dev/console",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 5,
|
|
||||||
Minor: 1,
|
|
||||||
Permissions: "rwm",
|
|
||||||
},
|
|
||||||
// /dev/pts/ - pts namespaces are "coming soon"
|
|
||||||
{
|
|
||||||
Path: "",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 136,
|
|
||||||
Minor: Wildcard,
|
|
||||||
Permissions: "rwm",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Path: "",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 5,
|
|
||||||
Minor: 2,
|
|
||||||
Permissions: "rwm",
|
|
||||||
},
|
|
||||||
|
|
||||||
// tuntap
|
|
||||||
{
|
|
||||||
Path: "",
|
|
||||||
Type: 'c',
|
|
||||||
Major: 10,
|
|
||||||
Minor: 200,
|
|
||||||
Permissions: "rwm",
|
|
||||||
},
|
|
||||||
}, DefaultSimpleDevices...)
|
|
||||||
DefaultAutoCreatedDevices = append([]*Device{}, DefaultSimpleDevices...)
|
|
||||||
)
|
|
36
vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go
generated
vendored
36
vendor/github.com/opencontainers/runc/libcontainer/devices/devices.go
generated
vendored
@ -31,33 +31,33 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
devType configs.DeviceType
|
||||||
|
mode = stat.Mode
|
||||||
devNumber = uint64(stat.Rdev)
|
devNumber = uint64(stat.Rdev)
|
||||||
major = unix.Major(devNumber)
|
major = unix.Major(devNumber)
|
||||||
minor = unix.Minor(devNumber)
|
minor = unix.Minor(devNumber)
|
||||||
)
|
)
|
||||||
if major == 0 {
|
|
||||||
return nil, ErrNotADevice
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
devType rune
|
|
||||||
mode = stat.Mode
|
|
||||||
)
|
|
||||||
switch {
|
switch {
|
||||||
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
case mode&unix.S_IFBLK == unix.S_IFBLK:
|
||||||
devType = 'b'
|
devType = configs.BlockDevice
|
||||||
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
case mode&unix.S_IFCHR == unix.S_IFCHR:
|
||||||
devType = 'c'
|
devType = configs.CharDevice
|
||||||
|
case mode&unix.S_IFIFO == unix.S_IFIFO:
|
||||||
|
devType = configs.FifoDevice
|
||||||
|
default:
|
||||||
|
return nil, ErrNotADevice
|
||||||
}
|
}
|
||||||
return &configs.Device{
|
return &configs.Device{
|
||||||
Type: devType,
|
DeviceRule: configs.DeviceRule{
|
||||||
Path: path,
|
Type: devType,
|
||||||
Major: int64(major),
|
Major: int64(major),
|
||||||
Minor: int64(minor),
|
Minor: int64(minor),
|
||||||
Permissions: permissions,
|
Permissions: configs.DevicePermissions(permissions),
|
||||||
FileMode: os.FileMode(mode),
|
},
|
||||||
Uid: stat.Uid,
|
Path: path,
|
||||||
Gid: stat.Gid,
|
FileMode: os.FileMode(mode),
|
||||||
|
Uid: stat.Uid,
|
||||||
|
Gid: stat.Gid,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
28
vendor/github.com/opencontainers/runc/libcontainer/nsenter/cloned_binary.c
generated
vendored
28
vendor/github.com/opencontainers/runc/libcontainer/nsenter/cloned_binary.c
generated
vendored
@ -1,7 +1,14 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
|
* Copyright (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
|
||||||
* Copyright (C) 2019 SUSE LLC
|
* Copyright (C) 2019 SUSE LLC
|
||||||
*
|
*
|
||||||
|
* This work is dual licensed under the following licenses. You may use,
|
||||||
|
* redistribute, and/or modify the work under the conditions of either (or
|
||||||
|
* both) licenses.
|
||||||
|
*
|
||||||
|
* === Apache-2.0 ===
|
||||||
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
@ -13,6 +20,23 @@
|
|||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* === LGPL-2.1-or-later ===
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library. If not, see
|
||||||
|
* <https://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
@ -95,8 +119,10 @@ static int is_self_cloned(void)
|
|||||||
struct statfs fsbuf = {};
|
struct statfs fsbuf = {};
|
||||||
|
|
||||||
fd = open("/proc/self/exe", O_RDONLY|O_CLOEXEC);
|
fd = open("/proc/self/exe", O_RDONLY|O_CLOEXEC);
|
||||||
if (fd < 0)
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "you have no read access to runc binary file\n");
|
||||||
return -ENOTRECOVERABLE;
|
return -ENOTRECOVERABLE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is the binary a fully-sealed memfd? We don't need CLONED_BINARY_ENV for
|
* Is the binary a fully-sealed memfd? We don't need CLONED_BINARY_ENV for
|
||||||
|
12
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
12
vendor/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
generated
vendored
@ -714,12 +714,12 @@ void nsexec(void)
|
|||||||
* ready, so we can receive all possible error codes
|
* ready, so we can receive all possible error codes
|
||||||
* generated by children.
|
* generated by children.
|
||||||
*/
|
*/
|
||||||
|
syncfd = sync_child_pipe[1];
|
||||||
|
close(sync_child_pipe[0]);
|
||||||
|
|
||||||
while (!ready) {
|
while (!ready) {
|
||||||
enum sync_t s;
|
enum sync_t s;
|
||||||
|
|
||||||
syncfd = sync_child_pipe[1];
|
|
||||||
close(sync_child_pipe[0]);
|
|
||||||
|
|
||||||
if (read(syncfd, &s, sizeof(s)) != sizeof(s))
|
if (read(syncfd, &s, sizeof(s)) != sizeof(s))
|
||||||
bail("failed to sync with child: next state");
|
bail("failed to sync with child: next state");
|
||||||
|
|
||||||
@ -789,13 +789,13 @@ void nsexec(void)
|
|||||||
|
|
||||||
/* Now sync with grandchild. */
|
/* Now sync with grandchild. */
|
||||||
|
|
||||||
|
syncfd = sync_grandchild_pipe[1];
|
||||||
|
close(sync_grandchild_pipe[0]);
|
||||||
|
|
||||||
ready = false;
|
ready = false;
|
||||||
while (!ready) {
|
while (!ready) {
|
||||||
enum sync_t s;
|
enum sync_t s;
|
||||||
|
|
||||||
syncfd = sync_grandchild_pipe[1];
|
|
||||||
close(sync_grandchild_pipe[0]);
|
|
||||||
|
|
||||||
s = SYNC_GRANDCHILD;
|
s = SYNC_GRANDCHILD;
|
||||||
if (write(syncfd, &s, sizeof(s)) != sizeof(s)) {
|
if (write(syncfd, &s, sizeof(s)) != sizeof(s)) {
|
||||||
kill(child, SIGKILL);
|
kill(child, SIGKILL);
|
||||||
|
29
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
generated
vendored
29
vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
generated
vendored
@ -4,6 +4,7 @@ package seccomp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@ -34,12 +35,12 @@ const (
|
|||||||
// of the init until they join the namespace
|
// of the init until they join the namespace
|
||||||
func InitSeccomp(config *configs.Seccomp) error {
|
func InitSeccomp(config *configs.Seccomp) error {
|
||||||
if config == nil {
|
if config == nil {
|
||||||
return fmt.Errorf("cannot initialize Seccomp - nil config passed")
|
return errors.New("cannot initialize Seccomp - nil config passed")
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultAction, err := getAction(config.DefaultAction)
|
defaultAction, err := getAction(config.DefaultAction, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error initializing seccomp - invalid default action")
|
return errors.New("error initializing seccomp - invalid default action")
|
||||||
}
|
}
|
||||||
|
|
||||||
filter, err := libseccomp.NewFilter(defaultAction)
|
filter, err := libseccomp.NewFilter(defaultAction)
|
||||||
@ -67,7 +68,7 @@ func InitSeccomp(config *configs.Seccomp) error {
|
|||||||
// Add a rule for each syscall
|
// Add a rule for each syscall
|
||||||
for _, call := range config.Syscalls {
|
for _, call := range config.Syscalls {
|
||||||
if call == nil {
|
if call == nil {
|
||||||
return fmt.Errorf("encountered nil syscall while initializing Seccomp")
|
return errors.New("encountered nil syscall while initializing Seccomp")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = matchCall(filter, call); err != nil {
|
if err = matchCall(filter, call); err != nil {
|
||||||
@ -101,22 +102,28 @@ func IsEnabled() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert Libcontainer Action to Libseccomp ScmpAction
|
// Convert Libcontainer Action to Libseccomp ScmpAction
|
||||||
func getAction(act configs.Action) (libseccomp.ScmpAction, error) {
|
func getAction(act configs.Action, errnoRet *uint) (libseccomp.ScmpAction, error) {
|
||||||
switch act {
|
switch act {
|
||||||
case configs.Kill:
|
case configs.Kill:
|
||||||
return actKill, nil
|
return actKill, nil
|
||||||
case configs.Errno:
|
case configs.Errno:
|
||||||
|
if errnoRet != nil {
|
||||||
|
return libseccomp.ActErrno.SetReturnCode(int16(*errnoRet)), nil
|
||||||
|
}
|
||||||
return actErrno, nil
|
return actErrno, nil
|
||||||
case configs.Trap:
|
case configs.Trap:
|
||||||
return actTrap, nil
|
return actTrap, nil
|
||||||
case configs.Allow:
|
case configs.Allow:
|
||||||
return actAllow, nil
|
return actAllow, nil
|
||||||
case configs.Trace:
|
case configs.Trace:
|
||||||
|
if errnoRet != nil {
|
||||||
|
return libseccomp.ActTrace.SetReturnCode(int16(*errnoRet)), nil
|
||||||
|
}
|
||||||
return actTrace, nil
|
return actTrace, nil
|
||||||
case configs.Log:
|
case configs.Log:
|
||||||
return actLog, nil
|
return actLog, nil
|
||||||
default:
|
default:
|
||||||
return libseccomp.ActInvalid, fmt.Errorf("invalid action, cannot use in rule")
|
return libseccomp.ActInvalid, errors.New("invalid action, cannot use in rule")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +145,7 @@ func getOperator(op configs.Operator) (libseccomp.ScmpCompareOp, error) {
|
|||||||
case configs.MaskEqualTo:
|
case configs.MaskEqualTo:
|
||||||
return libseccomp.CompareMaskedEqual, nil
|
return libseccomp.CompareMaskedEqual, nil
|
||||||
default:
|
default:
|
||||||
return libseccomp.CompareInvalid, fmt.Errorf("invalid operator, cannot use in rule")
|
return libseccomp.CompareInvalid, errors.New("invalid operator, cannot use in rule")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,7 +154,7 @@ func getCondition(arg *configs.Arg) (libseccomp.ScmpCondition, error) {
|
|||||||
cond := libseccomp.ScmpCondition{}
|
cond := libseccomp.ScmpCondition{}
|
||||||
|
|
||||||
if arg == nil {
|
if arg == nil {
|
||||||
return cond, fmt.Errorf("cannot convert nil to syscall condition")
|
return cond, errors.New("cannot convert nil to syscall condition")
|
||||||
}
|
}
|
||||||
|
|
||||||
op, err := getOperator(arg.Op)
|
op, err := getOperator(arg.Op)
|
||||||
@ -161,11 +168,11 @@ func getCondition(arg *configs.Arg) (libseccomp.ScmpCondition, error) {
|
|||||||
// Add a rule to match a single syscall
|
// Add a rule to match a single syscall
|
||||||
func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error {
|
func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error {
|
||||||
if call == nil || filter == nil {
|
if call == nil || filter == nil {
|
||||||
return fmt.Errorf("cannot use nil as syscall to block")
|
return errors.New("cannot use nil as syscall to block")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(call.Name) == 0 {
|
if len(call.Name) == 0 {
|
||||||
return fmt.Errorf("empty string is not a valid syscall")
|
return errors.New("empty string is not a valid syscall")
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we can't resolve the syscall, assume it's not supported on this kernel
|
// If we can't resolve the syscall, assume it's not supported on this kernel
|
||||||
@ -176,7 +183,7 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert the call's action to the libseccomp equivalent
|
// Convert the call's action to the libseccomp equivalent
|
||||||
callAct, err := getAction(call.Action)
|
callAct, err := getAction(call.Action, call.ErrnoRet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("action in seccomp profile is invalid: %s", err)
|
return fmt.Errorf("action in seccomp profile is invalid: %s", err)
|
||||||
}
|
}
|
||||||
|
28
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
28
vendor/github.com/opencontainers/runc/libcontainer/user/user.go
generated
vendored
@ -162,10 +162,6 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
line := strings.TrimSpace(s.Text())
|
line := strings.TrimSpace(s.Text())
|
||||||
if line == "" {
|
if line == "" {
|
||||||
continue
|
continue
|
||||||
@ -183,6 +179,9 @@ func ParsePasswdFilter(r io.Reader, filter func(User) bool) ([]User, error) {
|
|||||||
out = append(out, p)
|
out = append(out, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
@ -221,10 +220,6 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
text := s.Text()
|
text := s.Text()
|
||||||
if text == "" {
|
if text == "" {
|
||||||
continue
|
continue
|
||||||
@ -242,6 +237,9 @@ func ParseGroupFilter(r io.Reader, filter func(Group) bool) ([]Group, error) {
|
|||||||
out = append(out, p)
|
out = append(out, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
@ -532,10 +530,6 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
line := strings.TrimSpace(s.Text())
|
line := strings.TrimSpace(s.Text())
|
||||||
if line == "" {
|
if line == "" {
|
||||||
continue
|
continue
|
||||||
@ -549,6 +543,9 @@ func ParseSubIDFilter(r io.Reader, filter func(SubID) bool) ([]SubID, error) {
|
|||||||
out = append(out, p)
|
out = append(out, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
@ -586,10 +583,6 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
for s.Scan() {
|
for s.Scan() {
|
||||||
if err := s.Err(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
line := strings.TrimSpace(s.Text())
|
line := strings.TrimSpace(s.Text())
|
||||||
if line == "" {
|
if line == "" {
|
||||||
continue
|
continue
|
||||||
@ -603,6 +596,9 @@ func ParseIDMapFilter(r io.Reader, filter func(IDMap) bool) ([]IDMap, error) {
|
|||||||
out = append(out, p)
|
out = append(out, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := s.Err(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
31
vendor/github.com/opencontainers/runc/vendor.conf
generated
vendored
31
vendor/github.com/opencontainers/runc/vendor.conf
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
# OCI runtime-spec. When updating this, make sure you use a version tag rather
|
|
||||||
# than a commit ID so it's much more obvious what version of the spec we are
|
|
||||||
# using.
|
|
||||||
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db
|
|
||||||
|
|
||||||
# Core libcontainer functionality.
|
|
||||||
github.com/checkpoint-restore/go-criu 17b0214f6c48980c45dc47ecb0cfd6d9e02df723 # v3.11
|
|
||||||
github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7
|
|
||||||
github.com/opencontainers/selinux 5215b1806f52b1fcc2070a8826c542c9d33cd3cf # v1.3.0 (+ CVE-2019-16884)
|
|
||||||
github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1
|
|
||||||
github.com/sirupsen/logrus 8bdbc7bcc01dcbb8ec23dc8a28e332258d25251f # v1.4.1
|
|
||||||
github.com/syndtr/gocapability d98352740cb2c55f81556b63d4a1ec64c5a319c2
|
|
||||||
github.com/vishvananda/netlink 1e2e08e8a2dcdacaae3f14ac44c5cfa31361f270
|
|
||||||
|
|
||||||
# systemd integration.
|
|
||||||
github.com/coreos/go-systemd 95778dfbb74eb7e4dbaf43bf7d71809650ef8076 # v19
|
|
||||||
github.com/godbus/dbus 2ff6f7ffd60f0f2410b3105864bdd12c7894f844 # v5.0.1
|
|
||||||
github.com/golang/protobuf 925541529c1fa6821df4e44ce2723319eb2be768 # v1.0.0
|
|
||||||
|
|
||||||
# Command-line interface.
|
|
||||||
github.com/cyphar/filepath-securejoin a261ee33d7a517f054effbf451841abaafe3e0fd # v0.2.2
|
|
||||||
github.com/docker/go-units 47565b4f722fb6ceae66b95f853feed578a4a51c # v0.3.3
|
|
||||||
github.com/urfave/cli cfb38830724cc34fedffe9a2a29fb54fa9169cd1 # v1.20.0
|
|
||||||
golang.org/x/sys 9eafafc0a87e0fd0aeeba439a4573537970c44c7 https://github.com/golang/sys
|
|
||||||
|
|
||||||
# console dependencies
|
|
||||||
github.com/containerd/console 0650fd9eeb50bab4fc99dceb9f2e14cf58f36e7f
|
|
||||||
github.com/pkg/errors ba968bfe8b2f7e042a574c888954fccecfa385b4 # v0.8.1
|
|
||||||
|
|
||||||
# ebpf dependencies
|
|
||||||
github.com/cilium/ebpf 95b36a581eed7b0f127306ed1d16cc0ddc06cf67
|
|
7
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
7
vendor/github.com/opencontainers/runtime-spec/specs-go/config.go
generated
vendored
@ -667,9 +667,10 @@ type LinuxSeccompArg struct {
|
|||||||
|
|
||||||
// LinuxSyscall is used to match a syscall in Seccomp
|
// LinuxSyscall is used to match a syscall in Seccomp
|
||||||
type LinuxSyscall struct {
|
type LinuxSyscall struct {
|
||||||
Names []string `json:"names"`
|
Names []string `json:"names"`
|
||||||
Action LinuxSeccompAction `json:"action"`
|
Action LinuxSeccompAction `json:"action"`
|
||||||
Args []LinuxSeccompArg `json:"args,omitempty"`
|
ErrnoRet *uint `json:"errnoRet,omitempty"`
|
||||||
|
Args []LinuxSeccompArg `json:"args,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
// LinuxIntelRdt has container runtime resource constraints for Intel RDT
|
||||||
|
2
vendor/github.com/opencontainers/runtime-spec/specs-go/version.go
generated
vendored
2
vendor/github.com/opencontainers/runtime-spec/specs-go/version.go
generated
vendored
@ -11,7 +11,7 @@ const (
|
|||||||
VersionPatch = 2
|
VersionPatch = 2
|
||||||
|
|
||||||
// VersionDev indicates development branch. Releases will be empty string.
|
// VersionDev indicates development branch. Releases will be empty string.
|
||||||
VersionDev = ""
|
VersionDev = "-dev"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version is the specification version that the package types support.
|
// Version is the specification version that the package types support.
|
||||||
|
22
vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
generated
vendored
22
vendor/github.com/opencontainers/selinux/go-selinux/label/label.go
generated
vendored
@ -1,8 +1,6 @@
|
|||||||
package label
|
package label
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/opencontainers/selinux/go-selinux"
|
"github.com/opencontainers/selinux/go-selinux"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -48,7 +46,7 @@ var PidLabel = selinux.PidLabel
|
|||||||
|
|
||||||
// Init initialises the labeling system
|
// Init initialises the labeling system
|
||||||
func Init() {
|
func Init() {
|
||||||
_ = selinux.GetEnabled()
|
selinux.GetEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearLabels will clear all reserved labels
|
// ClearLabels will clear all reserved labels
|
||||||
@ -77,21 +75,3 @@ func ReleaseLabel(label string) error {
|
|||||||
// can be used to set duplicate labels on future container processes
|
// can be used to set duplicate labels on future container processes
|
||||||
// Deprecated: use selinux.DupSecOpt
|
// Deprecated: use selinux.DupSecOpt
|
||||||
var DupSecOpt = selinux.DupSecOpt
|
var DupSecOpt = selinux.DupSecOpt
|
||||||
|
|
||||||
// FormatMountLabel returns a string to be used by the mount command.
|
|
||||||
// The format of this string will be used to alter the labeling of the mountpoint.
|
|
||||||
// The string returned is suitable to be used as the options field of the mount command.
|
|
||||||
// If you need to have additional mount point options, you can pass them in as
|
|
||||||
// the first parameter. Second parameter is the label that you wish to apply
|
|
||||||
// to all content in the mount point.
|
|
||||||
func FormatMountLabel(src, mountLabel string) string {
|
|
||||||
if mountLabel != "" {
|
|
||||||
switch src {
|
|
||||||
case "":
|
|
||||||
src = fmt.Sprintf("context=%q", mountLabel)
|
|
||||||
default:
|
|
||||||
src = fmt.Sprintf("%s,context=%q", src, mountLabel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return src
|
|
||||||
}
|
|
||||||
|
32
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
generated
vendored
32
vendor/github.com/opencontainers/selinux/go-selinux/label/label_selinux.go
generated
vendored
@ -3,6 +3,7 @@
|
|||||||
package label
|
package label
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/user"
|
"os/user"
|
||||||
"strings"
|
"strings"
|
||||||
@ -42,7 +43,7 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
mcsLevel := pcon["level"]
|
|
||||||
mcon, err := selinux.NewContext(mountLabel)
|
mcon, err := selinux.NewContext(mountLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
@ -61,21 +62,16 @@ func InitLabels(options []string) (plabel string, mlabel string, Err error) {
|
|||||||
}
|
}
|
||||||
if con[0] == "filetype" {
|
if con[0] == "filetype" {
|
||||||
mcon["type"] = con[1]
|
mcon["type"] = con[1]
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
pcon[con[0]] = con[1]
|
pcon[con[0]] = con[1]
|
||||||
if con[0] == "level" || con[0] == "user" {
|
if con[0] == "level" || con[0] == "user" {
|
||||||
mcon[con[0]] = con[1]
|
mcon[con[0]] = con[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if pcon.Get() != processLabel {
|
selinux.ReleaseLabel(processLabel)
|
||||||
if pcon["level"] != mcsLevel {
|
processLabel = pcon.Get()
|
||||||
selinux.ReleaseLabel(processLabel)
|
|
||||||
}
|
|
||||||
processLabel = pcon.Get()
|
|
||||||
selinux.ReserveLabel(processLabel)
|
|
||||||
}
|
|
||||||
mountLabel = mcon.Get()
|
mountLabel = mcon.Get()
|
||||||
|
selinux.ReserveLabel(processLabel)
|
||||||
}
|
}
|
||||||
return processLabel, mountLabel, nil
|
return processLabel, mountLabel, nil
|
||||||
}
|
}
|
||||||
@ -86,6 +82,24 @@ func GenLabels(options string) (string, string, error) {
|
|||||||
return InitLabels(strings.Fields(options))
|
return InitLabels(strings.Fields(options))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormatMountLabel returns a string to be used by the mount command.
|
||||||
|
// The format of this string will be used to alter the labeling of the mountpoint.
|
||||||
|
// The string returned is suitable to be used as the options field of the mount command.
|
||||||
|
// If you need to have additional mount point options, you can pass them in as
|
||||||
|
// the first parameter. Second parameter is the label that you wish to apply
|
||||||
|
// to all content in the mount point.
|
||||||
|
func FormatMountLabel(src, mountLabel string) string {
|
||||||
|
if mountLabel != "" {
|
||||||
|
switch src {
|
||||||
|
case "":
|
||||||
|
src = fmt.Sprintf("context=%q", mountLabel)
|
||||||
|
default:
|
||||||
|
src = fmt.Sprintf("%s,context=%q", src, mountLabel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
|
||||||
// SetFileLabel modifies the "path" label to the specified file label
|
// SetFileLabel modifies the "path" label to the specified file label
|
||||||
func SetFileLabel(path string, fileLabel string) error {
|
func SetFileLabel(path string, fileLabel string) error {
|
||||||
if !selinux.GetEnabled() || fileLabel == "" {
|
if !selinux.GetEnabled() || fileLabel == "" {
|
||||||
|
4
vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go
generated
vendored
4
vendor/github.com/opencontainers/selinux/go-selinux/label/label_stub.go
generated
vendored
@ -15,6 +15,10 @@ func GenLabels(options string) (string, string, error) {
|
|||||||
return "", "", nil
|
return "", "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func FormatMountLabel(src string, mountLabel string) string {
|
||||||
|
return src
|
||||||
|
}
|
||||||
|
|
||||||
func SetFileLabel(path string, fileLabel string) error {
|
func SetFileLabel(path string, fileLabel string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
8
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
8
vendor/github.com/opencontainers/selinux/go-selinux/selinux_linux.go
generated
vendored
@ -31,9 +31,6 @@ const (
|
|||||||
// Disabled constant to indicate SELinux is disabled
|
// Disabled constant to indicate SELinux is disabled
|
||||||
Disabled = -1
|
Disabled = -1
|
||||||
|
|
||||||
// DefaultCategoryRange is the upper bound on the category range
|
|
||||||
DefaultCategoryRange = uint32(1024)
|
|
||||||
|
|
||||||
contextFile = "/usr/share/containers/selinux/contexts"
|
contextFile = "/usr/share/containers/selinux/contexts"
|
||||||
selinuxDir = "/etc/selinux/"
|
selinuxDir = "/etc/selinux/"
|
||||||
selinuxConfig = selinuxDir + "config"
|
selinuxConfig = selinuxDir + "config"
|
||||||
@ -60,9 +57,6 @@ var (
|
|||||||
// InvalidLabel is returned when an invalid label is specified.
|
// InvalidLabel is returned when an invalid label is specified.
|
||||||
InvalidLabel = errors.New("Invalid Label")
|
InvalidLabel = errors.New("Invalid Label")
|
||||||
|
|
||||||
// CategoryRange allows the upper bound on the category range to be adjusted
|
|
||||||
CategoryRange = DefaultCategoryRange
|
|
||||||
|
|
||||||
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
|
assignRegex = regexp.MustCompile(`^([^=]+)=(.*)$`)
|
||||||
roFileLabel string
|
roFileLabel string
|
||||||
state = selinuxState{
|
state = selinuxState{
|
||||||
@ -796,7 +790,7 @@ func ContainerLabels() (processLabel string, fileLabel string) {
|
|||||||
func addMcs(processLabel, fileLabel string) (string, string) {
|
func addMcs(processLabel, fileLabel string) (string, string) {
|
||||||
scon, _ := NewContext(processLabel)
|
scon, _ := NewContext(processLabel)
|
||||||
if scon["level"] != "" {
|
if scon["level"] != "" {
|
||||||
mcs := uniqMcs(CategoryRange)
|
mcs := uniqMcs(1024)
|
||||||
scon["level"] = mcs
|
scon["level"] = mcs
|
||||||
processLabel = scon.Get()
|
processLabel = scon.Get()
|
||||||
scon, _ = NewContext(fileLabel)
|
scon, _ = NewContext(fileLabel)
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user