전역 변수가 포함된 간단한 ebpf 코드: 할당 실패

전역 변수가 포함된 간단한 ebpf 코드: 할당 실패

전역 변수가 거의 없는 간단한 ebpf 테스트 코드가 있습니다(내가 아는 한 전역 변수는 내 버전(5.13 Linux)의 매핑 메커니즘을 통해 액세스됩니다). 코드는 다음과 같습니다.

int global_var = 911;
int * global_ptr = &global_var;

int __attribute__ ((noinline)) assign_value_via_var(void) {
    global_var = 119;
    return global_var;
}
int __attribute__ ((noinline)) assign_value_via_ptr1(void) {
    global_var = 118; 
    return *global_ptr;
}
int __attribute__ ((noinline)) assign_value_via_ptr2(void) {
    *global_ptr = 912; 
    return *global_ptr;
}
SEC("tracepoint/syscalls/sys_enter_execve")
int tracepoint__syscalls__sys_enter_execve_(struct trace_event_raw_sys_enter *ctx)
{
    bpf_printk("--before assignment-- global_var = %d \n",global_var);
    assign_value_via_var();
    bpf_printk("--after assignment-- global_var = %d \n",global_var);
    assign_value_via_ptr1();
    bpf_printk("--after  assignment-- global_var = %d \n",global_var);
    assign_value_via_ptr2();test
    bpf_printk("--after  assignment-- global_var = %d \n",global_var);
    return 0;
}

위의 코드는 할당_값_비아_ptr1 및 할당_값_비아_ptr2 함수에서 "R1 잘못된 메모리 액세스 'inv'" 오류를 발행하도록 유효성 검사기를 트리거합니다. 다음은 할당_값_비아_ptr1에 대한 검증자 로그입니다.

Validating assign_value_via_ptr1() func#2...
; global_var = 118;
32: (18) r1 = 0xffffc181c0224000
34: (b4) w2 = 118
35: (63) *(u32 *)(r1 +0) = r2
 R1_w=map_value(id=0,off=0,ks=4,vs=5040,imm=0) R2_w=invP118 R10=fp0
; return *global_ptr;
36: (18) r1 = 0xffffc181c0224008
38: (79) r1 = *(u64 *)(r1 +0)
 R1_w=map_value(id=0,off=8,ks=4,vs=5040,imm=0) R2_w=invP118 R10=fp0
; return *global_ptr;
39: (61) r0 = *(u32 *)(r1 +0)
R1 invalid mem access 'inv'

다음은 할당_값_비아_ptr2에 대한 검증자 로그입니다.

Validating assign_value_via_ptr2() func#2...
; *global_ptr = 912;
32: (18) r1 = 0xffffc181c0224008
34: (79) r1 = *(u64 *)(r1 +0)
 R1_w=map_value(id=0,off=8,ks=4,vs=5040,imm=0) R10=fp0
35: (b4) w2 = 912
; *global_ptr = 912;
36: (63) *(u32 *)(r1 +0) = r2
R1 invalid mem access 'inv'

위의 두 기능을 다음과 같이 변경하면. 모든 것이 잘 작동하기 시작했습니다.

int __attribute__ ((noinline)) assign_value_via_ptr1(void) {
    return *global_ptr;
}
int __attribute__ ((noinline)) assign_value_via_ptr2(void) {
    return *global_ptr;
}

누구든지 이에 대한 근거를 설명하는 데 도움을 줄 수 있습니까? 감사해요.

참고로 다음은 이러한 함수의 바이트코드입니다.

0000000000000000 assign_value_via_var:
;       global_var = 119;
       0:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
                0000000000000000:  R_BPF_64_64  global_var
       2:       b4 02 00 00 77 00 00 00 w2 = 119
       3:       63 21 00 00 00 00 00 00 *(u32 *)(r1 + 0) = r2
;       return global_var;
       4:       b4 00 00 00 77 00 00 00 w0 = 119
       5:       95 00 00 00 00 00 00 00 exit

0000000000000030 assign_value_via_ptr1:
;       global_var = 118;
       6:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
                0000000000000030:  R_BPF_64_64  global_var
       8:       b4 02 00 00 76 00 00 00 w2 = 118
       9:       63 21 00 00 00 00 00 00 *(u32 *)(r1 + 0) = r2
;       return *global_ptr;
      10:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
                0000000000000050:  R_BPF_64_64  global_ptr
      12:       79 11 00 00 00 00 00 00 r1 = *(u64 *)(r1 + 0)
      13:       61 10 00 00 00 00 00 00 r0 = *(u32 *)(r1 + 0)
      14:       95 00 00 00 00 00 00 00 exit

0000000000000078 assign_value_via_ptr2:
;       *global_ptr = 912;
      15:       18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 r1 = 0 ll
                0000000000000078:  R_BPF_64_64  global_ptr
      17:       79 11 00 00 00 00 00 00 r1 = *(u64 *)(r1 + 0)
      18:       b4 02 00 00 90 03 00 00 w2 = 912
      19:       63 21 00 00 00 00 00 00 *(u32 *)(r1 + 0) = r2
;       return *global_ptr;
      20:       b4 00 00 00 90 03 00 00 w0 = 912
      21:       95 00 00 00 00 00 00 00 exit

관련 정보