![](/img/trans.png)
[英]BPF: `bpf_obj_get_info_by_fd` fails with `Invalid argument`
[英]Invalid argument (EINVAL) when trying to load a BPF program
我正在嘗試使用bpf
系統調用加載 BPF 程序,但我在返回時收到invalid argument
(EINVAL)。 從手冊頁,可能的原因是:
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
編譯(我從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 在您之前的問題中指出的那樣,您的用戶空間 Go 程序需要從目標文件中提取 BPF 指令( .text
部分)。 否則,內核會嘗試將二進制內容解釋為 BPF 指令並不可避免地失敗。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.