在 BPF 中比较字符串时出现地址错误
Bad address error when comparing Strings within BPF
我有一个示例程序我在运行这里查看子字符串是否与字符串匹配,然后将它们打印出来。到目前为止,由于地址错误,我遇到了 运行 程序问题。我想知道是否有办法解决这个问题?我附上了完整的代码,但我的问题主要与 isSubstring 有关。
#include <uapi/linux/bpf.h>
#define ARRAYSIZE 64
struct data_t {
char buf[ARRAYSIZE];
};
BPF_ARRAY(lookupTable, struct data_t, ARRAYSIZE);
//char name[20];
//find substring in a string
static bool isSubstring(struct data_t stringVal)
{
char substring[] = "New York";
int M = sizeof(substring);
int N = sizeof(stringVal.buf) - 1;
/* A loop to slide pat[] one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for
pattern match */
for (j = 0; j < M; j++)
if (stringVal.buf[i + j] != substring[j])
break;
if (j == M)
return true;
}
return false;
}
int Test(void *ctx)
{
#pragma clang loop unroll(full)
for (int i = 0; i < ARRAYSIZE; i++) {
int k = i;
struct data_t *line = lookupTable.lookup(&k);
if (line) {
// bpf_trace_printk("%s\n", key->buf);
if (isSubstring(*line)) {
bpf_trace_printk("%s\n", line->buf);
}
}
}
return 0;
}
我的 python 代码在这里:
import ctypes
from bcc import BPF
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
print(len(string))
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="Test")
b.trace_print()
编辑:忘记补充错误:真的很长,可以在这里找到:https://pastebin.com/a7E9L230
我认为错误中最有趣的部分是在它提到的底部附近:
The sequence of 8193 jumps is too complex.
再往下一点提到:地址错误。
验证程序检查程序中的所有分支。每次它看到跳转指令时,它都会将新分支推送到它的“要检查的分支堆栈”。这个堆栈有一个限制(BPF_COMPLEXITY_LIMIT_JMP_SEQ
,目前是 8192),正如验证者告诉你的那样。 “错误地址”只是内核的 errno
值的翻译,在这种情况下被设置为 -EFAULT
。
不过不确定如何修复它,您可以尝试:
- 使用较小的字符串,或者
- 在 5.3+ 内核(支持有界循环)上:不使用 clang 展开循环(我不知道它是否有帮助)。
我有一个示例程序我在运行这里查看子字符串是否与字符串匹配,然后将它们打印出来。到目前为止,由于地址错误,我遇到了 运行 程序问题。我想知道是否有办法解决这个问题?我附上了完整的代码,但我的问题主要与 isSubstring 有关。
#include <uapi/linux/bpf.h>
#define ARRAYSIZE 64
struct data_t {
char buf[ARRAYSIZE];
};
BPF_ARRAY(lookupTable, struct data_t, ARRAYSIZE);
//char name[20];
//find substring in a string
static bool isSubstring(struct data_t stringVal)
{
char substring[] = "New York";
int M = sizeof(substring);
int N = sizeof(stringVal.buf) - 1;
/* A loop to slide pat[] one by one */
for (int i = 0; i <= N - M; i++) {
int j;
/* For current index i, check for
pattern match */
for (j = 0; j < M; j++)
if (stringVal.buf[i + j] != substring[j])
break;
if (j == M)
return true;
}
return false;
}
int Test(void *ctx)
{
#pragma clang loop unroll(full)
for (int i = 0; i < ARRAYSIZE; i++) {
int k = i;
struct data_t *line = lookupTable.lookup(&k);
if (line) {
// bpf_trace_printk("%s\n", key->buf);
if (isSubstring(*line)) {
bpf_trace_printk("%s\n", line->buf);
}
}
}
return 0;
}
我的 python 代码在这里:
import ctypes
from bcc import BPF
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
contents = f.readlines()
for i in range(0,len(contents)):
string = contents[i].encode('utf-8')
print(len(string))
lookupTable[ctypes.c_int(i)] = ctypes.create_string_buffer(string, len(string))
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="Test")
b.trace_print()
编辑:忘记补充错误:真的很长,可以在这里找到:https://pastebin.com/a7E9L230
我认为错误中最有趣的部分是在它提到的底部附近:
The sequence of 8193 jumps is too complex.
再往下一点提到:地址错误。
验证程序检查程序中的所有分支。每次它看到跳转指令时,它都会将新分支推送到它的“要检查的分支堆栈”。这个堆栈有一个限制(BPF_COMPLEXITY_LIMIT_JMP_SEQ
,目前是 8192),正如验证者告诉你的那样。 “错误地址”只是内核的 errno
值的翻译,在这种情况下被设置为 -EFAULT
。
不过不确定如何修复它,您可以尝试:
- 使用较小的字符串,或者
- 在 5.3+ 内核(支持有界循环)上:不使用 clang 展开循环(我不知道它是否有帮助)。