google / buzzer

Apache License 2.0
423 stars 30 forks source link

Support MovReg64 #45

Closed Lincyaw closed 4 months ago

Lincyaw commented 9 months ago

The current implementation cannot support the MovReg64 well.

In pkg/ebpf/alu_instructions.go, although there is a function called MovRegImm64, however, the arguments only supports the imm32.

// MovRegImm64 sets re to the specified value
func MovRegImm64(reg *Register, imm int32) *AluImmInstruction {
    return NewAluImmInstruction(AluMov, InsClassAlu64, reg, imm)
}

Example

For the following simple ebpf program

#define BPF_NO_GLOBAL_DATA
#include <linux/bpf.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

typedef unsigned int u32;
typedef int pid_t;
const pid_t pid_filter = 0;

char LICENSE[] SEC("license") = "Dual BSD/GPL";

SEC("tp/syscalls/sys_enter_write")
int handle_tp(void *ctx)
{
 pid_t pid = bpf_get_current_pid_tgid() >> 32;
 if (pid_filter && pid != pid_filter)
  return 0;
 bpf_printk("BPF triggered sys_enter_write from PID %d.\n", pid);
 return 0;
}

The disassembled result is:

Disassembly of section tp/syscalls/sys_enter_write:

0000000000000000 <handle_tp>:
       0:   85 00 00 00 0e 00 00 00 call 0xe
       1:   b7 01 00 00 64 2e 0a 00 r1 = 0xa2e64
       2:   63 1a f8 ff 00 00 00 00 *(u32 *)(r10 - 0x8) = r1
       3:   18 01 00 00 6f 6d 20 50 00 00 00 00 49 44 20 25 r1 = 0x2520444950206d6f ll
       5:   7b 1a f0 ff 00 00 00 00 *(u64 *)(r10 - 0x10) = r1
       6:   18 01 00 00 77 72 69 74 00 00 00 00 65 20 66 72 r1 = 0x7266206574697277 ll
       8:   7b 1a e8 ff 00 00 00 00 *(u64 *)(r10 - 0x18) = r1
       9:   18 01 00 00 73 5f 65 6e 00 00 00 00 74 65 72 5f r1 = 0x5f7265746e655f73 ll
      11:   7b 1a e0 ff 00 00 00 00 *(u64 *)(r10 - 0x20) = r1
      12:   18 01 00 00 67 65 72 65 00 00 00 00 64 20 73 79 r1 = 0x7973206465726567 ll
      14:   7b 1a d8 ff 00 00 00 00 *(u64 *)(r10 - 0x28) = r1
      15:   18 01 00 00 42 50 46 20 00 00 00 00 74 72 69 67 r1 = 0x6769727420465042 ll
      17:   7b 1a d0 ff 00 00 00 00 *(u64 *)(r10 - 0x30) = r1
      18:   77 00 00 00 20 00 00 00 r0 >>= 0x20
      19:   bf a1 00 00 00 00 00 00 r1 = r10
      20:   07 01 00 00 d0 ff ff ff r1 += -0x30
      21:   b7 02 00 00 2c 00 00 00 r2 = 0x2c
      22:   bf 03 00 00 00 00 00 00 r3 = r0
      23:   85 00 00 00 06 00 00 00 call 0x6
      24:   b7 00 00 00 00 00 00 00 r0 = 0x0
      25:   95 00 00 00 00 00 00 00 exit

There are instructions that load imm64 to the register, however in the code, it only supports imm64.

Lincyaw commented 9 months ago

https://docs.kernel.org/bpf/standardization/instruction-set.html#bit-immediate-instructions

According to the documentation, MovRegImm64 is a part of 64 bit operation, the operation code should be 0x18. However, it seems that there is no support for 64-bit immediate instructions.

image
thatjiaozi commented 9 months ago

Thanks!

That is a very nice catch. I will try to add support for this as soon as possible.

It seems that for immediate 64 bit values a wide instruction encoding is used https://docs.kernel.org/bpf/standardization/instruction-set.html#instruction-encoding:~:text=Thus%20the%2064,next_imm%20%3C%3C%2032)%20%7C%20imm