From b2892a34c05da71c21c7185b7ffa2830b112f3c3 Mon Sep 17 00:00:00 2001 From: grantseltzer Date: Thu, 19 Dec 2024 15:42:08 -0600 Subject: [PATCH] make use of bpf_probe_read_(kernel|user) functions Signed-off-by: grantseltzer --- .../codegen/c/dynamicinstrumentation.c | 48 +++++++++++++++---- pkg/dynamicinstrumentation/codegen/c/event.h | 3 ++ .../codegen/c/expressions.h | 28 +++++------ .../codegen/templates.go | 10 ++-- 4 files changed, 60 insertions(+), 29 deletions(-) diff --git a/pkg/dynamicinstrumentation/codegen/c/dynamicinstrumentation.c b/pkg/dynamicinstrumentation/codegen/c/dynamicinstrumentation.c index 3312082da5676..5988743166b75 100644 --- a/pkg/dynamicinstrumentation/codegen/c/dynamicinstrumentation.c +++ b/pkg/dynamicinstrumentation/codegen/c/dynamicinstrumentation.c @@ -29,11 +29,23 @@ int {{.GetBPFFuncName}}(struct pt_regs *ctx) bpf_ringbuf_discard(event, 0); return 0; } - - bpf_probe_read(&event->base.probe_id, sizeof(event->base.probe_id), zero_string); - bpf_probe_read(&event->base.program_counters, sizeof(event->base.program_counters), zero_string); - bpf_probe_read(&event->output, sizeof(event->output), zero_string); - bpf_probe_read(&event->base.probe_id, {{ .ID | len }}, "{{.ID}}"); + long err; + err = bpf_probe_read_kernel(&event->base.probe_id, sizeof(event->base.probe_id), zero_string); + if (err != 0) { + bpf_printk("could not zero out probe id buffer"); + } + err = bpf_probe_read_kernel(&event->base.program_counters, sizeof(event->base.program_counters), zero_string); + if (err != 0) { + bpf_printk("could not zero out program counter buffer"); + } + err = bpf_probe_read_kernel(&event->output, sizeof(event->output), zero_string); + if (err != 0) { + bpf_printk("could not zero out output buffer"); + } + err = bpf_probe_read_kernel(&event->base.probe_id, {{ .ID | len }}, "{{.ID}}"); + if (err != 0) { + bpf_printk("could not write probe id to output"); + } // Get tid and tgid u64 pidtgid = bpf_get_current_pid_tgid(); @@ -46,10 +58,17 @@ int {{.GetBPFFuncName}}(struct pt_regs *ctx) // Collect stack trace __u64 currentPC = PT_REGS_IP(ctx); - bpf_probe_read(&event->base.program_counters[0], sizeof(__u64), ¤tPC); + err = bpf_probe_read_kernel(&event->base.program_counters[0], sizeof(__u64), ¤tPC); + if (err != 0) { + bpf_printk("could not collect first program counter"); + } __u64 bp = PT_REGS_FP(ctx); - bpf_probe_read(&bp, sizeof(__u64), (void*)bp); // dereference bp to get current stack frame + err = bpf_probe_read_user(&bp, sizeof(__u64), (void*)bp); // dereference bp to get current stack frame + if (err != 0) { + bpf_printk("could not retrieve base pointer for current stack frame"); + } + __u64 ret_addr = PT_REGS_RET(ctx); // when bpf prog enters, the return address hasn't yet been written to the stack int i; @@ -60,9 +79,18 @@ int {{.GetBPFFuncName}}(struct pt_regs *ctx) if (bp == 0) { break; } - bpf_probe_read(&event->base.program_counters[i], sizeof(__u64), &ret_addr); - bpf_probe_read(&ret_addr, sizeof(__u64), (void*)(bp-8)); - bpf_probe_read(&bp, sizeof(__u64), (void*)bp); + err = bpf_probe_read_kernel(&event->base.program_counters[i], sizeof(__u64), &ret_addr); + if (err != 0) { + bpf_printk("error occurred while collecting program counter for stack trace (1)"); + } + err = bpf_probe_read_user(&ret_addr, sizeof(__u64), (void*)(bp-8)); + if (err != 0) { + bpf_printk("error occurred while collecting program counter for stack trace (2)"); + } + err = bpf_probe_read_user(&bp, sizeof(__u64), (void*)bp); + if (err != 0) { + bpf_printk("error occurred while collecting program counter for stack trace (3)"); + } } // Collect parameters diff --git a/pkg/dynamicinstrumentation/codegen/c/event.h b/pkg/dynamicinstrumentation/codegen/c/event.h index b6cfe573dba97..a6c0202564e77 100644 --- a/pkg/dynamicinstrumentation/codegen/c/event.h +++ b/pkg/dynamicinstrumentation/codegen/c/event.h @@ -2,12 +2,15 @@ #define DI_EVENT_H #include "ktypes.h" +#include "macros.h" struct event { struct base_event base; char output[PARAM_BUFFER_SIZE]; }; +// expression_context contains state that is meant to be shared across location expressions +// during execution of the full bpf program. struct expression_context { __u64 *output_offset; __u8 *stack_counter; diff --git a/pkg/dynamicinstrumentation/codegen/c/expressions.h b/pkg/dynamicinstrumentation/codegen/c/expressions.h index f6c6ad28aba2a..a62102dfc0d34 100644 --- a/pkg/dynamicinstrumentation/codegen/c/expressions.h +++ b/pkg/dynamicinstrumentation/codegen/c/expressions.h @@ -7,7 +7,7 @@ static __always_inline int read_register(struct expression_context context, __u6 { long err; __u64 valueHolder = 0; - err = bpf_probe_read(&valueHolder, element_size, &context.ctx->DWARF_REGISTER(reg)); + err = bpf_probe_read_kernel(&valueHolder, element_size, &context.ctx->DWARF_REGISTER(reg)); if (err != 0) { log_debug("error when reading data from register: %ld", err); } @@ -22,7 +22,7 @@ static __always_inline int read_stack(struct expression_context context, size_t { long err; __u64 valueHolder = 0; - err = bpf_probe_read(&valueHolder, element_size, &context.ctx->DWARF_STACK_REGISTER+stack_offset); + err = bpf_probe_read_kernel(&valueHolder, element_size, &context.ctx->DWARF_STACK_REGISTER+stack_offset); if (err != 0) { log_debug("error when reading data from stack: %ld", err); } @@ -36,7 +36,7 @@ static __always_inline int read_stack(struct expression_context context, size_t static __always_inline int read_register_value_to_output(struct expression_context context, __u64 reg, __u32 element_size) { long err; - err = bpf_probe_read(&context.event->output[*(context.output_offset)], element_size, &context.ctx->DWARF_REGISTER(reg)); + err = bpf_probe_read_kernel(&context.event->output[*(context.output_offset)], element_size, &context.ctx->DWARF_REGISTER(reg)); if (err != 0) { log_debug("error when reading data while reading register value to output: %ld", err); } @@ -49,7 +49,7 @@ static __always_inline int read_register_value_to_output(struct expression_conte static __always_inline int read_stack_value_to_output(struct expression_context context, __u64 stack_offset, __u32 element_size) { long err; - err = bpf_probe_read(&context.event->output[*(context.output_offset)], element_size, &context.ctx->DWARF_STACK_REGISTER+stack_offset); + err = bpf_probe_read_kernel(&context.event->output[*(context.output_offset)], element_size, &context.ctx->DWARF_STACK_REGISTER+stack_offset); if (err != 0) { log_debug("error when reading data while reading stack value to output: %ld", err); } @@ -68,7 +68,7 @@ static __always_inline int pop(struct expression_context context, __u64 num_elem bpf_map_pop_elem(¶m_stack, &valueHolder); *context.stack_counter -= 1; log_debug("Popping to output: %llu", valueHolder); - err = bpf_probe_read(&context.event->output[*(context.output_offset)+i], element_size, &valueHolder); + err = bpf_probe_read_kernel(&context.event->output[*(context.output_offset)+i], element_size, &valueHolder); if (err != 0) { log_debug("error when reading data while popping from bpf stack: %ld", err); return_err = err; @@ -122,7 +122,7 @@ static __always_inline int dereference_to_output(struct expression_context conte __u64 valueHolder = 0; log_debug("Going to deref to output: 0x%llx", addressHolder); - err = bpf_probe_read(&valueHolder, element_size, (void*)addressHolder); + err = bpf_probe_read_user(&valueHolder, element_size, (void*)addressHolder); if (err != 0) { return_err = err; log_debug("error when reading data while dereferencing to output: %ld", err); @@ -131,7 +131,7 @@ static __always_inline int dereference_to_output(struct expression_context conte __u64 encodedValueHolder = valueHolder & mask; log_debug("Writing %llu to output (dereferenced)", encodedValueHolder); - err = bpf_probe_read(&context.event->output[*(context.output_offset)], element_size, &encodedValueHolder); + err = bpf_probe_read_kernel(&context.event->output[*(context.output_offset)], element_size, &encodedValueHolder); if (err != 0) { return_err = err; log_debug("error when reading data while dereferencing into output: %ld", err); @@ -156,7 +156,7 @@ static __always_inline int dereference_large(struct expression_context context, __u32 chunk_size; for (i = 0; i < num_chunks; i++) { chunk_size = (i == num_chunks - 1 && element_size % 8 != 0) ? (element_size % 8) : 8; - err = bpf_probe_read(&context.temp_storage[i], element_size, (void*)(addressHolder + (i * 8))); + err = bpf_probe_read_user(&context.temp_storage[i], element_size, (void*)(addressHolder + (i * 8))); if (err != 0) { return_err = err; log_debug("error when reading data dereferencing large: %ld", err); @@ -175,7 +175,7 @@ static __always_inline int dereference_large(struct expression_context context, } // zero out shared array - err = bpf_probe_read(context.temp_storage, element_size*num_chunks, context.zero_string); + err = bpf_probe_read_kernel(context.temp_storage, element_size*num_chunks, context.zero_string); if (err != 0) { return_err = err; log_debug("error when reading data zeroing out shared memory while dereferencing large: %ld", err); @@ -192,7 +192,7 @@ static __always_inline int dereference_large_to_output(struct expression_context __u64 addressHolder = 0; bpf_map_pop_elem(¶m_stack, &addressHolder); *context.stack_counter -= 1; - err = bpf_probe_read(&context.event->output[*(context.output_offset)], element_size, (void*)(addressHolder)); + err = bpf_probe_read_user(&context.event->output[*(context.output_offset)], element_size, (void*)(addressHolder)); if (err != 0) { log_debug("error when reading data: %ld", err); } @@ -232,7 +232,7 @@ static __always_inline int dereference_dynamic_to_output(struct expression_conte if (collection_size > bytes_limit) { collection_size = bytes_limit; } - err = bpf_probe_read(&context.event->output[*(context.output_offset)], collection_size, (void*)addressHolder); + err = bpf_probe_read_user(&context.event->output[*(context.output_offset)], collection_size, (void*)addressHolder); if (err != 0) { log_debug("error when doing dynamic dereference: %ld", err); } @@ -296,11 +296,11 @@ static __always_inline int read_str_to_output(struct expression_context context, *context.stack_counter -= 1; char* characterPointer = 0; - err = bpf_probe_read(&characterPointer, sizeof(characterPointer), (void*)(stringStructAddressHolder)); + err = bpf_probe_read_user(&characterPointer, sizeof(characterPointer), (void*)(stringStructAddressHolder)); log_debug("Reading from 0x%p", characterPointer); __u32 length; - err = bpf_probe_read(&length, sizeof(length), (void*)(stringStructAddressHolder+8)); + err = bpf_probe_read_user(&length, sizeof(length), (void*)(stringStructAddressHolder+8)); if (err != 0) { log_debug("error reading string length: %ld", err); return err; @@ -308,7 +308,7 @@ static __always_inline int read_str_to_output(struct expression_context context, if (length > limit) { length = limit; } - err = bpf_probe_read(&context.event->output[*(context.output_offset)], length, (char*)characterPointer); + err = bpf_probe_read_user(&context.event->output[*(context.output_offset)], length, (char*)characterPointer); if (err != 0) { log_debug("error reading string: %ld", err); } diff --git a/pkg/dynamicinstrumentation/codegen/templates.go b/pkg/dynamicinstrumentation/codegen/templates.go index 17c299233b2c6..7d35ae30077f7 100644 --- a/pkg/dynamicinstrumentation/codegen/templates.go +++ b/pkg/dynamicinstrumentation/codegen/templates.go @@ -11,16 +11,16 @@ var headerTemplateText = ` // Name={{.Name}} ID={{.ID}} TotalSize={{.TotalSize}} Kind={{.Kind}} // Write the kind and size to output buffer param_type = {{.Kind}}; -bpf_probe_read(&event->output[outputOffset], sizeof(param_type), ¶m_type); +bpf_probe_read_kernel(&event->output[outputOffset], sizeof(param_type), ¶m_type); param_size = {{.TotalSize}}; -bpf_probe_read(&event->output[outputOffset+1], sizeof(param_size), ¶m_size); +bpf_probe_read_kernel(&event->output[outputOffset+1], sizeof(param_size), ¶m_size); outputOffset += 3; ` var sliceRegisterHeaderTemplateText = ` // Name={{.Parameter.Name}} ID={{.Parameter.ID}} TotalSize={{.Parameter.TotalSize}} Kind={{.Parameter.Kind}} // Write the slice kind to output buffer param_type = {{.Parameter.Kind}}; -bpf_probe_read(&event->output[outputOffset], sizeof(param_type), ¶m_type); +bpf_probe_read_kernel(&event->output[outputOffset], sizeof(param_type), ¶m_type); outputOffset += 1; @@ -42,7 +42,7 @@ var sliceStackHeaderTemplateText = ` // Name={{.Parameter.Name}} ID={{.Parameter.ID}} TotalSize={{.Parameter.TotalSize}} Kind={{.Parameter.Kind}} // Write the slice kind to output buffer param_type = {{.Parameter.Kind}}; -bpf_probe_read(&event->output[outputOffset], sizeof(param_type), ¶m_type); +bpf_probe_read_kernel(&event->output[outputOffset], sizeof(param_type), ¶m_type); outputOffset += 1; @@ -53,7 +53,7 @@ var stringHeaderTemplateText = ` // Name={{.Name}} ID={{.ID}} TotalSize={{.TotalSize}} Kind={{.Kind}} // Write the string kind to output buffer param_type = {{.Kind}}; -bpf_probe_read(&event->output[outputOffset], sizeof(param_type), ¶m_type); +bpf_probe_read_kernel(&event->output[outputOffset], sizeof(param_type), ¶m_type); outputOffset += 1; `