add local support for introspection service
Signed-off-by: Kathryn Baldauf <kabaldau@microsoft.com>
This commit is contained in:
		
							
								
								
									
										447
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								vendor/github.com/cilium/ebpf/syscalls.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,447 @@
 | 
			
		||||
package ebpf
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/cilium/ebpf/internal"
 | 
			
		||||
	"github.com/cilium/ebpf/internal/unix"
 | 
			
		||||
 | 
			
		||||
	"github.com/pkg/errors"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var errClosedFd = errors.New("use of closed file descriptor")
 | 
			
		||||
 | 
			
		||||
type bpfFD struct {
 | 
			
		||||
	raw int64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newBPFFD(value uint32) *bpfFD {
 | 
			
		||||
	fd := &bpfFD{int64(value)}
 | 
			
		||||
	runtime.SetFinalizer(fd, (*bpfFD).close)
 | 
			
		||||
	return fd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *bpfFD) String() string {
 | 
			
		||||
	return strconv.FormatInt(fd.raw, 10)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *bpfFD) value() (uint32, error) {
 | 
			
		||||
	if fd.raw < 0 {
 | 
			
		||||
		return 0, errClosedFd
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return uint32(fd.raw), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *bpfFD) close() error {
 | 
			
		||||
	if fd.raw < 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := int(fd.raw)
 | 
			
		||||
	fd.raw = -1
 | 
			
		||||
 | 
			
		||||
	fd.forget()
 | 
			
		||||
	return unix.Close(value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *bpfFD) forget() {
 | 
			
		||||
	runtime.SetFinalizer(fd, nil)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fd *bpfFD) dup() (*bpfFD, error) {
 | 
			
		||||
	if fd.raw < 0 {
 | 
			
		||||
		return nil, errClosedFd
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dup, err := unix.FcntlInt(uintptr(fd.raw), unix.F_DUPFD_CLOEXEC, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrap(err, "can't dup fd")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newBPFFD(uint32(dup)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// bpfObjName is a null-terminated string made up of
 | 
			
		||||
// 'A-Za-z0-9_' characters.
 | 
			
		||||
type bpfObjName [unix.BPF_OBJ_NAME_LEN]byte
 | 
			
		||||
 | 
			
		||||
// newBPFObjName truncates the result if it is too long.
 | 
			
		||||
func newBPFObjName(name string) (bpfObjName, error) {
 | 
			
		||||
	idx := strings.IndexFunc(name, invalidBPFObjNameChar)
 | 
			
		||||
	if idx != -1 {
 | 
			
		||||
		return bpfObjName{}, errors.Errorf("invalid character '%c' in name '%s'", name[idx], name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var result bpfObjName
 | 
			
		||||
	copy(result[:unix.BPF_OBJ_NAME_LEN-1], name)
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func invalidBPFObjNameChar(char rune) bool {
 | 
			
		||||
	switch {
 | 
			
		||||
	case char >= 'A' && char <= 'Z':
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case char >= 'a' && char <= 'z':
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case char >= '0' && char <= '9':
 | 
			
		||||
		fallthrough
 | 
			
		||||
	case char == '_':
 | 
			
		||||
		return false
 | 
			
		||||
	default:
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfMapCreateAttr struct {
 | 
			
		||||
	mapType    MapType
 | 
			
		||||
	keySize    uint32
 | 
			
		||||
	valueSize  uint32
 | 
			
		||||
	maxEntries uint32
 | 
			
		||||
	flags      uint32
 | 
			
		||||
	innerMapFd uint32     // since 4.12 56f668dfe00d
 | 
			
		||||
	numaNode   uint32     // since 4.14 96eabe7a40aa
 | 
			
		||||
	mapName    bpfObjName // since 4.15 ad5b177bd73f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfMapOpAttr struct {
 | 
			
		||||
	mapFd   uint32
 | 
			
		||||
	padding uint32
 | 
			
		||||
	key     syscallPtr
 | 
			
		||||
	value   syscallPtr
 | 
			
		||||
	flags   uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfMapInfo struct {
 | 
			
		||||
	mapType    uint32
 | 
			
		||||
	id         uint32
 | 
			
		||||
	keySize    uint32
 | 
			
		||||
	valueSize  uint32
 | 
			
		||||
	maxEntries uint32
 | 
			
		||||
	flags      uint32
 | 
			
		||||
	mapName    bpfObjName // since 4.15 ad5b177bd73f
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfPinObjAttr struct {
 | 
			
		||||
	fileName syscallPtr
 | 
			
		||||
	fd       uint32
 | 
			
		||||
	padding  uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgLoadAttr struct {
 | 
			
		||||
	progType           ProgramType
 | 
			
		||||
	insCount           uint32
 | 
			
		||||
	instructions       syscallPtr
 | 
			
		||||
	license            syscallPtr
 | 
			
		||||
	logLevel           uint32
 | 
			
		||||
	logSize            uint32
 | 
			
		||||
	logBuf             syscallPtr
 | 
			
		||||
	kernelVersion      uint32     // since 4.1  2541517c32be
 | 
			
		||||
	progFlags          uint32     // since 4.11 e07b98d9bffe
 | 
			
		||||
	progName           bpfObjName // since 4.15 067cae47771c
 | 
			
		||||
	progIfIndex        uint32     // since 4.15 1f6f4cb7ba21
 | 
			
		||||
	expectedAttachType AttachType // since 4.17 5e43f899b03a
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgInfo struct {
 | 
			
		||||
	progType     uint32
 | 
			
		||||
	id           uint32
 | 
			
		||||
	tag          [unix.BPF_TAG_SIZE]byte
 | 
			
		||||
	jitedLen     uint32
 | 
			
		||||
	xlatedLen    uint32
 | 
			
		||||
	jited        syscallPtr
 | 
			
		||||
	xlated       syscallPtr
 | 
			
		||||
	loadTime     uint64 // since 4.15 cb4d2b3f03d8
 | 
			
		||||
	createdByUID uint32
 | 
			
		||||
	nrMapIDs     uint32
 | 
			
		||||
	mapIds       syscallPtr
 | 
			
		||||
	name         bpfObjName
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgTestRunAttr struct {
 | 
			
		||||
	fd          uint32
 | 
			
		||||
	retval      uint32
 | 
			
		||||
	dataSizeIn  uint32
 | 
			
		||||
	dataSizeOut uint32
 | 
			
		||||
	dataIn      syscallPtr
 | 
			
		||||
	dataOut     syscallPtr
 | 
			
		||||
	repeat      uint32
 | 
			
		||||
	duration    uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfProgAlterAttr struct {
 | 
			
		||||
	targetFd    uint32
 | 
			
		||||
	attachBpfFd uint32
 | 
			
		||||
	attachType  uint32
 | 
			
		||||
	attachFlags uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfObjGetInfoByFDAttr struct {
 | 
			
		||||
	fd      uint32
 | 
			
		||||
	infoLen uint32
 | 
			
		||||
	info    syscallPtr // May be either bpfMapInfo or bpfProgInfo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type bpfGetFDByIDAttr struct {
 | 
			
		||||
	id   uint32
 | 
			
		||||
	next uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newPtr(ptr unsafe.Pointer) syscallPtr {
 | 
			
		||||
	return syscallPtr{ptr: ptr}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfProgLoad(attr *bpfProgLoadAttr) (*bpfFD, error) {
 | 
			
		||||
	for {
 | 
			
		||||
		fd, err := bpfCall(_ProgLoad, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
		// As of ~4.20 the verifier can be interrupted by a signal,
 | 
			
		||||
		// and returns EAGAIN in that case.
 | 
			
		||||
		if err == unix.EAGAIN {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return newBPFFD(uint32(fd)), nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfProgAlter(cmd int, attr *bpfProgAlterAttr) error {
 | 
			
		||||
	_, err := bpfCall(cmd, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapCreate(attr *bpfMapCreateAttr) (*bpfFD, error) {
 | 
			
		||||
	fd, err := bpfCall(_MapCreate, unsafe.Pointer(attr), unsafe.Sizeof(*attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return newBPFFD(uint32(fd)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveNestedMaps = internal.FeatureTest("nested maps", "4.12", func() bool {
 | 
			
		||||
	inner, err := bpfMapCreate(&bpfMapCreateAttr{
 | 
			
		||||
		mapType:    Array,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
		valueSize:  4,
 | 
			
		||||
		maxEntries: 1,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	defer inner.close()
 | 
			
		||||
 | 
			
		||||
	innerFd, _ := inner.value()
 | 
			
		||||
	nested, err := bpfMapCreate(&bpfMapCreateAttr{
 | 
			
		||||
		mapType:    ArrayOfMaps,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
		valueSize:  4,
 | 
			
		||||
		maxEntries: 1,
 | 
			
		||||
		innerMapFd: innerFd,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = nested.close()
 | 
			
		||||
	return true
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfMapLookupElem(m *bpfFD, key, valueOut syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapOpAttr{
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapLookupElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapUpdateElem(m *bpfFD, key, valueOut syscallPtr, flags uint64) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapOpAttr{
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: valueOut,
 | 
			
		||||
		flags: flags,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapUpdateElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapDeleteElem(m *bpfFD, key syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapOpAttr{
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapDeleteElem, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfMapGetNextKey(m *bpfFD, key, nextKeyOut syscallPtr) error {
 | 
			
		||||
	fd, err := m.value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapOpAttr{
 | 
			
		||||
		mapFd: fd,
 | 
			
		||||
		key:   key,
 | 
			
		||||
		value: nextKeyOut,
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_MapGetNextKey, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const bpfFSType = 0xcafe4a11
 | 
			
		||||
 | 
			
		||||
func bpfPinObject(fileName string, fd *bpfFD) 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 = bpfCall(_ObjPin, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
 | 
			
		||||
		fd:       value,
 | 
			
		||||
	}), 16)
 | 
			
		||||
	return errors.Wrapf(err, "pin object %s", fileName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetObject(fileName string) (*bpfFD, error) {
 | 
			
		||||
	ptr, err := bpfCall(_ObjGet, unsafe.Pointer(&bpfPinObjAttr{
 | 
			
		||||
		fileName: newPtr(unsafe.Pointer(&[]byte(fileName)[0])),
 | 
			
		||||
	}), 16)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(err, "get object %s", fileName)
 | 
			
		||||
	}
 | 
			
		||||
	return newBPFFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetObjectInfoByFD(fd *bpfFD, info unsafe.Pointer, size uintptr) error {
 | 
			
		||||
	value, err := fd.value()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// available from 4.13
 | 
			
		||||
	attr := bpfObjGetInfoByFDAttr{
 | 
			
		||||
		fd:      value,
 | 
			
		||||
		infoLen: uint32(size),
 | 
			
		||||
		info:    newPtr(info),
 | 
			
		||||
	}
 | 
			
		||||
	_, err = bpfCall(_ObjGetInfoByFD, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	return errors.Wrapf(err, "fd %d", value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetProgInfoByFD(fd *bpfFD) (*bpfProgInfo, error) {
 | 
			
		||||
	var info bpfProgInfo
 | 
			
		||||
	err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
 | 
			
		||||
	return &info, errors.Wrap(err, "can't get program info")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetMapInfoByFD(fd *bpfFD) (*bpfMapInfo, error) {
 | 
			
		||||
	var info bpfMapInfo
 | 
			
		||||
	err := bpfGetObjectInfoByFD(fd, unsafe.Pointer(&info), unsafe.Sizeof(info))
 | 
			
		||||
	return &info, errors.Wrap(err, "can't get map info")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var haveObjName = internal.FeatureTest("object names", "4.15", func() bool {
 | 
			
		||||
	name, err := newBPFObjName("feature_test")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		// This really is a fatal error, but it should be caught
 | 
			
		||||
		// by the unit tests not working.
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	attr := bpfMapCreateAttr{
 | 
			
		||||
		mapType:    Array,
 | 
			
		||||
		keySize:    4,
 | 
			
		||||
		valueSize:  4,
 | 
			
		||||
		maxEntries: 1,
 | 
			
		||||
		mapName:    name,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fd, err := bpfMapCreate(&attr)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_ = fd.close()
 | 
			
		||||
	return true
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
func bpfGetMapFDByID(id uint32) (*bpfFD, error) {
 | 
			
		||||
	// available from 4.13
 | 
			
		||||
	attr := bpfGetFDByIDAttr{
 | 
			
		||||
		id: id,
 | 
			
		||||
	}
 | 
			
		||||
	ptr, err := bpfCall(_MapGetFDByID, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, errors.Wrapf(err, "can't get fd for map id %d", id)
 | 
			
		||||
	}
 | 
			
		||||
	return newBPFFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfGetProgramFDByID(id uint32) (*bpfFD, error) {
 | 
			
		||||
	// available from 4.13
 | 
			
		||||
	attr := bpfGetFDByIDAttr{
 | 
			
		||||
		id: id,
 | 
			
		||||
	}
 | 
			
		||||
	ptr, err := bpfCall(_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 newBPFFD(uint32(ptr)), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func bpfCall(cmd int, attr unsafe.Pointer, size uintptr) (uintptr, error) {
 | 
			
		||||
	r1, _, errNo := unix.Syscall(unix.SYS_BPF, uintptr(cmd), uintptr(attr), size)
 | 
			
		||||
	runtime.KeepAlive(attr)
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
	if errNo != 0 {
 | 
			
		||||
		err = errNo
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return r1, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func convertCString(in []byte) string {
 | 
			
		||||
	inLen := bytes.IndexByte(in, 0)
 | 
			
		||||
	if inLen == -1 {
 | 
			
		||||
		return ""
 | 
			
		||||
	}
 | 
			
		||||
	return string(in[:inLen])
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user