|
9 | 9 |
|
10 | 10 | #include <linux/bitfield.h>
|
11 | 11 | #include <linux/bpf.h>
|
| 12 | +#include <linux/memory.h> |
12 | 13 | #include <linux/filter.h>
|
13 | 14 | #include <linux/printk.h>
|
14 | 15 | #include <linux/slab.h>
|
|
18 | 19 | #include <asm/cacheflush.h>
|
19 | 20 | #include <asm/debug-monitors.h>
|
20 | 21 | #include <asm/insn.h>
|
| 22 | +#include <asm/patching.h> |
21 | 23 | #include <asm/set_memory.h>
|
22 | 24 |
|
23 | 25 | #include "bpf_jit.h"
|
@@ -1529,3 +1531,53 @@ void bpf_jit_free_exec(void *addr)
|
1529 | 1531 | {
|
1530 | 1532 | return vfree(addr);
|
1531 | 1533 | }
|
| 1534 | + |
| 1535 | +static int gen_branch_or_nop(enum aarch64_insn_branch_type type, void *ip, |
| 1536 | + void *addr, u32 *insn) |
| 1537 | +{ |
| 1538 | + if (!addr) |
| 1539 | + *insn = aarch64_insn_gen_nop(); |
| 1540 | + else |
| 1541 | + *insn = aarch64_insn_gen_branch_imm((unsigned long)ip, |
| 1542 | + (unsigned long)addr, |
| 1543 | + type); |
| 1544 | + |
| 1545 | + return *insn != AARCH64_BREAK_FAULT ? 0 : -EFAULT; |
| 1546 | +} |
| 1547 | + |
| 1548 | +int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type poke_type, |
| 1549 | + void *old_addr, void *new_addr) |
| 1550 | +{ |
| 1551 | + int ret; |
| 1552 | + u32 old_insn; |
| 1553 | + u32 new_insn; |
| 1554 | + u32 replaced; |
| 1555 | + enum aarch64_insn_branch_type branch_type; |
| 1556 | + |
| 1557 | + if (poke_type == BPF_MOD_CALL) |
| 1558 | + branch_type = AARCH64_INSN_BRANCH_LINK; |
| 1559 | + else |
| 1560 | + branch_type = AARCH64_INSN_BRANCH_NOLINK; |
| 1561 | + |
| 1562 | + if (gen_branch_or_nop(branch_type, ip, old_addr, &old_insn) < 0) |
| 1563 | + return -EFAULT; |
| 1564 | + |
| 1565 | + if (gen_branch_or_nop(branch_type, ip, new_addr, &new_insn) < 0) |
| 1566 | + return -EFAULT; |
| 1567 | + |
| 1568 | + mutex_lock(&text_mutex); |
| 1569 | + if (aarch64_insn_read(ip, &replaced)) { |
| 1570 | + ret = -EFAULT; |
| 1571 | + goto out; |
| 1572 | + } |
| 1573 | + |
| 1574 | + if (replaced != old_insn) { |
| 1575 | + ret = -EFAULT; |
| 1576 | + goto out; |
| 1577 | + } |
| 1578 | + |
| 1579 | + ret = aarch64_insn_patch_text_nosync((void *)ip, new_insn); |
| 1580 | +out: |
| 1581 | + mutex_unlock(&text_mutex); |
| 1582 | + return ret; |
| 1583 | +} |
0 commit comments