Skip to content

Commit bf0c6e2

Browse files
image-dragonKernel Patches Daemon
authored andcommitted
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 <[email protected]>
1 parent b971ba7 commit bf0c6e2

File tree

9 files changed

+71
-46
lines changed

9 files changed

+71
-46
lines changed

arch/arm64/net/bpf_jit_comp.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2923,8 +2923,9 @@ static int gen_branch_or_nop(enum aarch64_insn_branch_type type, void *ip,
29232923
* The dummy_tramp is used to prevent another CPU from jumping to unknown
29242924
* locations during the patching process, making the patching process easier.
29252925
*/
2926-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
2927-
void *old_addr, void *new_addr)
2926+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
2927+
enum bpf_text_poke_type new_t, void *old_addr,
2928+
void *new_addr)
29282929
{
29292930
int ret;
29302931
u32 old_insn;
@@ -2968,14 +2969,13 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
29682969
!poking_bpf_entry))
29692970
return -EINVAL;
29702971

2971-
if (poke_type == BPF_MOD_CALL)
2972-
branch_type = AARCH64_INSN_BRANCH_LINK;
2973-
else
2974-
branch_type = AARCH64_INSN_BRANCH_NOLINK;
2975-
2972+
branch_type = old_t == BPF_MOD_CALL ? AARCH64_INSN_BRANCH_LINK :
2973+
AARCH64_INSN_BRANCH_NOLINK;
29762974
if (gen_branch_or_nop(branch_type, ip, old_addr, plt, &old_insn) < 0)
29772975
return -EFAULT;
29782976

2977+
branch_type = new_t == BPF_MOD_CALL ? AARCH64_INSN_BRANCH_LINK :
2978+
AARCH64_INSN_BRANCH_NOLINK;
29792979
if (gen_branch_or_nop(branch_type, ip, new_addr, plt, &new_insn) < 0)
29802980
return -EFAULT;
29812981

arch/loongarch/net/bpf_jit.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1284,11 +1284,12 @@ void *bpf_arch_text_copy(void *dst, void *src, size_t len)
12841284
return ret ? ERR_PTR(-EINVAL) : dst;
12851285
}
12861286

