Search code examples
bpfebpfbcc-bpf

Bad address error when comparing Strings within BPF


I have an example program I am running here to see if the substring matches the string and then print them out. So far, I am having trouble running the program due to a bad address. I am wondering if there is a way to fix this problem? I have attached the entire code but my problem is mostly related to 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;
}

My python code here:

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()

Edit: Forgot to add the error: It's really long and can be found here: https://pastebin.com/a7E9L230

I think the most interesting part of the error is near the bottom where it mentions:

The sequence of 8193 jumps is too complex.

And a little bit farther down mentions: Bad Address.


Solution

  • The verifier checks all branches in your program. Each time it sees a jump instruction, it pushes the new branch to its “stack of branches to check”. This stack has a limit (BPF_COMPLEXITY_LIMIT_JMP_SEQ, currently 8192) that you are hitting, as the verifier tells you. “Bad Address” is just the translation of kernel's errno value which is set to -EFAULT in that case.

    Not sure how to fix it though, you could try:

    1. With smaller strings, or
    2. On a 5.3+ kernel (which supports bounded loops): without unrolling the loop with clang (I don't know if it would help).