Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says:

====================
pull-request: bpf 2023-03-23

We've added 8 non-merge commits during the last 13 day(s) which contain
a total of 21 files changed, 238 insertions(+), 161 deletions(-).

The main changes are:

1) Fix verification issues in some BPF programs due to their stack usage
patterns, from Eduard Zingerman.

2) Fix to add missing overflow checks in xdp_umem_reg and return an error
in such case, from Kal Conley.

3) Fix and undo poisoning of strlcpy in libbpf given it broke builds for
libcs which provided the former like uClibc-ng, from Jesus Sanchez-Palencia.

4) Fix insufficient bpf_jit_limit default to avoid users running into hard
to debug seccomp BPF errors, from Daniel Borkmann.

5) Fix driver return code when they don't support a bpf_xdp_metadata kfunc
to make it unambiguous from other errors, from Jesper Dangaard Brouer.

6) Two BPF selftest fixes to address compilation errors from recent changes
in kernel structures, from Alexei Starovoitov.

* tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf:
xdp: bpf_xdp_metadata use EOPNOTSUPP for no driver support
bpf: Adjust insufficient default bpf_jit_limit
xsk: Add missing overflow check in xdp_umem_reg
selftests/bpf: Fix progs/test_deny_namespace.c issues.
selftests/bpf: Fix progs/find_vma_fail1.c build error.
libbpf: Revert poisoning of strlcpy
selftests/bpf: Tests for uninitialized stack reads
bpf: Allow reads from uninit stack
====================