1287-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
1288-
void *old_addr, void *new_addr)
1287+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
1288+
enum bpf_text_poke_type new_t, void *old_addr,
1289+
void *new_addr)
12891290
{
12901291
int ret;
1291-
bool is_call = (poke_type == BPF_MOD_CALL);
1292+
bool is_call;
12921293
u32 old_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
12931294
u32 new_insns[LOONGARCH_LONG_JUMP_NINSNS] = {[0 ... 4] = INSN_NOP};
12941295

@@ -1298,13 +1299,15 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
12981299
if (!is_bpf_text_address((unsigned long)ip))
12991300
return -ENOTSUPP;
13001301

1302+
is_call = old_t == BPF_MOD_CALL;
13011303
ret = emit_jump_or_nops(old_addr, ip, old_insns, is_call);
13021304
if (ret)
13031305
return ret;
13041306

13051307
if (memcmp(ip, old_insns, LOONGARCH_LONG_JUMP_NBYTES))
13061308
return -EFAULT;
13071309

1310+
is_call = new_t == BPF_MOD_CALL;
13081311
ret = emit_jump_or_nops(new_addr, ip, new_insns, is_call);
13091312
if (ret)
13101313
return ret;

arch/powerpc/net/bpf_jit_comp.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,8 +1107,9 @@ static void do_isync(void *info __maybe_unused)
11071107
* execute isync (or some CSI) so that they don't go back into the
11081108
* trampoline again.
11091109
*/
1110-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
1111-
void *old_addr, void *new_addr)
1110+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
1111+
enum bpf_text_poke_type new_t, void *old_addr,
1112+
void *new_addr)
11121113
{
11131114
unsigned long bpf_func, bpf_func_end, size, offset;
11141115
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,
11191120
return -EOPNOTSUPP;
11201121

11211122
bpf_func = (unsigned long)ip;
1122-
branch_flags = poke_type == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
11231123

11241124
/* We currently only support poking bpf programs */
11251125
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,
11321132
* an unconditional branch instruction at im->ip_after_call
11331133
*/
11341134
if (offset) {
1135-
if (poke_type != BPF_MOD_JUMP) {
1135+
if (old_t == BPF_MOD_CALL || new_t == BPF_MOD_CALL) {
11361136
pr_err("%s (0x%lx): calls are not supported in bpf prog body\n", __func__,
11371137
bpf_func);
11381138
return -EOPNOTSUPP;
@@ -1166,6 +1166,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
11661166
}
11671167

11681168
old_inst = ppc_inst(PPC_RAW_NOP());
1169+
branch_flags = old_t == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
11691170
if (old_addr) {
11701171
if (is_offset_in_branch_range(ip - old_addr))
11711172
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,
11741175
branch_flags);
11751176
}
11761177
new_inst = ppc_inst(PPC_RAW_NOP());
1178+
branch_flags = new_t == BPF_MOD_CALL ? BRANCH_SET_LINK : 0;
11771179
if (new_addr) {
11781180
if (is_offset_in_branch_range(ip - new_addr))
11791181
create_branch(&new_inst, ip, (unsigned long)new_addr, branch_flags);

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -852,24 +852,27 @@ static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
852852
return emit_jump_and_link(is_call ? RV_REG_T0 : RV_REG_ZERO, rvoff, false, &ctx);
853853
}
854854

855-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type,
856-
void *old_addr, void *new_addr)
855+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
856+
enum bpf_text_poke_type new_t, void *old_addr,
857+
void *new_addr)
857858
{
858859
u32 old_insns[RV_FENTRY_NINSNS], new_insns[RV_FENTRY_NINSNS];
859-
bool is_call = poke_type == BPF_MOD_CALL;
860+
bool is_call;
860861
int ret;
861862

862863
if (!is_kernel_text((unsigned long)ip) &&
863864
!is_bpf_text_address((unsigned long)ip))
864865
return -ENOTSUPP;
865866

867+
is_call = old_t == BPF_MOD_CALL;
866868
ret = gen_jump_or_nops(old_addr, ip, old_insns, is_call);
867869
if (ret)
868870
return ret;
869871

870872
if (memcmp(ip, old_insns, RV_FENTRY_NBYTES))
871873
return -EFAULT;
872874

875+
is_call = new_t == BPF_MOD_CALL;
873876
ret = gen_jump_or_nops(new_addr, ip, new_insns, is_call);
874877
if (ret)
875878
return ret;

arch/s390/net/bpf_jit_comp.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,8 +2413,9 @@ bool bpf_jit_supports_far_kfunc_call(void)
24132413
return true;
24142414
}
24152415

