mirror of https://github.com/torvalds/linux.git
bpf: specify the old and new poke_type for bpf_arch_text_poke
In the origin logic, the bpf_arch_text_poke() assume that the old and new instructions have the same opcode. However, they can have different opcode if we want to replace a "call" insn with a "jmp" insn. Therefore, add the new function parameter "old_t" along with the "new_t", which are used to indicate the old and new poke type. Meanwhile, adjust the implement of bpf_arch_text_poke() for all the archs. "BPF_MOD_NOP" is added to make the code more readable. In bpf_arch_text_poke(), we still check if the new and old address is NULL to determine if nop insn should be used, which I think is more safe. Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> Link: https://lore.kernel.org/r/20251118123639.688444-6-dongml2@chinatelecom.cn Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
373f2f44c3
commit
ae4a3160d1
|
|
@ -2934,8 +2934,9 @@ static int gen_branch_or_nop(enum aarch64_insn_branch_type type, void *ip,
|
||||||
* The dummy_tramp is used to prevent another CPU from jumping to unknown
|
* The dummy_tramp is used to prevent another CPU from jumping to unknown
|
||||||
* locations during the patching process, making the patching process easier.
|
* locations during the patching process, making the patching process easier.
|
||||||
*/
|
*/
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
u32 old_insn;
|
u32 old_insn;
|
||||||
|
|
@ -2979,14 +2980,13 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
!poking_bpf_entry))
|
!poking_bpf_entry))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (poke_type == BPF_MOD_CALL)
|
branch_type = old_t == BPF_MOD_CALL ? AARCH64_INSN_BRANCH_LINK :
|
||||||
branch_type = AARCH64_INSN_BRANCH_LINK;
|
AARCH64_INSN_BRANCH_NOLINK;
|
||||||
else
|
|
||||||
branch_type = AARCH64_INSN_BRANCH_NOLINK;
|
|
||||||
|
|
||||||
if (gen_branch_or_nop(branch_type, ip, old_addr, plt, &old_insn) < 0)
|
if (gen_branch_or_nop(branch_type, ip, old_addr, plt, &old_insn) < 0)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
branch_type = new_t == BPF_MOD_CALL ? AARCH64_INSN_BRANCH_LINK :
|
||||||
|
AARCH64_INSN_BRANCH_NOLINK;
|
||||||
if (gen_branch_or_nop(branch_type, ip, new_addr, plt, &new_insn) < 0)
|
if (gen_branch_or_nop(branch_type, ip, new_addr, plt, &new_insn) < 0)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1284,11 +1284,12 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len)
|
||||||
return ret ? ERR_PTR(-EINVAL) : dst;
|
return ret ? ERR_PTR(-EINVAL) : dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
bool is_call = (poke_type == BPF_MOD_CALL);
|
bool is_call;
|
||||||
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
|
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
|
||||||
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
|
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
|
||||||
|
|
||||||
|
|
@ -1298,6 +1299,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
if (!is_bpf_text_address((unsigned long)ip))
|
if (!is_bpf_text_address((unsigned long)ip))
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
is_call = old_t == BPF_MOD_CALL;
|
||||||
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
|
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -1305,6 +1307,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
if (memcmp(ip, old_insns, LOONGARCH_LONG_JUMP_NBYTES))
|
if (memcmp(ip, old_insns, LOONGARCH_LONG_JUMP_NBYTES))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
is_call = new_t == BPF_MOD_CALL;
|
||||||
ret = emit_jump_or_nops(new_addr, ip, new_insns, is_call);
|
ret = emit_jump_or_nops(new_addr, ip, new_insns, is_call);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -1107,8 +1107,9 @@ static void do_isync(void *info __maybe_unused)
|
||||||
* execute isync (or some CSI) so that they don't go back into the
|
* execute isync (or some CSI) so that they don't go back into the
|
||||||
* trampoline again.
|
* trampoline again.
|
||||||
*/
|
*/
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
unsigned long bpf_func, bpf_func_end, size, offset;
|
unsigned long bpf_func, bpf_func_end, size, offset;
|
||||||
ppc_inst_t old_inst, new_inst;
|
ppc_inst_t old_inst, new_inst;
|
||||||
|
|
@ -1119,7 +1120,6 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
bpf_func = (unsigned long)ip;
|
bpf_func = (unsigned long)ip;
|
||||||
branch_flags = poke_type == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
|
|
||||||
|
|
||||||
/* We currently only support poking bpf programs */
|
/* We currently only support poking bpf programs */
|
||||||
if (!__bpf_address_lookup(bpf_func, &size, &offset, name)) {
|
if (!__bpf_address_lookup(bpf_func, &size, &offset, name)) {
|
||||||
|
|
@ -1132,7 +1132,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
* an unconditional branch instruction at im->ip_after_call
|
* an unconditional branch instruction at im->ip_after_call
|
||||||
*/
|
*/
|
||||||
if (offset) {
|
if (offset) {
|
||||||
if (poke_type != BPF_MOD_JUMP) {
|
if (old_t == BPF_MOD_CALL || new_t == BPF_MOD_CALL) {
|
||||||
pr_err("%s (0x%lx): calls are not supported in bpf prog body\n", __func__,
|
pr_err("%s (0x%lx): calls are not supported in bpf prog body\n", __func__,
|
||||||
bpf_func);
|
bpf_func);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
@ -1166,6 +1166,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
}
|
}
|
||||||
|
|
||||||
old_inst = ppc_inst(PPC_RAW_NOP());
|
old_inst = ppc_inst(PPC_RAW_NOP());
|
||||||
|
branch_flags = old_t == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
|
||||||
if (old_addr) {
|
if (old_addr) {
|
||||||
if (is_offset_in_branch_range(ip - old_addr))
|
if (is_offset_in_branch_range(ip - old_addr))
|
||||||
create_branch(&old_inst, ip, (unsigned long)old_addr, branch_flags);
|
create_branch(&old_inst, ip, (unsigned long)old_addr, branch_flags);
|
||||||
|
|
@ -1174,6 +1175,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
branch_flags);
|
branch_flags);
|
||||||
}
|
}
|
||||||
new_inst = ppc_inst(PPC_RAW_NOP());
|
new_inst = ppc_inst(PPC_RAW_NOP());
|
||||||
|
branch_flags = new_t == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
|
||||||
if (new_addr) {
|
if (new_addr) {
|
||||||
if (is_offset_in_branch_range(ip - new_addr))
|
if (is_offset_in_branch_range(ip - new_addr))
|
||||||
create_branch(&new_inst, ip, (unsigned long)new_addr, branch_flags);
|
create_branch(&new_inst, ip, (unsigned long)new_addr, branch_flags);
|
||||||
|
|
|
||||||
|
|
@ -852,17 +852,19 @@ static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
|
||||||
return emit_jump_and_link(is_call ? RV_REG_T0 : RV_REG_ZERO, rvoff, false, &ctx);
|
return emit_jump_and_link(is_call ? RV_REG_T0 : RV_REG_ZERO, rvoff, false, &ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
u32 old_insns[RV_FENTRY_NINSNS], new_insns[RV_FENTRY_NINSNS];
|
u32 old_insns[RV_FENTRY_NINSNS], new_insns[RV_FENTRY_NINSNS];
|
||||||
bool is_call = poke_type == BPF_MOD_CALL;
|
bool is_call;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!is_kernel_text((unsigned long)ip) &&
|
if (!is_kernel_text((unsigned long)ip) &&
|
||||||
!is_bpf_text_address((unsigned long)ip))
|
!is_bpf_text_address((unsigned long)ip))
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
|
|
||||||
|
is_call = old_t == BPF_MOD_CALL;
|
||||||
ret = gen_jump_or_nops(old_addr, ip, old_insns, is_call);
|
ret = gen_jump_or_nops(old_addr, ip, old_insns, is_call);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -870,6 +872,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
|
||||||
if (memcmp(ip, old_insns, RV_FENTRY_NBYTES))
|
if (memcmp(ip, old_insns, RV_FENTRY_NBYTES))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
is_call = new_t == BPF_MOD_CALL;
|
||||||
ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
|
ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
|
|
@ -2413,8 +2413,9 @@ bool bpf_jit_supports_far_kfunc_call(void)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
struct bpf_plt expected_plt, current_plt, new_plt, *plt;
|
struct bpf_plt expected_plt, current_plt, new_plt, *plt;
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -2431,7 +2432,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||||
if (insn.opc != (0xc004 | (old_addr ? 0xf0 : 0)))
|
if (insn.opc != (0xc004 | (old_addr ? 0xf0 : 0)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (t == BPF_MOD_JUMP &&
|
if ((new_t == BPF_MOD_JUMP || old_t == BPF_MOD_JUMP) &&
|
||||||
insn.disp == ((char *)new_addr - (char *)ip) >> 1) {
|
insn.disp == ((char *)new_addr - (char *)ip) >> 1) {
|
||||||
/*
|
/*
|
||||||
* The branch already points to the destination,
|
* The branch already points to the destination,
|
||||||
|
|
|
||||||
|
|
@ -597,7 +597,8 @@ static int emit_jump(u8 **pprog, void *func, void *ip)
|
||||||
return emit_patch(pprog, func, ip, 0xE9);
|
return emit_patch(pprog, func, ip, 0xE9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
|
enum bpf_text_poke_type new_t,
|
||||||
void *old_addr, void *new_addr)
|
void *old_addr, void *new_addr)
|
||||||
{
|
{
|
||||||
const u8 *nop_insn = x86_nops[5];
|
const u8 *nop_insn = x86_nops[5];
|
||||||
|
|
@ -607,9 +608,9 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
memcpy(old_insn, nop_insn, X86_PATCH_SIZE);
|
memcpy(old_insn, nop_insn, X86_PATCH_SIZE);
|
||||||
if (old_addr) {
|
if (old_t != BPF_MOD_NOP && old_addr) {
|
||||||
prog = old_insn;
|
prog = old_insn;
|
||||||
ret = t == BPF_MOD_CALL ?
|
ret = old_t == BPF_MOD_CALL ?
|
||||||
emit_call(&prog, old_addr, ip) :
|
emit_call(&prog, old_addr, ip) :
|
||||||
emit_jump(&prog, old_addr, ip);
|
emit_jump(&prog, old_addr, ip);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
@ -617,9 +618,9 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(new_insn, nop_insn, X86_PATCH_SIZE);
|
memcpy(new_insn, nop_insn, X86_PATCH_SIZE);
|
||||||
if (new_addr) {
|
if (new_t != BPF_MOD_NOP && new_addr) {
|
||||||
prog = new_insn;
|
prog = new_insn;
|
||||||
ret = t == BPF_MOD_CALL ?
|
ret = new_t == BPF_MOD_CALL ?
|
||||||
emit_call(&prog, new_addr, ip) :
|
emit_call(&prog, new_addr, ip) :
|
||||||
emit_jump(&prog, new_addr, ip);
|
emit_jump(&prog, new_addr, ip);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
@ -640,8 +641,9 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *old_addr, void *new_addr)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
if (!is_kernel_text((long)ip) &&
|
if (!is_kernel_text((long)ip) &&
|
||||||
!is_bpf_text_address((long)ip))
|
!is_bpf_text_address((long)ip))
|
||||||
|
|
@ -655,7 +657,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
||||||
if (is_endbr(ip))
|
if (is_endbr(ip))
|
||||||
ip += ENDBR_INSN_SIZE;
|
ip += ENDBR_INSN_SIZE;
|
||||||
|
|
||||||
return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
|
return __bpf_arch_text_poke(ip, old_t, new_t, old_addr, new_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
|
#define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
|
||||||
|
|
@ -897,12 +899,13 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
|
||||||
target = array->ptrs[poke->tail_call.key];
|
target = array->ptrs[poke->tail_call.key];
|
||||||
if (target) {
|
if (target) {
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
||||||
BPF_MOD_JUMP, NULL,
|
BPF_MOD_NOP, BPF_MOD_JUMP,
|
||||||
|
NULL,
|
||||||
(u8 *)target->bpf_func +
|
(u8 *)target->bpf_func +
|
||||||
poke->adj_off);
|
poke->adj_off);
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
||||||
BPF_MOD_JUMP,
|
BPF_MOD_JUMP, BPF_MOD_NOP,
|
||||||
(u8 *)poke->tailcall_target +
|
(u8 *)poke->tailcall_target +
|
||||||
X86_PATCH_SIZE, NULL);
|
X86_PATCH_SIZE, NULL);
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
|
|
@ -3985,6 +3988,7 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
|
||||||
struct bpf_prog *new, struct bpf_prog *old)
|
struct bpf_prog *new, struct bpf_prog *old)
|
||||||
{
|
{
|
||||||
u8 *old_addr, *new_addr, *old_bypass_addr;
|
u8 *old_addr, *new_addr, *old_bypass_addr;
|
||||||
|
enum bpf_text_poke_type t;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
old_bypass_addr = old ? NULL : poke->bypass_addr;
|
old_bypass_addr = old ? NULL : poke->bypass_addr;
|
||||||
|
|
@ -3997,21 +4001,22 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
|
||||||
* the kallsyms check.
|
* the kallsyms check.
|
||||||
*/
|
*/
|
||||||
if (new) {
|
if (new) {
|
||||||
|
t = old_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
||||||
BPF_MOD_JUMP,
|
t, BPF_MOD_JUMP,
|
||||||
old_addr, new_addr);
|
old_addr, new_addr);
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
if (!old) {
|
if (!old) {
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
||||||
BPF_MOD_JUMP,
|
BPF_MOD_JUMP, BPF_MOD_NOP,
|
||||||
poke->bypass_addr,
|
poke->bypass_addr,
|
||||||
NULL);
|
NULL);
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
t = old_bypass_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
|
||||||
BPF_MOD_JUMP,
|
t, BPF_MOD_JUMP, old_bypass_addr,
|
||||||
old_bypass_addr,
|
|
||||||
poke->bypass_addr);
|
poke->bypass_addr);
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
/* let other CPUs finish the execution of program
|
/* let other CPUs finish the execution of program
|
||||||
|
|
@ -4020,9 +4025,9 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
|
||||||
*/
|
*/
|
||||||
if (!ret)
|
if (!ret)
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
t = old_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
|
||||||
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
ret = __bpf_arch_text_poke(poke->tailcall_target,
|
||||||
BPF_MOD_JUMP,
|
t, BPF_MOD_NOP, old_addr, NULL);
|
||||||
old_addr, NULL);
|
|
||||||
BUG_ON(ret < 0);
|
BUG_ON(ret < 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3710,12 +3710,14 @@ static inline u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
|
||||||
#endif /* CONFIG_INET */
|
#endif /* CONFIG_INET */
|
||||||
|
|
||||||
enum bpf_text_poke_type {
|
enum bpf_text_poke_type {
|
||||||
|
BPF_MOD_NOP,
|
||||||
BPF_MOD_CALL,
|
BPF_MOD_CALL,
|
||||||
BPF_MOD_JUMP,
|
BPF_MOD_JUMP,
|
||||||
};
|
};
|
||||||
|
|
||||||
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *addr1, void *addr2);
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr);
|
||||||
|
|
||||||
void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
|
void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
|
||||||
struct bpf_prog *new, struct bpf_prog *old);
|
struct bpf_prog *new, struct bpf_prog *old);
|
||||||
|
|
|
||||||
|
|
@ -3150,8 +3150,9 @@ int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __weak bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
|
int __weak bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
|
||||||
void *addr1, void *addr2)
|
enum bpf_text_poke_type new_t, void *old_addr,
|
||||||
|
void *new_addr)
|
||||||
{
|
{
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,8 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
|
||||||
if (tr->func.ftrace_managed)
|
if (tr->func.ftrace_managed)
|
||||||
ret = unregister_ftrace_direct(tr->fops, (long)old_addr, false);
|
ret = unregister_ftrace_direct(tr->fops, (long)old_addr, false);
|
||||||
else
|
else
|
||||||
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
|
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, BPF_MOD_NOP,
|
||||||
|
old_addr, NULL);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -200,7 +201,10 @@ static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_ad
|
||||||
else
|
else
|
||||||
ret = modify_ftrace_direct_nolock(tr->fops, (long)new_addr);
|
ret = modify_ftrace_direct_nolock(tr->fops, (long)new_addr);
|
||||||
} else {
|
} else {
|
||||||
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, new_addr);
|
ret = bpf_arch_text_poke(ip,
|
||||||
|
old_addr ? BPF_MOD_CALL : BPF_MOD_NOP,
|
||||||
|
new_addr ? BPF_MOD_CALL : BPF_MOD_NOP,
|
||||||
|
old_addr, new_addr);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +229,8 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
|
||||||
return ret;
|
return ret;
|
||||||
ret = register_ftrace_direct(tr->fops, (long)new_addr);
|
ret = register_ftrace_direct(tr->fops, (long)new_addr);
|
||||||
} else {
|
} else {
|
||||||
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr);
|
ret = bpf_arch_text_poke(ip, BPF_MOD_NOP, BPF_MOD_CALL,
|
||||||
|
NULL, new_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -336,8 +341,9 @@ static void bpf_tramp_image_put(struct bpf_tramp_image *im)
|
||||||
* call_rcu_tasks() is not necessary.
|
* call_rcu_tasks() is not necessary.
|
||||||
*/
|
*/
|
||||||
if (im->ip_after_call) {
|
if (im->ip_after_call) {
|
||||||
int err = bpf_arch_text_poke(im->ip_after_call, BPF_MOD_JUMP,
|
int err = bpf_arch_text_poke(im->ip_after_call, BPF_MOD_NOP,
|
||||||
NULL, im->ip_epilogue);
|
BPF_MOD_JUMP, NULL,
|
||||||
|
im->ip_epilogue);
|
||||||
WARN_ON(err);
|
WARN_ON(err);
|
||||||
if (IS_ENABLED(CONFIG_TASKS_RCU))
|
if (IS_ENABLED(CONFIG_TASKS_RCU))
|
||||||
call_rcu_tasks(&im->rcu, __bpf_tramp_image_put_rcu_tasks);
|
call_rcu_tasks(&im->rcu, __bpf_tramp_image_put_rcu_tasks);
|
||||||
|
|
@ -570,7 +576,8 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
tr->extension_prog = link->link.prog;
|
tr->extension_prog = link->link.prog;
|
||||||
return bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP, NULL,
|
return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
|
||||||
|
BPF_MOD_JUMP, NULL,
|
||||||
link->link.prog->bpf_func);
|
link->link.prog->bpf_func);
|
||||||
}
|
}
|
||||||
if (cnt >= BPF_MAX_TRAMP_LINKS)
|
if (cnt >= BPF_MAX_TRAMP_LINKS)
|
||||||
|
|
@ -618,6 +625,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
|
||||||
if (kind == BPF_TRAMP_REPLACE) {
|
if (kind == BPF_TRAMP_REPLACE) {
|
||||||
WARN_ON_ONCE(!tr->extension_prog);
|
WARN_ON_ONCE(!tr->extension_prog);
|
||||||
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP,
|
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP,
|
||||||
|
BPF_MOD_NOP,
|
||||||
tr->extension_prog->bpf_func, NULL);
|
tr->extension_prog->bpf_func, NULL);
|
||||||
tr->extension_prog = NULL;
|
tr->extension_prog = NULL;
|
||||||
guard(mutex)(&tgt_prog->aux->ext_mutex);
|
guard(mutex)(&tgt_prog->aux->ext_mutex);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue