-
Describe the bug I wanna write a raw_tracepoint bpf program by cilium/ebpf in Linux Kernel 4.18, my code is:
//go:build linux
// +build linux
// This program demonstrates attaching an eBPF program to a kernel symbol.
// The eBPF program will be attached to the start of the sys_execve
// kernel function and prints out the number of times it has been called
// every second.
package main
import (
"log"
"time"
"github.com/cilium/ebpf/link"
)
// $BPF_CLANG and $BPF_CFLAGS are set by the Makefile.
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -cc $BPF_CLANG -cflags $BPF_CFLAGS bpf raw_tracepoint.c -- -I../headers
//const mapKey uint32 = 0
func main() {
// Name of the kernel function to trace.
fn := "sys_enter"
// Allow the current process to lock memory for eBPF resources.
// if err := rlimit.RemoveMemlock(); err != nil {
// log.Fatal(err)
// }
// Load pre-compiled programs and maps into the kernel.
objs := bpfObjects{}
if err := loadBpfObjects(&objs, nil); err != nil {
log.Fatalf("loading objects: %v", err)
}
defer objs.Close()
link, err := link.AttachRawTracepoint(link.RawTracepointOptions{
Name: fn,
Program: objs.RawTpSysEnter,
})
if err != nil {
log.Fatalf(("attach faield"))
}
defer link.Close()
ticker := time.NewTicker(1 * time.Second)
log.Println("Waiting for events..")
for range ticker.C {
time.Sleep(1)
log.Printf(".")
}
}
// +build ignore
#include "common.h"
#include "bpf_helpers.h"
//#include "vmlinux.h"
char __license[] SEC("license") = "Dual MIT/GPL";
#define TASK_COMM_LEN 16
// struct bpf_map_def SEC("maps") raw_tracepoint_map = {
// .type = BPF_MAP_TYPE_ARRAY,
// .key_size = sizeof(u32),
// .value_size = sizeof(u64),
// .max_entries = 100,
// };
/* ****************************** Deceleration Begin ****************************** */
/* Another Helpers */
static __inline int memcmp(const void* s1, const void* s2, u64 cnt);
static __inline void *memcpy(void* dest, const void* src, u64 count);
static __inline int memcmp(const void* s1, const void* s2, u64 cnt){
const char *t1 = s1;
const char *t2 = s2;
int res = 0;
while(cnt-- > 0){
if(*t1 > *t2){
res =1;
break;
}
else if(*t1 < *t2){
res = -1;
break;
}
else{
t1++;
t2++;
}
}
return res;
}
static __inline void *memcpy(void* dest, const void* src, u64 count)
{
char* pdest =(char*) dest;
const char* psrc =(const char*) src;
if (psrc > pdest || pdest >= psrc + count)
{
while (count--)
*pdest++ = *psrc++;
}
else
{
while (count--)
{
*(pdest + count) = *(psrc + count);
}
}
return dest;
}
/* Enter Operation */
// static __inline int handle_enter_read(struct bpf_raw_tracepoint_args *ctx);
// static __inline int handle_enter_close(struct bpf_raw_tracepoint_args *ctx);
// static __inline int handle_enter_stat(struct bpf_raw_tracepoint_args *ctx);
// static __inline int handle_enter_fstat(struct bpf_raw_tracepoint_args *ctx);
// static __inline int handle_enter_openat(struct bpf_raw_tracepoint_args *ctx);
/* Exit Hook Operation */
// static __inline int handle_exit_read(struct bpf_raw_tracepoint_args *ctx);
// static __inline int handle_exit_stat();
// static __inline int handle_exit_fstat();
// static __inline int handle_exit_openat(struct bpf_raw_tracepoint_args *ctx);
/* ****************************** Deceleration Over ****************************** */
static __inline int handle_enter_read(struct bpf_raw_tracepoint_args *ctx){
bpf_printk("read\n");
return 0;
}
static __inline int handle_enter_close(struct bpf_raw_tracepoint_args *ctx){
bpf_printk("close\n");
return 0;
}
static __inline int handle_enter_stat(struct bpf_raw_tracepoint_args *ctx){
bpf_printk("stat\n");
return 0;
}
static __inline int handle_enter_fstat(struct bpf_raw_tracepoint_args *ctx){
bpf_printk("fstat\n");
return 0;
}
static __inline int handle_enter_openat(struct bpf_raw_tracepoint_args *ctx){
bpf_printk("openat\n");
return 0;
}
#define TARGET_NAME "sh"
SEC("raw_tracepoint/sys_enter")
int raw_tp_sys_enter(struct bpf_raw_tracepoint_args *ctx)
{
unsigned long syscall_id = ctx->args[1];
char comm[TASK_COMM_LEN];
bpf_get_current_comm(&comm, sizeof(comm));
// executable is not cron, return
if (memcmp(comm, TARGET_NAME, sizeof(TARGET_NAME))){
return 0;
}
switch (syscall_id)
{
case 0:
handle_enter_read(ctx);
break;
case 3: // close
handle_enter_close(ctx);
break;
case 4:
handle_enter_stat(ctx);
break;
case 5:
handle_enter_fstat(ctx);
break;
case 257:
handle_enter_openat(ctx);
break;
default:
return 0;
}
return 0;
} At the same time, I add the definition about And I compile it by: go generate
go build . which seems function well. And generate a ELF file: However, I run it and then receive a problem: root@VM-16-4-ubuntu:~/ebpf/examples/raw_tracepoint_in_c# ./raw_tracepoint_in_c
2022/03/06 22:02:50 loading objects: field RawTpSysEnter: program raw_tp_sys_enter: map .rodata: map create: read- and write-only maps not supported (requires >= v5.2) I really wonder why, and how to fix it.... By the way, I have done some other tests, and I found that if I remove the following part in switch (syscall_id)
{
case 0:
handle_enter_read(ctx);
break;
case 3: // close
handle_enter_close(ctx);
break;
case 4:
handle_enter_stat(ctx);
break;
case 5:
handle_enter_fstat(ctx);
break;
case 257:
handle_enter_openat(ctx);
break;
default:
return 0;
} Then, there is no problem, which I thought is weird.... To Reproduce Expected behavior |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @OrangeGzY, thanks for your question. Please refrain from creating issues and marking them as bugs, this is not the case here. An The library exposes data sections as e.g. an Today, there are a few ways to inspect the contents of a data section. One of them is inspecting the binary's BTF info using
To inspect the binary contents of a particular data section, use
Hope this helps! |
Beta Was this translation helpful? Give feedback.
Hi @OrangeGzY, thanks for your question. Please refrain from creating issues and marking them as bugs, this is not the case here.
An
.rodata
section generally shows up when declaring and initializing global constants, but declaring any kind of string in your program often has the same effect.The library exposes data sections as e.g. an
.rodata
map after loading to allow their contents to be modified before loading them into the kernel. As you've noticed, this can be somewhat surprising for newcomers. This feature requires kernel support, which only landed as of 5.2, which the error message is pretty clear about.Today, there are a few ways to inspect the contents of a data section. One o…