2416-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
2417-
void *old_addr, void *new_addr)
2416+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
2417+
enum bpf_text_poke_type new_t, void *old_addr,
2418+
void *new_addr)
24182419
{
24192420
struct bpf_plt expected_plt, current_plt, new_plt, *plt;
24202421
struct {
@@ -2431,7 +2432,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
24312432
if (insn.opc != (0xc004 | (old_addr ? 0xf0 : 0)))
24322433
return -EINVAL;
24332434

2434-
if (t == BPF_MOD_JUMP &&
2435+
if ((new_t == BPF_MOD_JUMP || old_t == BPF_MOD_JUMP) &&
24352436
insn.disp == ((char *)new_addr - (char *)ip) >> 1) {
24362437
/*
24372438
* The branch already points to the destination,

arch/x86/net/bpf_jit_comp.c

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@ static int emit_jump(u8 **pprog, void *func, void *ip)
597597
return emit_patch(pprog, func, ip, 0xE9);
598598
}
599599

600-
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
600+
static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
601+
enum bpf_text_poke_type new_t,
601602
void *old_addr, void *new_addr)
602603
{
603604
const u8 *nop_insn = x86_nops[5];
@@ -607,19 +608,19 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
607608
int ret;
608609

609610
memcpy(old_insn, nop_insn, X86_PATCH_SIZE);
610-
if (old_addr) {
611+
if (old_t != BPF_MOD_NOP && old_addr) {
611612
prog = old_insn;
612-
ret = t == BPF_MOD_CALL ?
613+
ret = old_t == BPF_MOD_CALL ?
613614
emit_call(&prog, old_addr, ip) :
614615
emit_jump(&prog, old_addr, ip);
615616
if (ret)
616617
return ret;
617618
}
618619

619620
memcpy(new_insn, nop_insn, X86_PATCH_SIZE);
620-
if (new_addr) {
621+
if (new_t != BPF_MOD_NOP && new_addr) {
621622
prog = new_insn;
622-
ret = t == BPF_MOD_CALL ?
623+
ret = new_t == BPF_MOD_CALL ?
623624
emit_call(&prog, new_addr, ip) :
624625
emit_jump(&prog, new_addr, ip);
625626
if (ret)
@@ -640,8 +641,9 @@ static int __bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
640641
return ret;
641642
}
642643

643-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
644-
void *old_addr, void *new_addr)
644+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
645+
enum bpf_text_poke_type new_t, void *old_addr,
646+
void *new_addr)
645647
{
646648
if (!is_kernel_text((long)ip) &&
647649
!is_bpf_text_address((long)ip))
@@ -655,7 +657,7 @@ int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
655657
if (is_endbr(ip))
656658
ip += ENDBR_INSN_SIZE;
657659

658-
return __bpf_arch_text_poke(ip, t, old_addr, new_addr);
660+
return __bpf_arch_text_poke(ip, old_t, new_t, old_addr, new_addr);
659661
}
660662

661663
#define EMIT_LFENCE() EMIT3(0x0F, 0xAE, 0xE8)
@@ -897,12 +899,13 @@ static void bpf_tail_call_direct_fixup(struct bpf_prog *prog)
897899
target = array->ptrs[poke->tail_call.key];
898900
if (target) {
899901
ret = __bpf_arch_text_poke(poke->tailcall_target,
900-
BPF_MOD_JUMP, NULL,
902+
BPF_MOD_NOP, BPF_MOD_JUMP,
903+
NULL,
901904
(u8 *)target->bpf_func +
902905
poke->adj_off);
903906
BUG_ON(ret < 0);
904907
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
905-
BPF_MOD_JUMP,
908+
BPF_MOD_JUMP, BPF_MOD_NOP,
906909
(u8 *)poke->tailcall_target +
907910
X86_PATCH_SIZE, NULL);
908911
BUG_ON(ret < 0);
@@ -3985,6 +3988,7 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
39853988
struct bpf_prog *new, struct bpf_prog *old)
39863989
{
39873990
u8 *old_addr, *new_addr, *old_bypass_addr;
3991+
enum bpf_text_poke_type t;
39883992
int ret;
39893993

39903994
old_bypass_addr = old ? NULL : poke->bypass_addr;
@@ -3997,21 +4001,22 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
39974001
* the kallsyms check.
39984002
*/
39994003
if (new) {
4004+
t = old_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
40004005
ret = __bpf_arch_text_poke(poke->tailcall_target,
4001-
BPF_MOD_JUMP,
4006+
t, BPF_MOD_JUMP,
40024007
old_addr, new_addr);
40034008
BUG_ON(ret < 0);
40044009
if (!old) {
40054010
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
4006-
BPF_MOD_JUMP,
4011+
BPF_MOD_JUMP, BPF_MOD_NOP,
40074012
poke->bypass_addr,
40084013
NULL);
40094014
BUG_ON(ret < 0);
40104015
}
40114016
} else {
4017+
t = old_bypass_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
40124018
ret = __bpf_arch_text_poke(poke->tailcall_bypass,
4013-
BPF_MOD_JUMP,
4014-
old_bypass_addr,
4019+
t, BPF_MOD_JUMP, old_bypass_addr,
40154020
poke->bypass_addr);
40164021
BUG_ON(ret < 0);
40174022
/* let other CPUs finish the execution of program
@@ -4020,9 +4025,9 @@ void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
40204025
*/
40214026
if (!ret)
40224027
synchronize_rcu();
4028+
t = old_addr ? BPF_MOD_JUMP : BPF_MOD_NOP;
40234029
ret = __bpf_arch_text_poke(poke->tailcall_target,
4024-
BPF_MOD_JUMP,
4025-
old_addr, NULL);
4030+
t, BPF_MOD_NOP, old_addr, NULL);
40264031
BUG_ON(ret < 0);
40274032
}
40284033
}

include/linux/bpf.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3708,12 +3708,14 @@ static inline u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
37083708
#endif /* CONFIG_INET */
37093709

37103710
enum bpf_text_poke_type {
3711+
BPF_MOD_NOP,
37113712
BPF_MOD_CALL,
37123713
BPF_MOD_JUMP,
37133714
};
37143715

3715-
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
3716-
void *addr1, void *addr2);
3716+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
3717+
enum bpf_text_poke_type new_t, void *old_addr,
3718+
void *new_addr);
37173719

