Skip to content

Commit bcc2287

Browse files
fix(ebpf): use dynamic offset for linux_binprm.filename and interp (#53068)
### What does this PR do? Replace direct `&bprm->filename` and `&bprm->interp` accesses with LOAD_CONSTANT-based offsets. ### Motivation Direct field access relies on compile-time struct layout from the kernel headers the program was built against. When the running kernel has a different layout (different version, different CONFIG_ options), the read silently targets the wrong memory location, causing corrupt security events. The LOAD_CONSTANT mechanism resolves offsets at eBPF load time via BTF (or other fallbacks), making the programs portable across kernel versions. ### Describe how you validated your changes Existing functional tests. ### Additional Notes Memory layout on a 6.17.0-29-generic Ubuntu kernel: ``` struct linux_binprm { struct vm_area_struct * vma; /* 0 8 */ long unsigned int vma_pages; /* 8 8 */ long unsigned int argmin; /* 16 8 */ struct mm_struct * mm; /* 24 8 */ long unsigned int p; /* 32 8 */ unsigned int have_execfd:1; /* 40: 0 4 */ unsigned int execfd_creds:1; /* 40: 1 4 */ unsigned int secureexec:1; /* 40: 2 4 */ unsigned int point_of_no_return:1; /* 40: 3 4 */ unsigned int comm_from_dentry:1; /* 40: 4 4 */ unsigned int is_check:1; /* 40: 5 4 */ /* XXX 26 bits hole, try to pack */ /* XXX 4 bytes hole, try to pack */ struct file * executable; /* 48 8 */ struct file * interpreter; /* 56 8 */ /* --- cacheline 1 boundary (64 bytes) --- */ struct file * file; /* 64 8 */ struct cred * cred; /* 72 8 */ int unsafe; /* 80 4 */ unsigned int per_clear; /* 84 4 */ int argc; /* 88 4 */ int envc; /* 92 4 */ const char * filename; /* 96 8 */ const char * interp; /* 104 8 */ const char * fdpath; /* 112 8 */ unsigned int interp_flags; /* 120 4 */ int execfd; /* 124 4 */ /* --- cacheline 2 boundary (128 bytes) --- */ long unsigned int exec; /* 128 8 */ struct rlimit rlim_stack; /* 136 16 */ char buf[256]; /* 152 256 */ /* size: 408, cachelines: 7, members: 27 */ /* sum members: 400, holes: 1, sum holes: 4 */ /* sum bitfield members: 6 bits, bit holes: 1, sum bit holes: 26 bits */ /* last cacheline: 24 bytes */ }; ``` Co-authored-by: dd-octo-sts[bot] <200755185+dd-octo-sts[bot]@users.noreply.github.com> Co-authored-by: yoann.ghigoff <yoann.ghigoff@datadoghq.com>
1 parent 99fc854 commit bcc2287

6 files changed

Lines changed: 574 additions & 3 deletions

File tree

pkg/security/ebpf/c/include/hooks/exec.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,11 +665,16 @@ int __attribute__((always_inline)) fetch_interpreter(void *ctx, struct linux_bin
665665

666666
bpf_printk("interpreter file: %llx", interpreter);
667667

668+
u64 binprm_filename_offset;
669+
LOAD_CONSTANT("linux_binprm_filename_offset", binprm_filename_offset);
670+
u64 binprm_interp_offset;
671+
LOAD_CONSTANT("linux_binprm_interp_offset", binprm_interp_offset);
672+
668673
const char *s;
669-
bpf_probe_read(&s, sizeof(s), &bprm->filename);
674+
bpf_probe_read(&s, sizeof(s), (char *)bprm + binprm_filename_offset);
670675
bpf_printk("*filename from binprm: %s", s);
671676

672-
bpf_probe_read(&s, sizeof(s), &bprm->interp);
677+
bpf_probe_read(&s, sizeof(s), (char *)bprm + binprm_interp_offset);
673678
bpf_printk("*interp from binprm: %s", s);
674679
#endif
675680

0 commit comments

Comments
 (0)