[PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets

Xu Kuohai posted 5 patches 1 month, 1 week ago
There is a newer version of this series
[PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets
Posted by Xu Kuohai 1 month, 1 week ago
From: Xu Kuohai <xukuohai@huawei.com>

On CPUs that support CET/IBT, the indirect jump selftest triggers
a kernel panic because the indirect jump targets lack ENDBR
instructions.

To fix it, emit an ENDBR instruction to each indirect jump target. Since
the ENDBR instruction shifts the position of original jited instructions,
fix the instruction address calculation wherever the addresses are used.

For reference, below is a sample panic log.

 Missing ENDBR: bpf_prog_2e5f1c71c13ac3e0_big_jump_table+0x97/0xe1
 ------------[ cut here ]------------
 kernel BUG at arch/x86/kernel/cet.c:133!
 Oops: invalid opcode: 0000 [#1] SMP NOPTI

 ...

  ? 0xffffffffc00fb258
  ? bpf_prog_2e5f1c71c13ac3e0_big_jump_table+0x97/0xe1
  bpf_prog_test_run_syscall+0x110/0x2f0
  ? fdget+0xba/0xe0
  __sys_bpf+0xe4b/0x2590
  ? __kmalloc_node_track_caller_noprof+0x1c7/0x680
  ? bpf_prog_test_run_syscall+0x215/0x2f0
  __x64_sys_bpf+0x21/0x30
  do_syscall_64+0x85/0x620
  ? bpf_prog_test_run_syscall+0x1e2/0x2f0

Fixes: 493d9e0d6083 ("bpf, x86: add support for indirect jumps")
Signed-off-by: Xu Kuohai <xukuohai@huawei.com>
---
 arch/x86/net/bpf_jit_comp.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 43beacaed56d..7a2fa828558a 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1658,8 +1658,8 @@ static int emit_spectre_bhb_barrier(u8 **pprog, u8 *ip,
 	return 0;
 }
 
-static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image,
-		  int oldproglen, struct jit_context *ctx, bool jmp_padding)
+static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *addrs, u8 *image,
+		  u8 *rw_image, int oldproglen, struct jit_context *ctx, bool jmp_padding)
 {
 	bool tail_call_reachable = bpf_prog->aux->tail_call_reachable;
 	struct bpf_insn *insn = bpf_prog->insnsi;
@@ -1743,6 +1743,9 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
 				dst_reg = X86_REG_R9;
 		}
 
+		if (bpf_insn_is_indirect_target(env, bpf_prog, i - 1))
+			EMIT_ENDBR();
+
 		switch (insn->code) {
 			/* ALU */
 		case BPF_ALU | BPF_ADD | BPF_X:
@@ -2449,7 +2452,7 @@ st:			if (is_imm8(insn->off))
 
 			/* call */
 		case BPF_JMP | BPF_CALL: {
-			u8 *ip = image + addrs[i - 1];
+			u8 *ip = image + addrs[i - 1] + (prog - temp);
 
 			func = (u8 *) __bpf_call_base + imm32;
 			if (src_reg == BPF_PSEUDO_CALL && tail_call_reachable) {
@@ -2474,7 +2477,8 @@ st:			if (is_imm8(insn->off))
 			if (imm32)
 				emit_bpf_tail_call_direct(bpf_prog,
 							  &bpf_prog->aux->poke_tab[imm32 - 1],
-							  &prog, image + addrs[i - 1],
+							  &prog,
+							  image + addrs[i - 1] + (prog - temp),
 							  callee_regs_used,
 							  stack_depth,
 							  ctx);
@@ -2483,7 +2487,7 @@ st:			if (is_imm8(insn->off))
 							    &prog,
 							    callee_regs_used,
 							    stack_depth,
-							    image + addrs[i - 1],
+							    image + addrs[i - 1] + (prog - temp),
 							    ctx);
 			break;
 
@@ -2648,7 +2652,8 @@ st:			if (is_imm8(insn->off))
 			break;
 
 		case BPF_JMP | BPF_JA | BPF_X:
-			emit_indirect_jump(&prog, insn->dst_reg, image + addrs[i - 1]);
+			emit_indirect_jump(&prog, insn->dst_reg,
+					   image + addrs[i - 1] + (prog - temp));
 			break;
 		case BPF_JMP | BPF_JA:
 		case BPF_JMP32 | BPF_JA:
@@ -2738,7 +2743,7 @@ st:			if (is_imm8(insn->off))
 			ctx->cleanup_addr = proglen;
 			if (bpf_prog_was_classic(bpf_prog) &&
 			    !ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN)) {
-				u8 *ip = image + addrs[i - 1];
+				u8 *ip = image + addrs[i - 1] + (prog - temp);
 
 				if (emit_spectre_bhb_barrier(&prog, ip, bpf_prog))
 					return -EINVAL;
@@ -3820,7 +3825,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr
 	for (pass = 0; pass < MAX_PASSES || image; pass++) {
 		if (!padding && pass >= PADDING_PASSES)
 			padding = true;
-		proglen = do_jit(prog, addrs, image, rw_image, oldproglen, &ctx, padding);
+		proglen = do_jit(env, prog, addrs, image, rw_image, oldproglen, &ctx, padding);
 		if (proglen <= 0) {
 out_image:
 			image = NULL;
-- 
2.47.3
Re: [PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets
Posted by kernel test robot 1 month ago
Hi Xu,

kernel test robot noticed the following build warnings:

[auto build test WARNING on bpf-next/master]

url:    https://github.com/intel-lab-lkp/linux/commits/Xu-Kuohai/bpf-Move-JIT-for-single-subprog-programs-to-verifier/20260302-181031
base:   https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git master
patch link:    https://lore.kernel.org/r/20260302102726.1126019-5-xukuohai%40huaweicloud.com
patch subject: [PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets
config: x86_64-buildonly-randconfig-001-20260305 (https://download.01.org/0day-ci/archive/20260305/202603051414.AAMjmOHv-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260305/202603051414.AAMjmOHv-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202603051414.AAMjmOHv-lkp@intel.com/

All warnings (new ones prefixed by >>):

   arch/x86/net/bpf_jit_comp.c: In function 'do_jit':
>> arch/x86/net/bpf_jit_comp.c:1747:37: warning: suggest braces around empty body in an 'if' statement [-Wempty-body]
    1747 |                         EMIT_ENDBR();
         |                                     ^


vim +/if +1747 arch/x86/net/bpf_jit_comp.c

  1660	
  1661	static int do_jit(struct bpf_verifier_env *env, struct bpf_prog *bpf_prog, int *addrs, u8 *image,
  1662			  u8 *rw_image, int oldproglen, struct jit_context *ctx, bool jmp_padding)
  1663	{
  1664		bool tail_call_reachable = bpf_prog->aux->tail_call_reachable;
  1665		struct bpf_insn *insn = bpf_prog->insnsi;
  1666		bool callee_regs_used[4] = {};
  1667		int insn_cnt = bpf_prog->len;
  1668		bool seen_exit = false;
  1669		u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY];
  1670		void __percpu *priv_frame_ptr = NULL;
  1671		u64 arena_vm_start, user_vm_start;
  1672		void __percpu *priv_stack_ptr;
  1673		int i, excnt = 0;
  1674		int ilen, proglen = 0;
  1675		u8 *prog = temp;
  1676		u32 stack_depth;
  1677		int err;
  1678	
  1679		stack_depth = bpf_prog->aux->stack_depth;
  1680		priv_stack_ptr = bpf_prog->aux->priv_stack_ptr;
  1681		if (priv_stack_ptr) {
  1682			priv_frame_ptr = priv_stack_ptr + PRIV_STACK_GUARD_SZ + round_up(stack_depth, 8);
  1683			stack_depth = 0;
  1684		}
  1685	
  1686		arena_vm_start = bpf_arena_get_kern_vm_start(bpf_prog->aux->arena);
  1687		user_vm_start = bpf_arena_get_user_vm_start(bpf_prog->aux->arena);
  1688	
  1689		detect_reg_usage(insn, insn_cnt, callee_regs_used);
  1690	
  1691		emit_prologue(&prog, image, stack_depth,
  1692			      bpf_prog_was_classic(bpf_prog), tail_call_reachable,
  1693			      bpf_is_subprog(bpf_prog), bpf_prog->aux->exception_cb);
  1694	
  1695		bpf_prog->aux->ksym.fp_start = prog - temp;
  1696	
  1697		/* Exception callback will clobber callee regs for its own use, and
  1698		 * restore the original callee regs from main prog's stack frame.
  1699		 */
  1700		if (bpf_prog->aux->exception_boundary) {
  1701			/* We also need to save r12, which is not mapped to any BPF
  1702			 * register, as we throw after entry into the kernel, which may
  1703			 * overwrite r12.
  1704			 */
  1705			push_r12(&prog);
  1706			push_callee_regs(&prog, all_callee_regs_used);
  1707		} else {
  1708			if (arena_vm_start)
  1709				push_r12(&prog);
  1710			push_callee_regs(&prog, callee_regs_used);
  1711		}
  1712		if (arena_vm_start)
  1713			emit_mov_imm64(&prog, X86_REG_R12,
  1714				       arena_vm_start >> 32, (u32) arena_vm_start);
  1715	
  1716		if (priv_frame_ptr)
  1717			emit_priv_frame_ptr(&prog, priv_frame_ptr);
  1718	
  1719		ilen = prog - temp;
  1720		if (rw_image)
  1721			memcpy(rw_image + proglen, temp, ilen);
  1722		proglen += ilen;
  1723		addrs[0] = proglen;
  1724		prog = temp;
  1725	
  1726		for (i = 1; i <= insn_cnt; i++, insn++) {
  1727			const s32 imm32 = insn->imm;
  1728			u32 dst_reg = insn->dst_reg;
  1729			u32 src_reg = insn->src_reg;
  1730			u8 b2 = 0, b3 = 0;
  1731			u8 *start_of_ldx;
  1732			s64 jmp_offset;
  1733			s16 insn_off;
  1734			u8 jmp_cond;
  1735			u8 *func;
  1736			int nops;
  1737	
  1738			if (priv_frame_ptr) {
  1739				if (src_reg == BPF_REG_FP)
  1740					src_reg = X86_REG_R9;
  1741	
  1742				if (dst_reg == BPF_REG_FP)
  1743					dst_reg = X86_REG_R9;
  1744			}
  1745	
  1746			if (bpf_insn_is_indirect_target(env, bpf_prog, i - 1))
> 1747				EMIT_ENDBR();
  1748	
  1749			switch (insn->code) {
  1750				/* ALU */
  1751			case BPF_ALU | BPF_ADD | BPF_X:
  1752			case BPF_ALU | BPF_SUB | BPF_X:
  1753			case BPF_ALU | BPF_AND | BPF_X:
  1754			case BPF_ALU | BPF_OR | BPF_X:
  1755			case BPF_ALU | BPF_XOR | BPF_X:
  1756			case BPF_ALU64 | BPF_ADD | BPF_X:
  1757			case BPF_ALU64 | BPF_SUB | BPF_X:
  1758			case BPF_ALU64 | BPF_AND | BPF_X:
  1759			case BPF_ALU64 | BPF_OR | BPF_X:
  1760			case BPF_ALU64 | BPF_XOR | BPF_X:
  1761				maybe_emit_mod(&prog, dst_reg, src_reg,
  1762					       BPF_CLASS(insn->code) == BPF_ALU64);
  1763				b2 = simple_alu_opcodes[BPF_OP(insn->code)];
  1764				EMIT2(b2, add_2reg(0xC0, dst_reg, src_reg));
  1765				break;
  1766	
  1767			case BPF_ALU64 | BPF_MOV | BPF_X:
  1768				if (insn_is_cast_user(insn)) {
  1769					if (dst_reg != src_reg)
  1770						/* 32-bit mov */
  1771						emit_mov_reg(&prog, false, dst_reg, src_reg);
  1772					/* shl dst_reg, 32 */
  1773					maybe_emit_1mod(&prog, dst_reg, true);
  1774					EMIT3(0xC1, add_1reg(0xE0, dst_reg), 32);
  1775	
  1776					/* or dst_reg, user_vm_start */
  1777					maybe_emit_1mod(&prog, dst_reg, true);
  1778					if (is_axreg(dst_reg))
  1779						EMIT1_off32(0x0D,  user_vm_start >> 32);
  1780					else
  1781						EMIT2_off32(0x81, add_1reg(0xC8, dst_reg),  user_vm_start >> 32);
  1782	
  1783					/* rol dst_reg, 32 */
  1784					maybe_emit_1mod(&prog, dst_reg, true);
  1785					EMIT3(0xC1, add_1reg(0xC0, dst_reg), 32);
  1786	
  1787					/* xor r11, r11 */
  1788					EMIT3(0x4D, 0x31, 0xDB);
  1789	
  1790					/* test dst_reg32, dst_reg32; check if lower 32-bit are zero */
  1791					maybe_emit_mod(&prog, dst_reg, dst_reg, false);
  1792					EMIT2(0x85, add_2reg(0xC0, dst_reg, dst_reg));
  1793	
  1794					/* cmove r11, dst_reg; if so, set dst_reg to zero */
  1795					/* WARNING: Intel swapped src/dst register encoding in CMOVcc !!! */
  1796					maybe_emit_mod(&prog, AUX_REG, dst_reg, true);
  1797					EMIT3(0x0F, 0x44, add_2reg(0xC0, AUX_REG, dst_reg));
  1798					break;
  1799				} else if (insn_is_mov_percpu_addr(insn)) {
  1800					/* mov <dst>, <src> (if necessary) */
  1801					EMIT_mov(dst_reg, src_reg);
  1802	#ifdef CONFIG_SMP
  1803					/* add <dst>, gs:[<off>] */
  1804					EMIT2(0x65, add_1mod(0x48, dst_reg));
  1805					EMIT3(0x03, add_2reg(0x04, 0, dst_reg), 0x25);
  1806					EMIT((u32)(unsigned long)&this_cpu_off, 4);
  1807	#endif
  1808					break;
  1809				}
  1810				fallthrough;
  1811			case BPF_ALU | BPF_MOV | BPF_X:
  1812				if (insn->off == 0)
  1813					emit_mov_reg(&prog,
  1814						     BPF_CLASS(insn->code) == BPF_ALU64,
  1815						     dst_reg, src_reg);
  1816				else
  1817					emit_movsx_reg(&prog, insn->off,
  1818						       BPF_CLASS(insn->code) == BPF_ALU64,
  1819						       dst_reg, src_reg);
  1820				break;
  1821	
  1822				/* neg dst */
  1823			case BPF_ALU | BPF_NEG:
  1824			case BPF_ALU64 | BPF_NEG:
  1825				maybe_emit_1mod(&prog, dst_reg,
  1826						BPF_CLASS(insn->code) == BPF_ALU64);
  1827				EMIT2(0xF7, add_1reg(0xD8, dst_reg));
  1828				break;
  1829	
  1830			case BPF_ALU | BPF_ADD | BPF_K:
  1831			case BPF_ALU | BPF_SUB | BPF_K:
  1832			case BPF_ALU | BPF_AND | BPF_K:
  1833			case BPF_ALU | BPF_OR | BPF_K:
  1834			case BPF_ALU | BPF_XOR | BPF_K:
  1835			case BPF_ALU64 | BPF_ADD | BPF_K:
  1836			case BPF_ALU64 | BPF_SUB | BPF_K:
  1837			case BPF_ALU64 | BPF_AND | BPF_K:
  1838			case BPF_ALU64 | BPF_OR | BPF_K:
  1839			case BPF_ALU64 | BPF_XOR | BPF_K:
  1840				maybe_emit_1mod(&prog, dst_reg,
  1841						BPF_CLASS(insn->code) == BPF_ALU64);
  1842	
  1843				/*
  1844				 * b3 holds 'normal' opcode, b2 short form only valid
  1845				 * in case dst is eax/rax.
  1846				 */
  1847				switch (BPF_OP(insn->code)) {
  1848				case BPF_ADD:
  1849					b3 = 0xC0;
  1850					b2 = 0x05;
  1851					break;
  1852				case BPF_SUB:
  1853					b3 = 0xE8;
  1854					b2 = 0x2D;
  1855					break;
  1856				case BPF_AND:
  1857					b3 = 0xE0;
  1858					b2 = 0x25;
  1859					break;
  1860				case BPF_OR:
  1861					b3 = 0xC8;
  1862					b2 = 0x0D;
  1863					break;
  1864				case BPF_XOR:
  1865					b3 = 0xF0;
  1866					b2 = 0x35;
  1867					break;
  1868				}
  1869	
  1870				if (is_imm8(imm32))
  1871					EMIT3(0x83, add_1reg(b3, dst_reg), imm32);
  1872				else if (is_axreg(dst_reg))
  1873					EMIT1_off32(b2, imm32);
  1874				else
  1875					EMIT2_off32(0x81, add_1reg(b3, dst_reg), imm32);
  1876				break;
  1877	
  1878			case BPF_ALU64 | BPF_MOV | BPF_K:
  1879			case BPF_ALU | BPF_MOV | BPF_K:
  1880				emit_mov_imm32(&prog, BPF_CLASS(insn->code) == BPF_ALU64,
  1881					       dst_reg, imm32);
  1882				break;
  1883	
  1884			case BPF_LD | BPF_IMM | BPF_DW:
  1885				emit_mov_imm64(&prog, dst_reg, insn[1].imm, insn[0].imm);
  1886				insn++;
  1887				i++;
  1888				break;
  1889	
  1890				/* dst %= src, dst /= src, dst %= imm32, dst /= imm32 */
  1891			case BPF_ALU | BPF_MOD | BPF_X:
  1892			case BPF_ALU | BPF_DIV | BPF_X:
  1893			case BPF_ALU | BPF_MOD | BPF_K:
  1894			case BPF_ALU | BPF_DIV | BPF_K:
  1895			case BPF_ALU64 | BPF_MOD | BPF_X:
  1896			case BPF_ALU64 | BPF_DIV | BPF_X:
  1897			case BPF_ALU64 | BPF_MOD | BPF_K:
  1898			case BPF_ALU64 | BPF_DIV | BPF_K: {
  1899				bool is64 = BPF_CLASS(insn->code) == BPF_ALU64;
  1900	
  1901				if (dst_reg != BPF_REG_0)
  1902					EMIT1(0x50); /* push rax */
  1903				if (dst_reg != BPF_REG_3)
  1904					EMIT1(0x52); /* push rdx */
  1905	
  1906				if (BPF_SRC(insn->code) == BPF_X) {
  1907					if (src_reg == BPF_REG_0 ||
  1908					    src_reg == BPF_REG_3) {
  1909						/* mov r11, src_reg */
  1910						EMIT_mov(AUX_REG, src_reg);
  1911						src_reg = AUX_REG;
  1912					}
  1913				} else {
  1914					/* mov r11, imm32 */
  1915					EMIT3_off32(0x49, 0xC7, 0xC3, imm32);
  1916					src_reg = AUX_REG;
  1917				}
  1918	
  1919				if (dst_reg != BPF_REG_0)
  1920					/* mov rax, dst_reg */
  1921					emit_mov_reg(&prog, is64, BPF_REG_0, dst_reg);
  1922	
  1923				if (insn->off == 0) {
  1924					/*
  1925					 * xor edx, edx
  1926					 * equivalent to 'xor rdx, rdx', but one byte less
  1927					 */
  1928					EMIT2(0x31, 0xd2);
  1929	
  1930					/* div src_reg */
  1931					maybe_emit_1mod(&prog, src_reg, is64);
  1932					EMIT2(0xF7, add_1reg(0xF0, src_reg));
  1933				} else {
  1934					if (BPF_CLASS(insn->code) == BPF_ALU)
  1935						EMIT1(0x99); /* cdq */
  1936					else
  1937						EMIT2(0x48, 0x99); /* cqo */
  1938	
  1939					/* idiv src_reg */
  1940					maybe_emit_1mod(&prog, src_reg, is64);
  1941					EMIT2(0xF7, add_1reg(0xF8, src_reg));
  1942				}
  1943	
  1944				if (BPF_OP(insn->code) == BPF_MOD &&
  1945				    dst_reg != BPF_REG_3)
  1946					/* mov dst_reg, rdx */
  1947					emit_mov_reg(&prog, is64, dst_reg, BPF_REG_3);
  1948				else if (BPF_OP(insn->code) == BPF_DIV &&
  1949					 dst_reg != BPF_REG_0)
  1950					/* mov dst_reg, rax */
  1951					emit_mov_reg(&prog, is64, dst_reg, BPF_REG_0);
  1952	
  1953				if (dst_reg != BPF_REG_3)
  1954					EMIT1(0x5A); /* pop rdx */
  1955				if (dst_reg != BPF_REG_0)
  1956					EMIT1(0x58); /* pop rax */
  1957				break;
  1958			}
  1959	
  1960			case BPF_ALU | BPF_MUL | BPF_K:
  1961			case BPF_ALU64 | BPF_MUL | BPF_K:
  1962				maybe_emit_mod(&prog, dst_reg, dst_reg,
  1963					       BPF_CLASS(insn->code) == BPF_ALU64);
  1964	
  1965				if (is_imm8(imm32))
  1966					/* imul dst_reg, dst_reg, imm8 */
  1967					EMIT3(0x6B, add_2reg(0xC0, dst_reg, dst_reg),
  1968					      imm32);
  1969				else
  1970					/* imul dst_reg, dst_reg, imm32 */
  1971					EMIT2_off32(0x69,
  1972						    add_2reg(0xC0, dst_reg, dst_reg),
  1973						    imm32);
  1974				break;
  1975	
  1976			case BPF_ALU | BPF_MUL | BPF_X:
  1977			case BPF_ALU64 | BPF_MUL | BPF_X:
  1978				maybe_emit_mod(&prog, src_reg, dst_reg,
  1979					       BPF_CLASS(insn->code) == BPF_ALU64);
  1980	
  1981				/* imul dst_reg, src_reg */
  1982				EMIT3(0x0F, 0xAF, add_2reg(0xC0, src_reg, dst_reg));
  1983				break;
  1984	
  1985				/* Shifts */
  1986			case BPF_ALU | BPF_LSH | BPF_K:
  1987			case BPF_ALU | BPF_RSH | BPF_K:
  1988			case BPF_ALU | BPF_ARSH | BPF_K:
  1989			case BPF_ALU64 | BPF_LSH | BPF_K:
  1990			case BPF_ALU64 | BPF_RSH | BPF_K:
  1991			case BPF_ALU64 | BPF_ARSH | BPF_K:
  1992				maybe_emit_1mod(&prog, dst_reg,
  1993						BPF_CLASS(insn->code) == BPF_ALU64);
  1994	
  1995				b3 = simple_alu_opcodes[BPF_OP(insn->code)];
  1996				if (imm32 == 1)
  1997					EMIT2(0xD1, add_1reg(b3, dst_reg));
  1998				else
  1999					EMIT3(0xC1, add_1reg(b3, dst_reg), imm32);
  2000				break;
  2001	
  2002			case BPF_ALU | BPF_LSH | BPF_X:
  2003			case BPF_ALU | BPF_RSH | BPF_X:
  2004			case BPF_ALU | BPF_ARSH | BPF_X:
  2005			case BPF_ALU64 | BPF_LSH | BPF_X:
  2006			case BPF_ALU64 | BPF_RSH | BPF_X:
  2007			case BPF_ALU64 | BPF_ARSH | BPF_X:
  2008				/* BMI2 shifts aren't better when shift count is already in rcx */
  2009				if (boot_cpu_has(X86_FEATURE_BMI2) && src_reg != BPF_REG_4) {
  2010					/* shrx/sarx/shlx dst_reg, dst_reg, src_reg */
  2011					bool w = (BPF_CLASS(insn->code) == BPF_ALU64);
  2012					u8 op;
  2013	
  2014					switch (BPF_OP(insn->code)) {
  2015					case BPF_LSH:
  2016						op = 1; /* prefix 0x66 */
  2017						break;
  2018					case BPF_RSH:
  2019						op = 3; /* prefix 0xf2 */
  2020						break;
  2021					case BPF_ARSH:
  2022						op = 2; /* prefix 0xf3 */
  2023						break;
  2024					}
  2025	
  2026					emit_shiftx(&prog, dst_reg, src_reg, w, op);
  2027	
  2028					break;
  2029				}
  2030	
  2031				if (src_reg != BPF_REG_4) { /* common case */
  2032					/* Check for bad case when dst_reg == rcx */
  2033					if (dst_reg == BPF_REG_4) {
  2034						/* mov r11, dst_reg */
  2035						EMIT_mov(AUX_REG, dst_reg);
  2036						dst_reg = AUX_REG;
  2037					} else {
  2038						EMIT1(0x51); /* push rcx */
  2039					}
  2040					/* mov rcx, src_reg */
  2041					EMIT_mov(BPF_REG_4, src_reg);
  2042				}
  2043	
  2044				/* shl %rax, %cl | shr %rax, %cl | sar %rax, %cl */
  2045				maybe_emit_1mod(&prog, dst_reg,
  2046						BPF_CLASS(insn->code) == BPF_ALU64);
  2047	
  2048				b3 = simple_alu_opcodes[BPF_OP(insn->code)];
  2049				EMIT2(0xD3, add_1reg(b3, dst_reg));
  2050	
  2051				if (src_reg != BPF_REG_4) {
  2052					if (insn->dst_reg == BPF_REG_4)
  2053						/* mov dst_reg, r11 */
  2054						EMIT_mov(insn->dst_reg, AUX_REG);
  2055					else
  2056						EMIT1(0x59); /* pop rcx */
  2057				}
  2058	
  2059				break;
  2060	
  2061			case BPF_ALU | BPF_END | BPF_FROM_BE:
  2062			case BPF_ALU64 | BPF_END | BPF_FROM_LE:
  2063				switch (imm32) {
  2064				case 16:
  2065					/* Emit 'ror %ax, 8' to swap lower 2 bytes */
  2066					EMIT1(0x66);
  2067					if (is_ereg(dst_reg))
  2068						EMIT1(0x41);
  2069					EMIT3(0xC1, add_1reg(0xC8, dst_reg), 8);
  2070	
  2071					/* Emit 'movzwl eax, ax' */
  2072					if (is_ereg(dst_reg))
  2073						EMIT3(0x45, 0x0F, 0xB7);
  2074					else
  2075						EMIT2(0x0F, 0xB7);
  2076					EMIT1(add_2reg(0xC0, dst_reg, dst_reg));
  2077					break;
  2078				case 32:
  2079					/* Emit 'bswap eax' to swap lower 4 bytes */
  2080					if (is_ereg(dst_reg))
  2081						EMIT2(0x41, 0x0F);
  2082					else
  2083						EMIT1(0x0F);
  2084					EMIT1(add_1reg(0xC8, dst_reg));
  2085					break;
  2086				case 64:
  2087					/* Emit 'bswap rax' to swap 8 bytes */
  2088					EMIT3(add_1mod(0x48, dst_reg), 0x0F,
  2089					      add_1reg(0xC8, dst_reg));
  2090					break;
  2091				}
  2092				break;
  2093	
  2094			case BPF_ALU | BPF_END | BPF_FROM_LE:
  2095				switch (imm32) {
  2096				case 16:
  2097					/*
  2098					 * Emit 'movzwl eax, ax' to zero extend 16-bit
  2099					 * into 64 bit
  2100					 */
  2101					if (is_ereg(dst_reg))
  2102						EMIT3(0x45, 0x0F, 0xB7);
  2103					else
  2104						EMIT2(0x0F, 0xB7);
  2105					EMIT1(add_2reg(0xC0, dst_reg, dst_reg));
  2106					break;
  2107				case 32:
  2108					/* Emit 'mov eax, eax' to clear upper 32-bits */
  2109					if (is_ereg(dst_reg))
  2110						EMIT1(0x45);
  2111					EMIT2(0x89, add_2reg(0xC0, dst_reg, dst_reg));
  2112					break;
  2113				case 64:
  2114					/* nop */
  2115					break;
  2116				}
  2117				break;
  2118	
  2119				/* speculation barrier */
  2120			case BPF_ST | BPF_NOSPEC:
  2121				EMIT_LFENCE();
  2122				break;
  2123	
  2124				/* ST: *(u8*)(dst_reg + off) = imm */
  2125			case BPF_ST | BPF_MEM | BPF_B:
  2126				if (is_ereg(dst_reg))
  2127					EMIT2(0x41, 0xC6);
  2128				else
  2129					EMIT1(0xC6);
  2130				goto st;
  2131			case BPF_ST | BPF_MEM | BPF_H:
  2132				if (is_ereg(dst_reg))
  2133					EMIT3(0x66, 0x41, 0xC7);
  2134				else
  2135					EMIT2(0x66, 0xC7);
  2136				goto st;
  2137			case BPF_ST | BPF_MEM | BPF_W:
  2138				if (is_ereg(dst_reg))
  2139					EMIT2(0x41, 0xC7);
  2140				else
  2141					EMIT1(0xC7);
  2142				goto st;
  2143			case BPF_ST | BPF_MEM | BPF_DW:
  2144				EMIT2(add_1mod(0x48, dst_reg), 0xC7);
  2145	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets
Posted by Eduard Zingerman 1 month ago
On Mon, 2026-03-02 at 18:27 +0800, Xu Kuohai wrote:

[...]

> @@ -2449,7 +2452,7 @@ st:			if (is_imm8(insn->off))
>  
>  			/* call */
>  		case BPF_JMP | BPF_CALL: {
> -			u8 *ip = image + addrs[i - 1];
> +			u8 *ip = image + addrs[i - 1] + (prog - temp);
                                                        ^^^^^^^^^^^^^
			Could you please comment a bit why this addend is needed?
>  
>  			func = (u8 *) __bpf_call_base + imm32;
>  			if (src_reg == BPF_PSEUDO_CALL && tail_call_reachable) {

[...]
Re: [PATCH bpf-next v5 4/5] bpf, x86: Emit ENDBR for indirect jump targets
Posted by Xu Kuohai 1 month ago
On 3/4/2026 2:23 PM, Eduard Zingerman wrote:
> On Mon, 2026-03-02 at 18:27 +0800, Xu Kuohai wrote:
> 
> [...]
> 
>> @@ -2449,7 +2452,7 @@ st:			if (is_imm8(insn->off))
>>   
>>   			/* call */
>>   		case BPF_JMP | BPF_CALL: {
>> -			u8 *ip = image + addrs[i - 1];
>> +			u8 *ip = image + addrs[i - 1] + (prog - temp);
>                                                          ^^^^^^^^^^^^^
> 			Could you please comment a bit why this addend is needed?
>>

The temp buffer holds the JITed x86 instruction for each BPF instruction, and
prog variable points to the position in temp buffer where the next JITed x86
instruction will be written.

Since there may already be an ENDBR instruction in the temp buffer, which is
written when the current BPF instruction is an indirect jump target, we need to
add addend when computing the actual address of the JITed x86 instruction.

>>   			func = (u8 *) __bpf_call_base + imm32;
>>   			if (src_reg == BPF_PSEUDO_CALL && tail_call_reachable) {
> 
> [...]
> 
>