37183720
void bpf_arch_poke_desc_update(struct bpf_jit_poke_descriptor *poke,
37193721
struct bpf_prog *new, struct bpf_prog *old);

kernel/bpf/core.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3150,8 +3150,9 @@ int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to,
31503150
return -EFAULT;
31513151
}
31523152

3153-
int __weak bpf_arch_text_poke(void *ip, enum bpf_text_poke_type t,
3154-
void *addr1, void *addr2)
3153+
int __weak bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
3154+
enum bpf_text_poke_type new_t, void *old_addr,
3155+
void *new_addr)
31553156
{
31563157
return -ENOTSUPP;
31573158
}

kernel/bpf/trampoline.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,8 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
183183
if (tr->func.ftrace_managed)
184184
ret = unregister_ftrace_direct(tr->fops, (long)old_addr, false);
185185
else
186-
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
186+
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, BPF_MOD_NOP,
187+
old_addr, NULL);
187188

188189
return ret;
189190
}
@@ -200,7 +201,10 @@ static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_ad
200201
else
201202
ret = modify_ftrace_direct_nolock(tr->fops, (long)new_addr);
202203
} else {
203-
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, new_addr);
204+
ret = bpf_arch_text_poke(ip,
205+
old_addr ? BPF_MOD_CALL : BPF_MOD_NOP,
206+
new_addr ? BPF_MOD_CALL : BPF_MOD_NOP,
207+
old_addr, new_addr);
204208
}
205209
return ret;
206210
}
@@ -225,7 +229,8 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
225229
return ret;
226230
ret = register_ftrace_direct(tr->fops, (long)new_addr);
227231
} else {
228-
ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr);
232+
ret = bpf_arch_text_poke(ip, BPF_MOD_NOP, BPF_MOD_CALL,
233+
NULL, new_addr);
229234
}
230235

231236
return ret;
@@ -336,8 +341,9 @@ static void bpf_tramp_image_put(struct bpf_tramp_image *im)
336341
* call_rcu_tasks() is not necessary.
337342
*/
338343
if (im->ip_after_call) {
339-
int err = bpf_arch_text_poke(im->ip_after_call, BPF_MOD_JUMP,
340-
NULL, im->ip_epilogue);
344+
int err = bpf_arch_text_poke(im->ip_after_call, BPF_MOD_NOP,
345+
BPF_MOD_JUMP, NULL,
346+
im->ip_epilogue);
341347
WARN_ON(err);
342348
if (IS_ENABLED(CONFIG_TASKS_RCU))
343349
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,
570576
if (err)
571577
return err;
572578
tr->extension_prog = link->link.prog;
573-
return bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP, NULL,
579+
return bpf_arch_text_poke(tr->func.addr, BPF_MOD_NOP,
580+
BPF_MOD_JUMP, NULL,
574581
link->link.prog->bpf_func);
575582
}
576583
if (cnt >= BPF_MAX_TRAMP_LINKS)
@@ -618,6 +625,7 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
618625
if (kind == BPF_TRAMP_REPLACE) {
619626
WARN_ON_ONCE(!tr->extension_prog);
620627
err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_JUMP,
628+
BPF_MOD_NOP,
621629
tr->extension_prog->bpf_func, NULL);
622630
tr->extension_prog = NULL;
623631
guard(mutex)(&tgt_prog->aux->ext_mutex);

0 commit comments

Comments
 (0)