mirror of
https://github.com/opencontainers/runc.git
synced 2025-10-16 12:31:51 +08:00
cgroup2: port over eBPF device controller from crun
The implementation is based on https://github.com/containers/crun/blob/0.10.2/src/libcrun/ebpf.c Although ebpf.c is originally licensed under LGPL-3.0-or-later, the author Giuseppe Scrivano agreed to relicense the file in Apache License 2.0: https://github.com/opencontainers/runc/issues/2144#issuecomment-543116397 See libcontainer/cgroups/ebpf/devicefilter/devicefilter_test.go for tested configurations. Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
183
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
Normal file
183
vendor/github.com/cilium/ebpf/abi.go
generated
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
package ebpf
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// CollectionABI describes the interface of an eBPF collection.
|
||||
type CollectionABI struct {
|
||||
Maps map[string]*MapABI
|
||||
Programs map[string]*ProgramABI
|
||||
}
|
||||
|
||||
// CheckSpec verifies that all maps and programs mentioned
|
||||
// in the ABI are present in the spec.
|
||||
func (abi *CollectionABI) CheckSpec(cs *CollectionSpec) error {
|
||||
for name := range abi.Maps {
|
||||
if cs.Maps[name] == nil {
|
||||
return errors.Errorf("missing map %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
for name := range abi.Programs {
|
||||
if cs.Programs[name] == nil {
|
||||
return errors.Errorf("missing program %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check verifies that all items in a collection conform to this ABI.
|
||||
func (abi *CollectionABI) Check(coll *Collection) error {
|
||||
for name, mapABI := range abi.Maps {
|
||||
m := coll.Maps[name]
|
||||
if m == nil {
|
||||
return errors.Errorf("missing map %s", name)
|
||||
}
|
||||
if err := mapABI.Check(m); err != nil {
|
||||
return errors.Wrapf(err, "map %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
for name, progABI := range abi.Programs {
|
||||
p := coll.Programs[name]
|
||||
if p == nil {
|
||||
return errors.Errorf("missing program %s", name)
|
||||
}
|
||||
if err := progABI.Check(p); err != nil {
|
||||
return errors.Wrapf(err, "program %s", name)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// MapABI describes a Map.
|
||||
//
|
||||
// Use it to assert that a Map matches what your code expects.
|
||||
type MapABI struct {
|
||||
Type MapType
|
||||
KeySize uint32
|
||||
ValueSize uint32
|
||||
MaxEntries uint32
|
||||
InnerMap *MapABI
|
||||
}
|
||||
|
||||
func newMapABIFromSpec(spec *MapSpec) *MapABI {
|
||||
var inner *MapABI
|
||||
if spec.InnerMap != nil {
|
||||
inner = newMapABIFromSpec(spec.InnerMap)
|
||||
}
|
||||
|
||||
return &MapABI{
|
||||
spec.Type,
|
||||
spec.KeySize,
|
||||
spec.ValueSize,
|
||||
spec.MaxEntries,
|
||||
inner,
|
||||
}
|
||||
}
|
||||
|
||||
func newMapABIFromFd(fd *bpfFD) (*MapABI, error) {
|
||||
info, err := bpfGetMapInfoByFD(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mapType := MapType(info.mapType)
|
||||
if mapType == ArrayOfMaps || mapType == HashOfMaps {
|
||||
return nil, errors.New("can't get map info for nested maps")
|
||||
}
|
||||
|
||||
return &MapABI{
|
||||
mapType,
|
||||
info.keySize,
|
||||
info.valueSize,
|
||||
info.maxEntries,
|
||||
nil,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Check verifies that a Map conforms to the ABI.
|
||||
//
|
||||
// Members of ABI which have the zero value of their type are not checked.
|
||||
func (abi *MapABI) Check(m *Map) error {
|
||||
return abi.check(&m.abi)
|
||||
}
|
||||
|
||||
func (abi *MapABI) check(other *MapABI) error {
|
||||
if abi.Type != UnspecifiedMap && other.Type != abi.Type {
|
||||
return errors.Errorf("expected map type %s, have %s", abi.Type, other.Type)
|
||||
}
|
||||
if err := checkUint32("key size", abi.KeySize, other.KeySize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkUint32("value size", abi.ValueSize, other.ValueSize); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkUint32("max entries", abi.MaxEntries, other.MaxEntries); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if abi.InnerMap == nil {
|
||||
if abi.Type == ArrayOfMaps || abi.Type == HashOfMaps {
|
||||
return errors.New("missing inner map ABI")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
if other.InnerMap == nil {
|
||||
return errors.New("missing inner map")
|
||||
}
|
||||
|
||||
return errors.Wrap(abi.InnerMap.check(other.InnerMap), "inner map")
|
||||
}
|
||||
|
||||
// ProgramABI describes a Program.
|
||||
//
|
||||
// Use it to assert that a Program matches what your code expects.
|
||||
type ProgramABI struct {
|
||||
Type ProgramType
|
||||
}
|
||||
|
||||
func newProgramABIFromSpec(spec *ProgramSpec) *ProgramABI {
|
||||
return &ProgramABI{
|
||||
spec.Type,
|
||||
}
|
||||
}
|
||||
|
||||
func newProgramABIFromFd(fd *bpfFD) (*ProgramABI, error) {
|
||||
info, err := bpfGetProgInfoByFD(fd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newProgramABIFromInfo(info), nil
|
||||
}
|
||||
|
||||
func newProgramABIFromInfo(info *bpfProgInfo) *ProgramABI {
|
||||
return &ProgramABI{
|
||||
Type: ProgramType(info.progType),
|
||||
}
|
||||
}
|
||||
|
||||
// Check verifies that a Program conforms to the ABI.
|
||||
//
|
||||
// Members which have the zero value of their type
|
||||
// are not checked.
|
||||
func (abi *ProgramABI) Check(prog *Program) error {
|
||||
if abi.Type != UnspecifiedProgram && prog.abi.Type != abi.Type {
|
||||
return errors.Errorf("expected program type %s, have %s", abi.Type, prog.abi.Type)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkUint32(name string, want, have uint32) error {
|
||||
if want != 0 && have != want {
|
||||
return errors.Errorf("expected %s to be %d, have %d", name, want, have)
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user