Link: https://lore.kernel.org/r/20230323225221.6082-1-daniel@iogearbox.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+238 -161
+5 -2
Documentation/networking/xdp-rx-metadata.rst
··· 23 23 An XDP program can use these kfuncs to read the metadata into stack 24 24 variables for its own consumption. Or, to pass the metadata on to other 25 25 consumers, an XDP program can store it into the metadata area carried 26 - ahead of the packet. 26 + ahead of the packet. Not all packets will necessary have the requested 27 + metadata available in which case the driver returns ``-ENODATA``. 27 28 28 29 Not all kfuncs have to be implemented by the device driver; when not 29 - implemented, the default ones that return ``-EOPNOTSUPP`` will be used. 30 + implemented, the default ones that return ``-EOPNOTSUPP`` will be used 31 + to indicate the device driver have not implemented this kfunc. 32 + 30 33 31 34 Within an XDP frame, the metadata layout (accessed via ``xdp_buff``) is 32 35 as follows::
+2 -2
drivers/net/ethernet/mellanox/mlx4/en_rx.c
··· 674 674 struct mlx4_en_xdp_buff *_ctx = (void *)ctx; 675 675 676 676 if (unlikely(_ctx->ring->hwtstamp_rx_filter != HWTSTAMP_FILTER_ALL)) 677 - return -EOPNOTSUPP; 677 + return -ENODATA; 678 678 679 679 *timestamp = mlx4_en_get_hwtstamp(_ctx->mdev, 680 680 mlx4_en_get_cqe_ts(_ctx->cqe)); ··· 686 686 struct mlx4_en_xdp_buff *_ctx = (void *)ctx; 687 687 688 688 if (unlikely(!(_ctx->dev->features & NETIF_F_RXHASH))) 689 - return -EOPNOTSUPP; 689 + return -ENODATA; 690 690 691 691 *hash = be32_to_cpu(_ctx->cqe->immed_rss_invalid); 692 692 return 0;
+2 -2
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
··· 162 162 const struct mlx5e_xdp_buff *_ctx = (void *)ctx; 163 163 164 164 if (unlikely(!mlx5e_rx_hw_stamp(_ctx->rq->tstamp))) 165 - return -EOPNOTSUPP; 165 + return -ENODATA; 166 166 167 167 *timestamp = mlx5e_cqe_ts_to_ns(_ctx->rq->ptp_cyc2time, 168 168 _ctx->rq->clock, get_cqe_ts(_ctx->cqe)); ··· 174 174 const struct mlx5e_xdp_buff *_ctx = (void *)ctx; 175 175 176 176 if (unlikely(!(_ctx->xdp.rxq->dev->features & NETIF_F_RXHASH))) 177 - return -EOPNOTSUPP; 177 + return -ENODATA; 178 178 179 179 *hash = be32_to_cpu(_ctx->cqe->rss_hash_result); 180 180 return 0;
+2 -2
drivers/net/veth.c
··· 1642 1642 struct veth_xdp_buff *_ctx = (void *)ctx; 1643 1643 1644 1644 if (!_ctx->skb) 1645 - return -EOPNOTSUPP; 1645 + return -ENODATA; 1646 1646 1647 1647 *timestamp = skb_hwtstamps(_ctx->skb)->hwtstamp; 1648 1648 return 0; ··· 1653 1653 struct veth_xdp_buff *_ctx = (void *)ctx; 1654 1654 1655 1655 if (!_ctx->skb) 1656 - return -EOPNOTSUPP; 1656 + return -ENODATA; 1657 1657 1658 1658 *hash = skb_get_hash(_ctx->skb); 1659 1659 return 0;
+1 -1
kernel/bpf/core.c
··· 972 972 { 973 973 /* Only used as heuristic here to derive limit. */ 974 974 bpf_jit_limit_max = bpf_jit_alloc_exec_limit(); 975 - bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 2, 975 + bpf_jit_limit = min_t(u64, round_up(bpf_jit_limit_max >> 1, 976 976 PAGE_SIZE), LONG_MAX); 977 977 return 0; 978 978 }
+10 -1
kernel/bpf/verifier.c
··· 3826 3826 continue; 3827 3827 if (type == STACK_MISC) 3828 3828 continue; 3829 + if (type == STACK_INVALID && env->allow_uninit_stack) 3830 + continue; 3829 3831 verbose(env, "invalid read from stack off %d+%d size %d\n", 3830 3832 off, i, size); 3831 3833 return -EACCES; ··· 3864 3862 if (type == STACK_MISC) 3865 3863 continue; 3866 3864 if (type == STACK_ZERO) 3865 + continue; 3866 + if (type == STACK_INVALID && env->allow_uninit_stack) 3867 3867 continue; 3868 3868 verbose(env, "invalid read from stack off %d+%d size %d\n", 3869 3869 off, i, size); ··· 5758 5754 stype = &state->stack[spi].slot_type[slot % BPF_REG_SIZE]; 5759 5755 if (*stype == STACK_MISC) 5760 5756 goto mark; 5761 - if (*stype == STACK_ZERO) { 5757 + if ((*stype == STACK_ZERO) || 5758 + (*stype == STACK_INVALID && env->allow_uninit_stack)) { 5762 5759 if (clobber) { 5763 5760 /* helper can write anything into the stack */ 5764 5761 *stype = STACK_MISC; ··· 13939 13934 } 13940 13935 13941 13936 if (old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_INVALID) 13937 + continue; 13938 + 13939 + if (env->allow_uninit_stack && 13940 + old->stack[spi].slot_type[i % BPF_REG_SIZE] == STACK_MISC) 13942 13941 continue; 13943 13942 13944 13943 /* explored stack has more populated slots than current stack
+8 -2
net/core/xdp.c
··· 720 720 * @ctx: XDP context pointer. 721 721 * @timestamp: Return value pointer. 722 722 * 723 - * Returns 0 on success or ``-errno`` on error. 723 + * Return: 724 + * * Returns 0 on success or ``-errno`` on error. 725 + * * ``-EOPNOTSUPP`` : means device driver does not implement kfunc 726 + * * ``-ENODATA`` : means no RX-timestamp available for this frame 724 727 */ 725 728 __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp) 726 729 { ··· 735 732 * @ctx: XDP context pointer. 736 733 * @hash: Return value pointer. 737 734 * 738 - * Returns 0 on success or ``-errno`` on error. 735 + * Return: 736 + * * Returns 0 on success or ``-errno`` on error. 737 + * * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc 738 + * * ``-ENODATA`` : means no RX-hash available for this frame 739 739 */ 740 740 __bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash) 741 741 {
+7 -6
net/xdp/xdp_umem.c
··· 150 150 151 151 static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) 152 152 { 153 - u32 npgs_rem, chunk_size = mr->chunk_size, headroom = mr->headroom; 154 153 bool unaligned_chunks = mr->flags & XDP_UMEM_UNALIGNED_CHUNK_FLAG; 155 - u64 npgs, addr = mr->addr, size = mr->len; 156 - unsigned int chunks, chunks_rem; 154 + u32 chunk_size = mr->chunk_size, headroom = mr->headroom; 155 + u64 addr = mr->addr, size = mr->len; 156 + u32 chunks_rem, npgs_rem; 157 + u64 chunks, npgs; 157 158 int err; 158 159 159 160 if (chunk_size < XDP_UMEM_MIN_CHUNK_SIZE || chunk_size > PAGE_SIZE) { ··· 189 188 if (npgs > U32_MAX) 190 189 return -EINVAL; 191 190 192 - chunks = (unsigned int)div_u64_rem(size, chunk_size, &chunks_rem); 193 - if (chunks == 0) 191 + chunks = div_u64_rem(size, chunk_size, &chunks_rem); 192 + if (!chunks || chunks > U32_MAX) 194 193 return -EINVAL; 195 194 196 195 if (!unaligned_chunks && chunks_rem) ··· 203 202 umem->headroom = headroom; 204 203 umem->chunk_size = chunk_size; 205 204 umem->chunks = chunks; 206 - umem->npgs = (u32)npgs; 205 + umem->npgs = npgs; 207 206 umem->pgs = NULL; 208 207 umem->user = NULL; 209 208 umem->flags = mr->flags;
+2 -2
tools/lib/bpf/libbpf_internal.h
··· 20 20 /* make sure libbpf doesn't use kernel-only integer typedefs */ 21 21 #pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 22 22 23 - /* prevent accidental re-addition of reallocarray()/strlcpy() */ 24 - #pragma GCC poison reallocarray strlcpy 23 + /* prevent accidental re-addition of reallocarray() */ 24 + #pragma GCC poison reallocarray 25 25 26 26 #include "libbpf.h" 27 27 #include "btf.h"
+9
tools/testing/selftests/bpf/prog_tests/uninit_stack.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <test_progs.h> 4 + #include "uninit_stack.skel.h" 5 + 6 + void test_uninit_stack(void) 7 + { 8 + RUN_TESTS(uninit_stack); 9 + }
+1
tools/testing/selftests/bpf/progs/find_vma_fail1.c
··· 2 2 /* Copyright (c) 2021 Facebook */ 3 3 #include "vmlinux.h" 4 4 #include <bpf/bpf_helpers.h> 5 + #define vm_flags vm_start 5 6 6 7 char _license[] SEC("license") = "GPL"; 7 8
+4 -6
tools/testing/selftests/bpf/progs/test_deny_namespace.c
··· 5 5 #include <errno.h> 6 6 #include <linux/capability.h> 7 7 8 - struct kernel_cap_struct { 9 - __u64 val; 10 - } __attribute__((preserve_access_index)); 8 + typedef struct { unsigned long long val; } kernel_cap_t; 11 9 12 10 struct cred { 13 - struct kernel_cap_struct cap_effective; 11 + kernel_cap_t cap_effective; 14 12 } __attribute__((preserve_access_index)); 15 13 16 14 char _license[] SEC("license") = "GPL"; ··· 16 18 SEC("lsm.s/userns_create") 17 19 int BPF_PROG(test_userns_create, const struct cred *cred, int ret) 18 20 { 19 - struct kernel_cap_struct caps = cred->cap_effective; 20 - __u64 cap_mask = BIT_LL(CAP_SYS_ADMIN); 21 + kernel_cap_t caps = cred->cap_effective; 22 + __u64 cap_mask = 1ULL << CAP_SYS_ADMIN; 21 23 22 24 if (ret) 23 25 return 0;
+4 -4
tools/testing/selftests/bpf/progs/test_global_func10.c
··· 5 5 #include "bpf_misc.h" 6 6 7 7 struct Small { 8 - int x; 8 + long x; 9 9 }; 10 10 11 11 struct Big { 12 - int x; 13 - int y; 12 + long x; 13 + long y; 14 14 }; 15 15 16 16 __noinline int foo(const struct Big *big) ··· 22 22 } 23 23 24 24 SEC("cgroup_skb/ingress") 25 - __failure __msg("invalid indirect read from stack") 25 + __failure __msg("invalid indirect access to stack") 26 26 int global_func10(struct __sk_buff *skb) 27 27 { 28 28 const struct Small small = {.x = skb->len };
+87
tools/testing/selftests/bpf/progs/uninit_stack.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 6 + 7 + /* Read an uninitialized value from stack at a fixed offset */ 8 + SEC("socket") 9 + __naked int read_uninit_stack_fixed_off(void *ctx) 10 + { 11 + asm volatile (" \ 12 + r0 = 0; \ 13 + /* force stack depth to be 128 */ \ 14 + *(u64*)(r10 - 128) = r1; \ 15 + r1 = *(u8 *)(r10 - 8 ); \ 16 + r0 += r1; \ 17 + r1 = *(u8 *)(r10 - 11); \ 18 + r1 = *(u8 *)(r10 - 13); \ 19 + r1 = *(u8 *)(r10 - 15); \ 20 + r1 = *(u16*)(r10 - 16); \ 21 + r1 = *(u32*)(r10 - 32); \ 22 + r1 = *(u64*)(r10 - 64); \ 23 + /* read from a spill of a wrong size, it is a separate \ 24 + * branch in check_stack_read_fixed_off() \ 25 + */ \ 26 + *(u32*)(r10 - 72) = r1; \ 27 + r1 = *(u64*)(r10 - 72); \ 28 + r0 = 0; \ 29 + exit; \ 30 + " 31 + ::: __clobber_all); 32 + } 33 + 34 + /* Read an uninitialized value from stack at a variable offset */ 35 + SEC("socket") 36 + __naked int read_uninit_stack_var_off(void *ctx) 37 + { 38 + asm volatile (" \ 39 + call %[bpf_get_prandom_u32]; \ 40 + /* force stack depth to be 64 */ \ 41 + *(u64*)(r10 - 64) = r0; \ 42 + r0 = -r0; \ 43 + /* give r0 a range [-31, -1] */ \ 44 + if r0 s<= -32 goto exit_%=; \ 45 + if r0 s>= 0 goto exit_%=; \ 46 + /* access stack using r0 */ \ 47 + r1 = r10; \ 48 + r1 += r0; \ 49 + r2 = *(u8*)(r1 + 0); \ 50 + exit_%=: r0 = 0; \ 51 + exit; \ 52 + " 53 + : 54 + : __imm(bpf_get_prandom_u32) 55 + : __clobber_all); 56 + } 57 + 58 + static __noinline void dummy(void) {} 59 + 60 + /* Pass a pointer to uninitialized stack memory to a helper. 61 + * Passed memory block should be marked as STACK_MISC after helper call. 62 + */ 63 + SEC("socket") 64 + __log_level(7) __msg("fp-104=mmmmmmmm") 65 + __naked int helper_uninit_to_misc(void *ctx) 66 + { 67 + asm volatile (" \ 68 + /* force stack depth to be 128 */ \ 69 + *(u64*)(r10 - 128) = r1; \ 70 + r1 = r10; \ 71 + r1 += -128; \ 72 + r2 = 32; \ 73 + call %[bpf_trace_printk]; \ 74 + /* Call to dummy() forces print_verifier_state(..., true), \ 75 + * thus showing the stack state, matched by __msg(). \ 76 + */ \ 77 + call %[dummy]; \ 78 + r0 = 0; \ 79 + exit; \ 80 + " 81 + : 82 + : __imm(bpf_trace_printk), 83 + __imm(dummy) 84 + : __clobber_all); 85 + } 86 + 87 + char _license[] SEC("license") = "GPL";
+8 -5
tools/testing/selftests/bpf/verifier/calls.c
··· 2221 2221 * that fp-8 stack slot was unused in the fall-through 2222 2222 * branch and will accept the program incorrectly 2223 2223 */ 2224 - BPF_JMP_IMM(BPF_JGT, BPF_REG_1, 2, 2), 2224 + BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32), 2225 + BPF_JMP_IMM(BPF_JGT, BPF_REG_0, 2, 2), 2225 2226 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 2226 2227 BPF_JMP_IMM(BPF_JA, 0, 0, 0), 2227 2228 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 2228 2229 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), 2229 2230 BPF_LD_MAP_FD(BPF_REG_1, 0), 2230 2231 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), 2232 + BPF_MOV64_IMM(BPF_REG_0, 0), 2231 2233 BPF_EXIT_INSN(), 2232 2234 }, 2233 - .fixup_map_hash_48b = { 6 }, 2234 - .errstr = "invalid indirect read from stack R2 off -8+0 size 8", 2235 - .result = REJECT, 2236 - .prog_type = BPF_PROG_TYPE_XDP, 2235 + .fixup_map_hash_48b = { 7 }, 2236 + .errstr_unpriv = "invalid indirect read from stack R2 off -8+0 size 8", 2237 + .result_unpriv = REJECT, 2238 + /* in privileged mode reads from uninitialized stack locations are permitted */ 2239 + .result = ACCEPT, 2237 2240 }, 2238 2241 { 2239 2242 "calls: ctx read at start of subprog",
+69 -35
tools/testing/selftests/bpf/verifier/helper_access_var_len.c
··· 29 29 { 30 30 "helper access to variable memory: stack, bitwise AND, zero included", 31 31 .insns = { 32 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8), 33 - BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 34 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 35 - BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 36 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 37 - BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 64), 38 - BPF_MOV64_IMM(BPF_REG_3, 0), 39 - BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel), 32 + /* set max stack size */ 33 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0), 34 + /* set r3 to a random value */ 35 + BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32), 36 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 37 + /* use bitwise AND to limit r3 range to [0, 64] */ 38 + BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 64), 39 + BPF_LD_MAP_FD(BPF_REG_1, 0), 40 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 41 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64), 42 + BPF_MOV64_IMM(BPF_REG_4, 0), 43 + /* Call bpf_ringbuf_output(), it is one of a few helper functions with 44 + * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode. 45 + * For unpriv this should signal an error, because memory at &fp[-64] is 46 + * not initialized. 47 + */ 48 + BPF_EMIT_CALL(BPF_FUNC_ringbuf_output), 40 49 BPF_EXIT_INSN(), 41 50 }, 42 - .errstr = "invalid indirect read from stack R1 off -64+0 size 64", 43 - .result = REJECT, 44 - .prog_type = BPF_PROG_TYPE_TRACEPOINT, 51 + .fixup_map_ringbuf = { 4 }, 52 + .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64", 53 + .result_unpriv = REJECT, 54 + /* in privileged mode reads from uninitialized stack locations are permitted */ 55 + .result = ACCEPT, 45 56 }, 46 57 { 47 58 "helper access to variable memory: stack, bitwise AND + JMP, wrong max", ··· 194 183 { 195 184 "helper access to variable memory: stack, JMP, no min check", 196 185 .insns = { 197 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8), 198 - BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 199 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 200 - BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_2, -128), 201 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, -128), 202 - BPF_JMP_IMM(BPF_JGT, BPF_REG_2, 64, 3), 203 - BPF_MOV64_IMM(BPF_REG_3, 0), 204 - BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel), 186 + /* set max stack size */ 187 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0), 188 + /* set r3 to a random value */ 189 + BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32), 190 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 191 + /* use JMP to limit r3 range to [0, 64] */ 192 + BPF_JMP_IMM(BPF_JGT, BPF_REG_3, 64, 6), 193 + BPF_LD_MAP_FD(BPF_REG_1, 0), 194 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 195 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64), 196 + BPF_MOV64_IMM(BPF_REG_4, 0), 197 + /* Call bpf_ringbuf_output(), it is one of a few helper functions with 198 + * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode. 199 + * For unpriv this should signal an error, because memory at &fp[-64] is 200 + * not initialized. 201 + */ 202 + BPF_EMIT_CALL(BPF_FUNC_ringbuf_output), 205 203 BPF_MOV64_IMM(BPF_REG_0, 0), 206 204 BPF_EXIT_INSN(), 207 205 }, 208 - .errstr = "invalid indirect read from stack R1 off -64+0 size 64", 209 - .result = REJECT, 210 - .prog_type = BPF_PROG_TYPE_TRACEPOINT, 206 + .fixup_map_ringbuf = { 4 }, 207 + .errstr_unpriv = "invalid indirect read from stack R2 off -64+0 size 64", 208 + .result_unpriv = REJECT, 209 + /* in privileged mode reads from uninitialized stack locations are permitted */ 210 + .result = ACCEPT, 211 211 }, 212 212 { 213 213 "helper access to variable memory: stack, JMP (signed), no min check", ··· 586 564 { 587 565 "helper access to variable memory: 8 bytes leak", 588 566 .insns = { 589 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 8), 590 - BPF_MOV64_REG(BPF_REG_1, BPF_REG_10), 591 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -64), 567 + /* set max stack size */ 568 + BPF_ST_MEM(BPF_DW, BPF_REG_10, -128, 0), 569 + /* set r3 to a random value */ 570 + BPF_EMIT_CALL(BPF_FUNC_get_prandom_u32), 571 + BPF_MOV64_REG(BPF_REG_3, BPF_REG_0), 572 + BPF_LD_MAP_FD(BPF_REG_1, 0), 573 + BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), 574 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -64), 592 575 BPF_MOV64_IMM(BPF_REG_0, 0), 593 576 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -64), 594 577 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -56), 595 578 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -48), 596 579 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -40), 580 + /* Note: fp[-32] left uninitialized */ 597 581 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -24), 598 582 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -16), 599 583 BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8), 600 - BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_2, -128), 601 - BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_10, -128), 602 - BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 63), 603 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, 1), 604 - BPF_MOV64_IMM(BPF_REG_3, 0), 605 - BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel), 606 - BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -16), 584 + /* Limit r3 range to [1, 64] */ 585 + BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 63), 586 + BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 1), 587 + BPF_MOV64_IMM(BPF_REG_4, 0), 588 + /* Call bpf_ringbuf_output(), it is one of a few helper functions with 589 + * ARG_CONST_SIZE_OR_ZERO parameter allowed in unpriv mode. 590 + * For unpriv this should signal an error, because memory region [1, 64] 591 + * at &fp[-64] is not fully initialized. 592 + */ 593 + BPF_EMIT_CALL(BPF_FUNC_ringbuf_output), 594 + BPF_MOV64_IMM(BPF_REG_0, 0), 607 595 BPF_EXIT_INSN(), 608 596 }, 609 - .errstr = "invalid indirect read from stack R1 off -64+32 size 64", 610 - .result = REJECT, 611 - .prog_type = BPF_PROG_TYPE_TRACEPOINT, 597 + .fixup_map_ringbuf = { 3 }, 598 + .errstr_unpriv = "invalid indirect read from stack R2 off -64+32 size 64", 599 + .result_unpriv = REJECT, 600 + /* in privileged mode reads from uninitialized stack locations are permitted */ 601 + .result = ACCEPT, 612 602 }, 613 603 { 614 604 "helper access to variable memory: 8 bytes no leak (init memory)",
+5 -4
tools/testing/selftests/bpf/verifier/int_ptr.c
··· 54 54 /* bpf_strtoul() */ 55 55 BPF_EMIT_CALL(BPF_FUNC_strtoul), 56 56 57 - BPF_MOV64_IMM(BPF_REG_0, 1), 57 + BPF_MOV64_IMM(BPF_REG_0, 0), 58 58 BPF_EXIT_INSN(), 59 59 }, 60 - .result = REJECT, 61 - .prog_type = BPF_PROG_TYPE_CGROUP_SYSCTL, 62 - .errstr = "invalid indirect read from stack R4 off -16+4 size 8", 60 + .result_unpriv = REJECT, 61 + .errstr_unpriv = "invalid indirect read from stack R4 off -16+4 size 8", 62 + /* in privileged mode reads from uninitialized stack locations are permitted */ 63 + .result = ACCEPT, 63 64 }, 64 65 { 65 66 "ARG_PTR_TO_LONG misaligned",
+8 -5
tools/testing/selftests/bpf/verifier/search_pruning.c
··· 128 128 BPF_EXIT_INSN(), 129 129 }, 130 130 .fixup_map_hash_8b = { 3 }, 131 - .errstr = "invalid read from stack off -16+0 size 8", 132 - .result = REJECT, 133 - .prog_type = BPF_PROG_TYPE_TRACEPOINT, 131 + .errstr_unpriv = "invalid read from stack off -16+0 size 8", 132 + .result_unpriv = REJECT, 133 + /* in privileged mode reads from uninitialized stack locations are permitted */ 134 + .result = ACCEPT, 134 135 }, 135 136 { 136 137 "precision tracking for u32 spill/fill", ··· 259 258 BPF_EXIT_INSN(), 260 259 }, 261 260 .flags = BPF_F_TEST_STATE_FREQ, 262 - .errstr = "invalid read from stack off -8+1 size 8", 263 - .result = REJECT, 261 + .errstr_unpriv = "invalid read from stack off -8+1 size 8", 262 + .result_unpriv = REJECT, 263 + /* in privileged mode reads from uninitialized stack locations are permitted */ 264 + .result = ACCEPT, 264 265 },
-27
tools/testing/selftests/bpf/verifier/sock.c
··· 531 531 .result = ACCEPT, 532 532 }, 533 533 { 534 - "sk_storage_get(map, skb->sk, &stack_value, 1): partially init stack_value", 535 - .insns = { 536 - BPF_MOV64_IMM(BPF_REG_2, 0), 537 - BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_2, -8), 538 - BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_1, offsetof(struct __sk_buff, sk)), 539 - BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 2), 540 - BPF_MOV64_IMM(BPF_REG_0, 0), 541 - BPF_EXIT_INSN(), 542 - BPF_EMIT_CALL(BPF_FUNC_sk_fullsock), 543 - BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 2), 544 - BPF_MOV64_IMM(BPF_REG_0, 0), 545 - BPF_EXIT_INSN(), 546 - BPF_MOV64_IMM(BPF_REG_4, 1), 547 - BPF_MOV64_REG(BPF_REG_3, BPF_REG_10), 548 - BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, -8), 549 - BPF_MOV64_REG(BPF_REG_2, BPF_REG_0), 550 - BPF_LD_MAP_FD(BPF_REG_1, 0), 551 - BPF_EMIT_CALL(BPF_FUNC_sk_storage_get), 552 - BPF_MOV64_IMM(BPF_REG_0, 0), 553 - BPF_EXIT_INSN(), 554 - }, 555 - .fixup_sk_storage_map = { 14 }, 556 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 557 - .result = REJECT, 558 - .errstr = "invalid indirect read from stack", 559 - }, 560 - { 561 534 "bpf_map_lookup_elem(smap, &key)", 562 535 .insns = { 563 536 BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 0),
+4 -3
tools/testing/selftests/bpf/verifier/spill_fill.c
··· 171 171 BPF_MOV64_IMM(BPF_REG_0, 0), 172 172 BPF_EXIT_INSN(), 173 173 }, 174 - .result = REJECT, 175 - .errstr = "invalid read from stack off -4+0 size 4", 176 - .prog_type = BPF_PROG_TYPE_SCHED_CLS, 174 + .result_unpriv = REJECT, 175 + .errstr_unpriv = "invalid read from stack off -4+0 size 4", 176 + /* in privileged mode reads from uninitialized stack locations are permitted */ 177 + .result = ACCEPT, 177 178 }, 178 179 { 179 180 "Spill a u32 const scalar. Refill as u16. Offset to skb->data",
-52
tools/testing/selftests/bpf/verifier/var_off.c
··· 213 213 .prog_type = BPF_PROG_TYPE_LWT_IN, 214 214 }, 215 215 { 216 - "indirect variable-offset stack access, max_off+size > max_initialized", 217 - .insns = { 218 - /* Fill only the second from top 8 bytes of the stack. */ 219 - BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0), 220 - /* Get an unknown value. */ 221 - BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0), 222 - /* Make it small and 4-byte aligned. */ 223 - BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4), 224 - BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16), 225 - /* Add it to fp. We now have either fp-12 or fp-16, but we don't know 226 - * which. fp-12 size 8 is partially uninitialized stack. 227 - */ 228 - BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10), 229 - /* Dereference it indirectly. */ 230 - BPF_LD_MAP_FD(BPF_REG_1, 0), 231 - BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem), 232 - BPF_MOV64_IMM(BPF_REG_0, 0), 233 - BPF_EXIT_INSN(), 234 - }, 235 - .fixup_map_hash_8b = { 5 }, 236 - .errstr = "invalid indirect read from stack R2 var_off", 237 - .result = REJECT, 238 - .prog_type = BPF_PROG_TYPE_LWT_IN, 239 - }, 240 - { 241 216 "indirect variable-offset stack access, min_off < min_initialized", 242 217 .insns = { 243 218 /* Fill only the top 8 bytes of the stack. */ ··· 263 288 .result_unpriv = REJECT, 264 289 .result = ACCEPT, 265 290 .prog_type = BPF_PROG_TYPE_CGROUP_SKB, 266 - }, 267 - { 268 - "indirect variable-offset stack access, uninitialized", 269 - .insns = { 270 - BPF_MOV64_IMM(BPF_REG_2, 6), 271 - BPF_MOV64_IMM(BPF_REG_3, 28), 272 - /* Fill the top 16 bytes of the stack. */ 273 - BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0), 274 - BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), 275 - /* Get an unknown value. */ 276 - BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0), 277 - /* Make it small and 4-byte aligned. */ 278 - BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4), 279 - BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16), 280 - /* Add it to fp. We now have either fp-12 or fp-16, we don't know 281 - * which, but either way it points to initialized stack. 282 - */ 283 - BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10), 284 - BPF_MOV64_IMM(BPF_REG_5, 8), 285 - /* Dereference it indirectly. */ 286 - BPF_EMIT_CALL(BPF_FUNC_getsockopt), 287 - BPF_MOV64_IMM(BPF_REG_0, 0), 288 - BPF_EXIT_INSN(), 289 - }, 290 - .errstr = "invalid indirect read from stack R4 var_off", 291 - .result = REJECT, 292 - .prog_type = BPF_PROG_TYPE_SOCK_OPS, 293 291 }, 294 292 { 295 293 "indirect variable-offset stack access, ok",