gpt4 book ai didi

c - 尝试加载 BPF 程序时参数无效 (EINVAL)

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:36:11 25 4
gpt4 key购买 nike

我正在尝试使用 bpf 系统调用加载 BPF 程序,但我在返回时收到 invalid argument (EINVAL)。来自man page ,可能的原因是:

EINVAL

For BPF_PROG_LOAD, indicates an attempt to load an invalid program.
eBPF programs can be deemed invalid due to unrecognized instructions,
the use of reserved fields, jumps out of range, infinite loops or calls
of unknown functions.

看来我的BPF程序有问题。我的BPF程序如下:

#include <uapi/linux/bpf.h>

int prog(struct pt_regs *ctx)
{
return 0;
}

这肯定不会有任何问题。

我正在使用 Makefile 进行编译 here (我从 test_overhead_kprobe_kern.c 中删除了大部分代码,以提供一个非常简单的测试程序)。

我的程序可能有什么问题导致它被拒绝?

uname -a:Linux ubuntu1710 4.13.0-32-generic#35-Ubuntu SMP Thu Jan 25 09:13:46 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

我的完整用户空间代码(在 Go 中)如下:

package main

/*
#include <stdio.h>
#include <stdlib.h>

void print(char* s) {
printf("%s\n", s);
}
*/
import "C"

import (
"unsafe"

"golang.org/x/sys/unix"

"github.com/cilium/cilium/pkg/bpf"
)
import (
"fmt"
"io/ioutil"
)

const (
bufferSize = 256
sessionIDHTTPHeader = "X-Session-ID"
defaultServerAddress = "localhost"
defaultPort = 5050
)

const (
BPF_PROG_TYPE_UNSPEC = 0
BPF_PROG_TYPE_SOCKET_FILTER = 1
BPF_PROG_TYPE_KPROBE = 2
BPF_PROG_TYPE_SCHED_CLS = 3
BPF_PROG_TYPE_SCHED_ACT = 4
)

type ttyWrite struct {
Count int32
Buf [bufferSize]byte
SessionID int32
}

func main() {

//for i := 0; i < 6; i++ {
//b, err := ioutil.ReadFile(fmt.Sprintf("bpf/test%d.o", i))
b, err := ioutil.ReadFile("bpf/bpf_tty.o")
if err != nil {
fmt.Print(err)
}

err = loadProgram(BPF_PROG_TYPE_KPROBE, unsafe.Pointer(&b), len(b))
if err != nil {
fmt.Printf("%s\n", err)
}
//}

}

func loadProgram(progType int, insns unsafe.Pointer, insnCnt int) error {

licenseBuf := "GPL"
licenseStr := C.CString(licenseBuf)
defer C.free(unsafe.Pointer(licenseStr))

logStr := C.CString("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
defer C.free(unsafe.Pointer(logStr))

lba := struct {
progType uint32
//pad0 [4]byte
insnCnt uint32
//pad1 [4]byte
insns uint64
license uint64
logLevel uint32
//pad2 [4]byte
logSize uint32
//pad3 [4]byte
logBuf uint64
kernVersion uint32
//pad4 [4]byte
}{
progType: uint32(progType),
insnCnt: uint32(insnCnt),
insns: uint64(uintptr(insns)),
license: uint64(uintptr(unsafe.Pointer(licenseStr))),
logLevel: uint32(1),
logSize: uint32(50),
logBuf: uint64(uintptr(unsafe.Pointer(logStr))),
//logBuf: uint64(uintptr(unsafe.Pointer(bufStr))),
// /usr/src/linux-headers-4.13.0-32-generic/include/generated/uapi/linux/version.h
kernVersion: uint32(265485),
}

ret, _, err := unix.Syscall(
unix.SYS_BPF,
bpf.BPF_PROG_LOAD,
uintptr(unsafe.Pointer(&lba)),
unsafe.Sizeof(lba),
)

//fmt.Printf("%s\n", logBuf)
//cs := C.CString("XXXXXXXXXX")
C.print(logStr)
//fmt.Printf("%c\n", *logStr)

if ret != 0 || err != 0 {
//fmt.Printf("%#v %d\n", logBuf, unsafe.Sizeof(lba))
return fmt.Errorf("Unable to load program: ret: %d: %s", int(ret), err)
}

return nil
}

最佳答案

作为Qeole pointed out in your previous question ,你的用户空间 Go 程序需要从目标文件中提取 BPF 指令(.text 部分)。否则,内核将尝试将二进制内容解释为 BPF 指令,但不可避免地会失败。

关于c - 尝试加载 BPF 程序时参数无效 (EINVAL),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48673140/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com