bpftrace / bpftrace

High-level tracing language for Linux
Apache License 2.0
8.69k stars 1.36k forks source link

How to access uprobe global variables #3613

Closed honghaier250 closed 2 days ago

honghaier250 commented 3 days ago

What reproduces the bug? Provide code if possible.

I want access nginx global variables: ngx_accept_disabled,but can not get correct value

bpftrace -e 'uprobe:/usr/local/nginx/sbin/nginx:ngx_process_events_and_timers  {printf("%d, %d\n", pid, *(int64*)uaddr("ngx_accept_disabled")); }'

349471, 0

bpftrace --info output

System
  OS: Linux 6.11.2-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.11.2-1kali1 (2024-10-15)
  Arch: x86_64

Build
  version: v0.21.0-235-gf0f6
  LLVM: 13.0.1
  bfd: yes
  liblldb (DWARF support): yes
  libsystemd (systemd notify support): no

Kernel helpers
  probe_read: yes
  probe_read_str: yes
  probe_read_user: yes
  probe_read_user_str: yes
  probe_read_kernel: yes
  probe_read_kernel_str: yes
  get_current_cgroup_id: yes
  send_signal: yes
  override_return: no
  get_boot_ns: yes
  dpath: yes
  skboutput: yes
  get_tai_ns: yes
  get_func_ip: yes
  jiffies64: yes
  for_each_map_elem: yes

Kernel features
  Instruction limit: 1000000
  Loop support: yes
  btf: yes
  module btf: yes
  Kernel DWARF: yes
  map batch: yes
  uprobe refcount (depends on Build:bcc bpf_attach_uprobe refcount): yes

Map types
  hash: yes
  percpu hash: yes
  array: yes
  percpu array: yes
  stack_trace: yes
  perf_event_array: yes
  ringbuf: yes

Probe types
  kprobe: yes
  tracepoint: yes
  perf_event: yes
  fentry: yes
  kprobe_multi: yes
  uprobe_multi: yes
  iter: yes

nginx -V output

nginx version: nginx/1.21.4.1
built by gcc 14.2.0 (Debian 14.2.0-3)
built with OpenSSL 3.3.0-dev  (running with OpenSSL 3.3.2 3 Sep 2024)
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --with-debug --with-cc-opt='-g3 -O0 -Wall -Werror -fno-omit-frame-pointer  --with-ld-opt='-lssl -lcrypto' --with-http_sub_module --with-stream_ssl_preread_module --with-http_realip_module --with-stream_realip_module --with-http_stub_status_module --with-http_v2_module --http-fastcgi-temp-path=/dev/null --http-uwsgi-temp-path=/dev/null --http-scgi-temp-path=/dev/null --http-client-body-temp-path=logs/client-body-temp --http-proxy-temp-path=logs/proxy-temp --with-stream --with-stream_ssl_module --with-http_ssl_module
ajor commented 3 days ago

Do you know if ASLR is affecting your nginx? uaddr() does not work in the presence of ASLR.

The outputs of the following two commands will give us the answer if you're not sure:

If both answers are "yes", then ASLR will be enabled for your nginx.

You could either:

  1. Recompile nginx without -pie
  2. Disable ASLR system-wide by writing 0 to /proc/sys/kernel/randomize_va_space
  3. Determine the ASLR base offset being applied to your running nginx and add that to the result of uaddr() before dereferencing the pointer.
honghaier250 commented 2 days ago

@ajor However, I already disable ASLR by: echo 0 > /proc/sys/kernel/randomize_va_space

honghaier250 commented 2 days ago

I know, it should plus base address 0x555555554000

#!/usr/bin/env bpftrace

uprobe:/usr/local/nginx/sbin/nginx:ngx_process_events_and_timers {
    $base = (uint64)0x555555554000;
    $offset = (uint32)uaddr("ngx_accept_disabled");
    $ngx_accept_disabled = *(int64*)($base + $offset);
    printf("%d, %ld\n", pid,, $ngx_accept_disabled);
}