forked from luck/tmp_suning_uos_patched
af9bd3e333
Currently, BPF programs with kprobe/sys_connect does not work properly. Commit34745aed51
("samples/bpf: fix kprobe attachment issue on x64") This commit modifies the bpf_load behavior of kprobe events in the x64 architecture. If the current kprobe event target starts with "sys_*", add the prefix "__x64_" to the front of the event. Appending "__x64_" prefix with kprobe/sys_* event was appropriate as a solution to most of the problems caused by the commit below. commitd5a00528b5
("syscalls/core, syscalls/x86: Rename struct pt_regs-based sys_*() to __x64_sys_*()") However, there is a problem with the sys_connect kprobe event that does not work properly. For __sys_connect event, parameters can be fetched normally, but for __x64_sys_connect, parameters cannot be fetched. ffffffff818d3520 <__x64_sys_connect>: ffffffff818d3520: e8 fb df 32 00 callq 0xffffffff81c01520 <__fentry__> ffffffff818d3525: 48 8b 57 60 movq 96(%rdi), %rdx ffffffff818d3529: 48 8b 77 68 movq 104(%rdi), %rsi ffffffff818d352d: 48 8b 7f 70 movq 112(%rdi), %rdi ffffffff818d3531: e8 1a ff ff ff callq 0xffffffff818d3450 <__sys_connect> ffffffff818d3536: 48 98 cltq ffffffff818d3538: c3 retq ffffffff818d3539: 0f 1f 80 00 00 00 00 nopl (%rax) As the assembly code for __x64_sys_connect shows, parameters should be fetched and set into rdi, rsi, rdx registers prior to calling __sys_connect. Because of this problem, this commit fixes the sys_connect event by first getting the value of the rdi register and then the value of the rdi, rsi, and rdx register through an offset based on that value. Fixes:34745aed51
("samples/bpf: fix kprobe attachment issue on x64") Signed-off-by: Daniel T. Lee <danieltimlee@gmail.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200707184855.30968-2-danieltimlee@gmail.com
57 lines
1.8 KiB
C
57 lines
1.8 KiB
C
/* Copyright (c) 2016 Sargun Dhillon <sargun@sargun.me>
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of version 2 of the GNU General Public
|
|
* License as published by the Free Software Foundation.
|
|
*/
|
|
#include <linux/skbuff.h>
|
|
#include <linux/netdevice.h>
|
|
#include <uapi/linux/bpf.h>
|
|
#include <linux/version.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
#include <bpf/bpf_core_read.h>
|
|
#include "trace_common.h"
|
|
|
|
struct bpf_map_def SEC("maps") dnat_map = {
|
|
.type = BPF_MAP_TYPE_HASH,
|
|
.key_size = sizeof(struct sockaddr_in),
|
|
.value_size = sizeof(struct sockaddr_in),
|
|
.max_entries = 256,
|
|
};
|
|
|
|
/* kprobe is NOT a stable ABI
|
|
* kernel functions can be removed, renamed or completely change semantics.
|
|
* Number of arguments and their positions can change, etc.
|
|
* In such case this bpf+kprobe example will no longer be meaningful
|
|
*
|
|
* This example sits on a syscall, and the syscall ABI is relatively stable
|
|
* of course, across platforms, and over time, the ABI may change.
|
|
*/
|
|
SEC("kprobe/" SYSCALL(sys_connect))
|
|
int bpf_prog1(struct pt_regs *ctx)
|
|
{
|
|
struct pt_regs *real_regs = (struct pt_regs *)PT_REGS_PARM1_CORE(ctx);
|
|
void *sockaddr_arg = (void *)PT_REGS_PARM2_CORE(real_regs);
|
|
int sockaddr_len = (int)PT_REGS_PARM3_CORE(real_regs);
|
|
struct sockaddr_in new_addr, orig_addr = {};
|
|
struct sockaddr_in *mapped_addr;
|
|
|
|
if (sockaddr_len > sizeof(orig_addr))
|
|
return 0;
|
|
|
|
if (bpf_probe_read_user(&orig_addr, sizeof(orig_addr), sockaddr_arg) != 0)
|
|
return 0;
|
|
|
|
mapped_addr = bpf_map_lookup_elem(&dnat_map, &orig_addr);
|
|
if (mapped_addr != NULL) {
|
|
memcpy(&new_addr, mapped_addr, sizeof(new_addr));
|
|
bpf_probe_write_user(sockaddr_arg, &new_addr,
|
|
sizeof(new_addr));
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
char _license[] SEC("license") = "GPL";
|
|
u32 _version SEC("version") = LINUX_VERSION_CODE;
|