From: Greg Kroah-Hartman Date: Mon, 23 Jun 2025 09:58:00 +0000 (+0200) Subject: drop bpf series from 5.10.y that break the build X-Git-Tag: v5.4.295~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=45715fe6ac5f1f88fb87d360b5e4d712031553ef;p=thirdparty%2Fkernel%2Fstable-queue.git drop bpf series from 5.10.y that break the build --- diff --git a/queue-5.10/bpf-add-mem_rdonly-for-helper-args-that-are-pointers-to-rdonly-mem.patch b/queue-5.10/bpf-add-mem_rdonly-for-helper-args-that-are-pointers-to-rdonly-mem.patch deleted file mode 100644 index 80cd32caf5..0000000000 --- a/queue-5.10/bpf-add-mem_rdonly-for-helper-args-that-are-pointers-to-rdonly-mem.patch +++ /dev/null @@ -1,513 +0,0 @@ -From stable+bounces-152308-greg=kroah.com@vger.kernel.org Tue Jun 10 16:46:36 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:44:02 +0000 -Subject: bpf: Add MEM_RDONLY for helper args that are pointers to rdonly mem. -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-8-puranjay@kernel.org> - -From: Hao Luo - -commit 216e3cd2f28dbbf1fe86848e0e29e6693b9f0a20 upstream. - -Some helper functions may modify its arguments, for example, -bpf_d_path, bpf_get_stack etc. Previously, their argument types -were marked as ARG_PTR_TO_MEM, which is compatible with read-only -mem types, such as PTR_TO_RDONLY_BUF. Therefore it's legitimate, -but technically incorrect, to modify a read-only memory by passing -it into one of such helper functions. - -This patch tags the bpf_args compatible with immutable memory with -MEM_RDONLY flag. The arguments that don't have this flag will be -only compatible with mutable memory types, preventing the helper -from modifying a read-only memory. The bpf_args that have -MEM_RDONLY are compatible with both mutable memory and immutable -memory. - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-9-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 4 ++- - kernel/bpf/cgroup.c | 2 - - kernel/bpf/helpers.c | 6 ++-- - kernel/bpf/ringbuf.c | 2 - - kernel/bpf/verifier.c | 20 ++++++++++++--- - kernel/trace/bpf_trace.c | 22 ++++++++-------- - net/core/filter.c | 62 +++++++++++++++++++++++------------------------ - 7 files changed, 67 insertions(+), 51 deletions(-) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -277,7 +277,9 @@ enum bpf_type_flag { - /* PTR may be NULL. */ - PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), - -- /* MEM is read-only. */ -+ /* MEM is read-only. When applied on bpf_arg, it indicates the arg is -+ * compatible with both mutable and immutable memory. -+ */ - MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS), - - __BPF_TYPE_LAST_FLAG = MEM_RDONLY, ---- a/kernel/bpf/cgroup.c -+++ b/kernel/bpf/cgroup.c -@@ -1738,7 +1738,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - }; - ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -516,7 +516,7 @@ const struct bpf_func_proto bpf_strtol_p - .func = bpf_strtol, - .gpl_only = false, - .ret_type = RET_INTEGER, -- .arg1_type = ARG_PTR_TO_MEM, -+ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg2_type = ARG_CONST_SIZE, - .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_LONG, -@@ -544,7 +544,7 @@ const struct bpf_func_proto bpf_strtoul_ - .func = bpf_strtoul, - .gpl_only = false, - .ret_type = RET_INTEGER, -- .arg1_type = ARG_PTR_TO_MEM, -+ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg2_type = ARG_CONST_SIZE, - .arg3_type = ARG_ANYTHING, - .arg4_type = ARG_PTR_TO_LONG, -@@ -616,7 +616,7 @@ const struct bpf_func_proto bpf_event_ou - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - ---- a/kernel/bpf/ringbuf.c -+++ b/kernel/bpf/ringbuf.c -@@ -483,7 +483,7 @@ const struct bpf_func_proto bpf_ringbuf_ - .func = bpf_ringbuf_output, - .ret_type = RET_INTEGER, - .arg1_type = ARG_CONST_MAP_PTR, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE_OR_ZERO, - .arg4_type = ARG_ANYTHING, - }; ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -4602,7 +4602,6 @@ static const struct bpf_reg_types mem_ty - PTR_TO_MAP_VALUE, - PTR_TO_MEM, - PTR_TO_BUF, -- PTR_TO_BUF | MEM_RDONLY, - }, - }; - -@@ -4663,6 +4662,21 @@ static int check_reg_type(struct bpf_ver - return -EFAULT; - } - -+ /* ARG_PTR_TO_MEM + RDONLY is compatible with PTR_TO_MEM and PTR_TO_MEM + RDONLY, -+ * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM and NOT with PTR_TO_MEM + RDONLY -+ * -+ * Same for MAYBE_NULL: -+ * -+ * ARG_PTR_TO_MEM + MAYBE_NULL is compatible with PTR_TO_MEM and PTR_TO_MEM + MAYBE_NULL, -+ * but ARG_PTR_TO_MEM is compatible only with PTR_TO_MEM but NOT with PTR_TO_MEM + MAYBE_NULL -+ * -+ * Therefore we fold these flags depending on the arg_type before comparison. -+ */ -+ if (arg_type & MEM_RDONLY) -+ type &= ~MEM_RDONLY; -+ if (arg_type & PTR_MAYBE_NULL) -+ type &= ~PTR_MAYBE_NULL; -+ - for (i = 0; i < ARRAY_SIZE(compatible->types); i++) { - expected = compatible->types[i]; - if (expected == NOT_INIT) -@@ -4672,14 +4686,14 @@ static int check_reg_type(struct bpf_ver - goto found; - } - -- verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, type)); -+ verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, reg->type)); - for (j = 0; j + 1 < i; j++) - verbose(env, "%s, ", reg_type_str(env, compatible->types[j])); - verbose(env, "%s\n", reg_type_str(env, compatible->types[j])); - return -EACCES; - - found: -- if (type == PTR_TO_BTF_ID) { -+ if (reg->type == PTR_TO_BTF_ID) { - if (!arg_btf_id) { - if (!compatible->btf_id) { - verbose(env, "verifier internal error: missing arg compatible BTF ID\n"); ---- a/kernel/trace/bpf_trace.c -+++ b/kernel/trace/bpf_trace.c -@@ -342,7 +342,7 @@ static const struct bpf_func_proto bpf_p - .gpl_only = true, - .ret_type = RET_INTEGER, - .arg1_type = ARG_ANYTHING, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - }; - -@@ -545,7 +545,7 @@ static const struct bpf_func_proto bpf_t - .func = bpf_trace_printk, - .gpl_only = true, - .ret_type = RET_INTEGER, -- .arg1_type = ARG_PTR_TO_MEM, -+ .arg1_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg2_type = ARG_CONST_SIZE, - }; - -@@ -754,9 +754,9 @@ static const struct bpf_func_proto bpf_s - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_BTF_ID, - .arg1_btf_id = &btf_seq_file_ids[0], -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, -- .arg4_type = ARG_PTR_TO_MEM_OR_NULL, -+ .arg4_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -771,7 +771,7 @@ static const struct bpf_func_proto bpf_s - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_BTF_ID, - .arg1_btf_id = &btf_seq_file_ids[0], -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -795,7 +795,7 @@ static const struct bpf_func_proto bpf_s - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_BTF_ID, - .arg1_btf_id = &btf_seq_file_ids[0], -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE_OR_ZERO, - .arg4_type = ARG_ANYTHING, - }; -@@ -956,7 +956,7 @@ static const struct bpf_func_proto bpf_p - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -1247,7 +1247,7 @@ const struct bpf_func_proto bpf_snprintf - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_MEM, - .arg2_type = ARG_CONST_SIZE, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE, - .arg5_type = ARG_ANYTHING, - }; -@@ -1422,7 +1422,7 @@ static const struct bpf_func_proto bpf_p - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -1640,7 +1640,7 @@ static const struct bpf_func_proto bpf_p - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -1694,7 +1694,7 @@ static const struct bpf_func_proto bpf_g - .gpl_only = true, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE_OR_ZERO, - .arg4_type = ARG_ANYTHING, - }; ---- a/net/core/filter.c -+++ b/net/core/filter.c -@@ -1724,7 +1724,7 @@ static const struct bpf_func_proto bpf_s - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE, - .arg5_type = ARG_ANYTHING, - }; -@@ -2033,9 +2033,9 @@ static const struct bpf_func_proto bpf_c - .gpl_only = false, - .pkt_access = true, - .ret_type = RET_INTEGER, -- .arg1_type = ARG_PTR_TO_MEM_OR_NULL, -+ .arg1_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, - .arg2_type = ARG_CONST_SIZE_OR_ZERO, -- .arg3_type = ARG_PTR_TO_MEM_OR_NULL, -+ .arg3_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE_OR_ZERO, - .arg5_type = ARG_ANYTHING, - }; -@@ -2582,7 +2582,7 @@ static const struct bpf_func_proto bpf_r - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_ANYTHING, -- .arg2_type = ARG_PTR_TO_MEM_OR_NULL, -+ .arg2_type = ARG_PTR_TO_MEM | PTR_MAYBE_NULL | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE_OR_ZERO, - .arg4_type = ARG_ANYTHING, - }; -@@ -4254,7 +4254,7 @@ static const struct bpf_func_proto bpf_s - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -4268,7 +4268,7 @@ const struct bpf_func_proto bpf_skb_outp - .arg1_btf_id = &bpf_skb_output_btf_ids[0], - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -4451,7 +4451,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - }; -@@ -4477,7 +4477,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - }; - -@@ -4647,7 +4647,7 @@ static const struct bpf_func_proto bpf_x - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -4661,7 +4661,7 @@ const struct bpf_func_proto bpf_xdp_outp - .arg1_btf_id = &bpf_xdp_output_btf_ids[0], - .arg2_type = ARG_CONST_MAP_PTR, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE_OR_ZERO, - }; - -@@ -5079,7 +5079,7 @@ static const struct bpf_func_proto bpf_s - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE, - }; - -@@ -5113,7 +5113,7 @@ static const struct bpf_func_proto bpf_s - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, - .arg3_type = ARG_ANYTHING, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE, - }; - -@@ -5288,7 +5288,7 @@ static const struct bpf_func_proto bpf_b - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - }; - -@@ -5749,7 +5749,7 @@ static const struct bpf_func_proto bpf_l - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE - }; - -@@ -5759,7 +5759,7 @@ static const struct bpf_func_proto bpf_l - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE - }; - -@@ -5802,7 +5802,7 @@ static const struct bpf_func_proto bpf_l - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE - }; - -@@ -5890,7 +5890,7 @@ static const struct bpf_func_proto bpf_l - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, - .arg2_type = ARG_ANYTHING, -- .arg3_type = ARG_PTR_TO_MEM, -+ .arg3_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg4_type = ARG_CONST_SIZE - }; - -@@ -6137,7 +6137,7 @@ static const struct bpf_func_proto bpf_s - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6156,7 +6156,7 @@ static const struct bpf_func_proto bpf_s - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6175,7 +6175,7 @@ static const struct bpf_func_proto bpf_s - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6212,7 +6212,7 @@ static const struct bpf_func_proto bpf_x - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6235,7 +6235,7 @@ static const struct bpf_func_proto bpf_x - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6258,7 +6258,7 @@ static const struct bpf_func_proto bpf_x - .pkt_access = true, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6277,7 +6277,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_PTR_TO_SOCK_COMMON_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6296,7 +6296,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6315,7 +6315,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_PTR_TO_SOCKET_OR_NULL, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - .arg5_type = ARG_ANYTHING, -@@ -6637,9 +6637,9 @@ static const struct bpf_func_proto bpf_t - .pkt_access = true, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE, - }; - -@@ -6706,9 +6706,9 @@ static const struct bpf_func_proto bpf_t - .pkt_access = true, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, -- .arg4_type = ARG_PTR_TO_MEM, -+ .arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg5_type = ARG_CONST_SIZE, - }; - -@@ -6939,7 +6939,7 @@ static const struct bpf_func_proto bpf_s - .gpl_only = false, - .ret_type = RET_INTEGER, - .arg1_type = ARG_PTR_TO_CTX, -- .arg2_type = ARG_PTR_TO_MEM, -+ .arg2_type = ARG_PTR_TO_MEM | MEM_RDONLY, - .arg3_type = ARG_CONST_SIZE, - .arg4_type = ARG_ANYTHING, - }; diff --git a/queue-5.10/bpf-introduce-composable-reg-ret-and-arg-types.patch b/queue-5.10/bpf-introduce-composable-reg-ret-and-arg-types.patch deleted file mode 100644 index acb735b495..0000000000 --- a/queue-5.10/bpf-introduce-composable-reg-ret-and-arg-types.patch +++ /dev/null @@ -1,147 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:20 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:43:56 +0000 -Subject: bpf: Introduce composable reg, ret and arg types. -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-2-puranjay@kernel.org> - -From: Hao Luo - -commit d639b9d13a39cf15639cbe6e8b2c43eb60148a73 upstream. - -There are some common properties shared between bpf reg, ret and arg -values. For instance, a value may be a NULL pointer, or a pointer to -a read-only memory. Previously, to express these properties, enumeration -was used. For example, in order to test whether a reg value can be NULL, -reg_type_may_be_null() simply enumerates all types that are possibly -NULL. The problem of this approach is that it's not scalable and causes -a lot of duplication. These properties can be combined, for example, a -type could be either MAYBE_NULL or RDONLY, or both. - -This patch series rewrites the layout of reg_type, arg_type and -ret_type, so that common properties can be extracted and represented as -composable flag. For example, one can write - - ARG_PTR_TO_MEM | PTR_MAYBE_NULL - -which is equivalent to the previous - - ARG_PTR_TO_MEM_OR_NULL - -The type ARG_PTR_TO_MEM are called "base type" in this patch. Base -types can be extended with flags. A flag occupies the higher bits while -base types sits in the lower bits. - -This patch in particular sets up a set of macro for this purpose. The -following patches will rewrite arg_types, ret_types and reg_types -respectively. - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-2-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 43 +++++++++++++++++++++++++++++++++++++++++++ - include/linux/bpf_verifier.h | 14 ++++++++++++++ - 2 files changed, 57 insertions(+) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -263,6 +263,29 @@ bool bpf_map_meta_equal(const struct bpf - - extern const struct bpf_map_ops bpf_map_offload_ops; - -+/* bpf_type_flag contains a set of flags that are applicable to the values of -+ * arg_type, ret_type and reg_type. For example, a pointer value may be null, -+ * or a memory is read-only. We classify types into two categories: base types -+ * and extended types. Extended types are base types combined with a type flag. -+ * -+ * Currently there are no more than 32 base types in arg_type, ret_type and -+ * reg_types. -+ */ -+#define BPF_BASE_TYPE_BITS 8 -+ -+enum bpf_type_flag { -+ /* PTR may be NULL. */ -+ PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), -+ -+ __BPF_TYPE_LAST_FLAG = PTR_MAYBE_NULL, -+}; -+ -+/* Max number of base types. */ -+#define BPF_BASE_TYPE_LIMIT (1UL << BPF_BASE_TYPE_BITS) -+ -+/* Max number of all types. */ -+#define BPF_TYPE_LIMIT (__BPF_TYPE_LAST_FLAG | (__BPF_TYPE_LAST_FLAG - 1)) -+ - /* function argument constraints */ - enum bpf_arg_type { - ARG_DONTCARE = 0, /* unused argument in helper function */ -@@ -305,7 +328,13 @@ enum bpf_arg_type { - ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */ - ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */ - __BPF_ARG_TYPE_MAX, -+ -+ /* This must be the last entry. Its purpose is to ensure the enum is -+ * wide enough to hold the higher bits reserved for bpf_type_flag. -+ */ -+ __BPF_ARG_TYPE_LIMIT = BPF_TYPE_LIMIT, - }; -+static_assert(__BPF_ARG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); - - /* type of values returned from helper functions */ - enum bpf_return_type { -@@ -320,7 +349,14 @@ enum bpf_return_type { - RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */ - RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ - RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ -+ __BPF_RET_TYPE_MAX, -+ -+ /* This must be the last entry. Its purpose is to ensure the enum is -+ * wide enough to hold the higher bits reserved for bpf_type_flag. -+ */ -+ __BPF_RET_TYPE_LIMIT = BPF_TYPE_LIMIT, - }; -+static_assert(__BPF_RET_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); - - /* eBPF function prototype used by verifier to allow BPF_CALLs from eBPF programs - * to in-kernel helper functions and for adjusting imm32 field in BPF_CALL -@@ -419,7 +455,14 @@ enum bpf_reg_type { - PTR_TO_RDWR_BUF, /* reg points to a read/write buffer */ - PTR_TO_RDWR_BUF_OR_NULL, /* reg points to a read/write buffer or NULL */ - PTR_TO_PERCPU_BTF_ID, /* reg points to a percpu kernel variable */ -+ __BPF_REG_TYPE_MAX, -+ -+ /* This must be the last entry. Its purpose is to ensure the enum is -+ * wide enough to hold the higher bits reserved for bpf_type_flag. -+ */ -+ __BPF_REG_TYPE_LIMIT = BPF_TYPE_LIMIT, - }; -+static_assert(__BPF_REG_TYPE_MAX <= BPF_BASE_TYPE_LIMIT); - - /* The information passed from prog-specific *_is_valid_access - * back to the verifier. ---- a/include/linux/bpf_verifier.h -+++ b/include/linux/bpf_verifier.h -@@ -509,4 +509,18 @@ int bpf_check_attach_target(struct bpf_v - u32 btf_id, - struct bpf_attach_target_info *tgt_info); - -+#define BPF_BASE_TYPE_MASK GENMASK(BPF_BASE_TYPE_BITS - 1, 0) -+ -+/* extract base type from bpf_{arg, return, reg}_type. */ -+static inline u32 base_type(u32 type) -+{ -+ return type & BPF_BASE_TYPE_MASK; -+} -+ -+/* extract flags from an extended type. See bpf_type_flag in bpf.h. */ -+static inline u32 type_flag(u32 type) -+{ -+ return type & ~BPF_BASE_TYPE_MASK; -+} -+ - #endif /* _LINUX_BPF_VERIFIER_H */ diff --git a/queue-5.10/bpf-introduce-mem_rdonly-flag.patch b/queue-5.10/bpf-introduce-mem_rdonly-flag.patch deleted file mode 100644 index 7e5960f272..0000000000 --- a/queue-5.10/bpf-introduce-mem_rdonly-flag.patch +++ /dev/null @@ -1,259 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:37 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:44:00 +0000 -Subject: bpf: Introduce MEM_RDONLY flag -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-6-puranjay@kernel.org> - -From: Hao Luo - -commit 20b2aff4bc15bda809f994761d5719827d66c0b4 upstream. - -This patch introduce a flag MEM_RDONLY to tag a reg value -pointing to read-only memory. It makes the following changes: - -1. PTR_TO_RDWR_BUF -> PTR_TO_BUF -2. PTR_TO_RDONLY_BUF -> PTR_TO_BUF | MEM_RDONLY - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-6-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 8 ++-- - kernel/bpf/btf.c | 3 - - kernel/bpf/map_iter.c | 4 +- - kernel/bpf/verifier.c | 84 +++++++++++++++++++++++++++------------------- - net/core/bpf_sk_storage.c | 2 - - net/core/sock_map.c | 2 - - 6 files changed, 60 insertions(+), 43 deletions(-) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -277,7 +277,10 @@ enum bpf_type_flag { - /* PTR may be NULL. */ - PTR_MAYBE_NULL = BIT(0 + BPF_BASE_TYPE_BITS), - -- __BPF_TYPE_LAST_FLAG = PTR_MAYBE_NULL, -+ /* MEM is read-only. */ -+ MEM_RDONLY = BIT(1 + BPF_BASE_TYPE_BITS), -+ -+ __BPF_TYPE_LAST_FLAG = MEM_RDONLY, - }; - - /* Max number of base types. */ -@@ -452,8 +455,7 @@ enum bpf_reg_type { - * an explicit null check is required for this struct. - */ - PTR_TO_MEM, /* reg points to valid memory region */ -- PTR_TO_RDONLY_BUF, /* reg points to a readonly buffer */ -- PTR_TO_RDWR_BUF, /* reg points to a read/write buffer */ -+ PTR_TO_BUF, /* reg points to a read/write buffer */ - PTR_TO_PERCPU_BTF_ID, /* reg points to a percpu kernel variable */ - __BPF_REG_TYPE_MAX, - ---- a/kernel/bpf/btf.c -+++ b/kernel/bpf/btf.c -@@ -4539,8 +4539,7 @@ bool btf_ctx_access(int off, int size, e - - type = base_type(ctx_arg_info->reg_type); - flag = type_flag(ctx_arg_info->reg_type); -- if (ctx_arg_info->offset == off && -- (type == PTR_TO_RDWR_BUF || type == PTR_TO_RDONLY_BUF) && -+ if (ctx_arg_info->offset == off && type == PTR_TO_BUF && - (flag & PTR_MAYBE_NULL)) { - info->reg_type = ctx_arg_info->reg_type; - return true; ---- a/kernel/bpf/map_iter.c -+++ b/kernel/bpf/map_iter.c -@@ -174,9 +174,9 @@ static const struct bpf_iter_reg bpf_map - .ctx_arg_info_size = 2, - .ctx_arg_info = { - { offsetof(struct bpf_iter__bpf_map_elem, key), -- PTR_TO_RDONLY_BUF | PTR_MAYBE_NULL }, -+ PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY }, - { offsetof(struct bpf_iter__bpf_map_elem, value), -- PTR_TO_RDWR_BUF | PTR_MAYBE_NULL }, -+ PTR_TO_BUF | PTR_MAYBE_NULL }, - }, - }; - ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -417,6 +417,11 @@ static bool reg_type_may_be_refcounted_o - base_type(type) == PTR_TO_MEM; - } - -+static bool type_is_rdonly_mem(u32 type) -+{ -+ return type & MEM_RDONLY; -+} -+ - static bool arg_type_may_be_refcounted(enum bpf_arg_type type) - { - return type == ARG_PTR_TO_SOCK_COMMON; -@@ -485,7 +490,7 @@ static bool is_ptr_cast_function(enum bp - static const char *reg_type_str(struct bpf_verifier_env *env, - enum bpf_reg_type type) - { -- char postfix[16] = {0}; -+ char postfix[16] = {0}, prefix[16] = {0}; - static const char * const str[] = { - [NOT_INIT] = "?", - [SCALAR_VALUE] = "inv", -@@ -505,8 +510,7 @@ static const char *reg_type_str(struct b - [PTR_TO_BTF_ID] = "ptr_", - [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", - [PTR_TO_MEM] = "mem", -- [PTR_TO_RDONLY_BUF] = "rdonly_buf", -- [PTR_TO_RDWR_BUF] = "rdwr_buf", -+ [PTR_TO_BUF] = "buf", - }; - - if (type & PTR_MAYBE_NULL) { -@@ -517,8 +521,11 @@ static const char *reg_type_str(struct b - strncpy(postfix, "_or_null", 16); - } - -- snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s", -- str[base_type(type)], postfix); -+ if (type & MEM_RDONLY) -+ strncpy(prefix, "rdonly_", 16); -+ -+ snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s%s", -+ prefix, str[base_type(type)], postfix); - return env->type_str_buf; - } - -@@ -2376,8 +2383,7 @@ static bool is_spillable_regtype(enum bp - case PTR_TO_TCP_SOCK: - case PTR_TO_XDP_SOCK: - case PTR_TO_BTF_ID: -- case PTR_TO_RDONLY_BUF: -- case PTR_TO_RDWR_BUF: -+ case PTR_TO_BUF: - case PTR_TO_PERCPU_BTF_ID: - case PTR_TO_MEM: - return true; -@@ -4120,22 +4126,28 @@ static int check_mem_access(struct bpf_v - } else if (reg->type == CONST_PTR_TO_MAP) { - err = check_ptr_to_map_access(env, regs, regno, off, size, t, - value_regno); -- } else if (reg->type == PTR_TO_RDONLY_BUF) { -- if (t == BPF_WRITE) { -- verbose(env, "R%d cannot write into %s\n", -- regno, reg_type_str(env, reg->type)); -- return -EACCES; -+ } else if (base_type(reg->type) == PTR_TO_BUF) { -+ bool rdonly_mem = type_is_rdonly_mem(reg->type); -+ const char *buf_info; -+ u32 *max_access; -+ -+ if (rdonly_mem) { -+ if (t == BPF_WRITE) { -+ verbose(env, "R%d cannot write into %s\n", -+ regno, reg_type_str(env, reg->type)); -+ return -EACCES; -+ } -+ buf_info = "rdonly"; -+ max_access = &env->prog->aux->max_rdonly_access; -+ } else { -+ buf_info = "rdwr"; -+ max_access = &env->prog->aux->max_rdwr_access; - } -+ - err = check_buffer_access(env, reg, regno, off, size, false, -- "rdonly", -- &env->prog->aux->max_rdonly_access); -- if (!err && value_regno >= 0) -- mark_reg_unknown(env, regs, value_regno); -- } else if (reg->type == PTR_TO_RDWR_BUF) { -- err = check_buffer_access(env, reg, regno, off, size, false, -- "rdwr", -- &env->prog->aux->max_rdwr_access); -- if (!err && t == BPF_READ && value_regno >= 0) -+ buf_info, max_access); -+ -+ if (!err && value_regno >= 0 && (rdonly_mem || t == BPF_READ)) - mark_reg_unknown(env, regs, value_regno); - } else { - verbose(env, "R%d invalid mem access '%s'\n", regno, -@@ -4339,8 +4351,10 @@ static int check_helper_mem_access(struc - struct bpf_call_arg_meta *meta) - { - struct bpf_reg_state *regs = cur_regs(env), *reg = ®s[regno]; -+ const char *buf_info; -+ u32 *max_access; - -- switch (reg->type) { -+ switch (base_type(reg->type)) { - case PTR_TO_PACKET: - case PTR_TO_PACKET_META: - return check_packet_access(env, regno, reg->off, access_size, -@@ -4356,18 +4370,20 @@ static int check_helper_mem_access(struc - return check_mem_region_access(env, regno, reg->off, - access_size, reg->mem_size, - zero_size_allowed); -- case PTR_TO_RDONLY_BUF: -- if (meta && meta->raw_mode) -- return -EACCES; -- return check_buffer_access(env, reg, regno, reg->off, -- access_size, zero_size_allowed, -- "rdonly", -- &env->prog->aux->max_rdonly_access); -- case PTR_TO_RDWR_BUF: -+ case PTR_TO_BUF: -+ if (type_is_rdonly_mem(reg->type)) { -+ if (meta && meta->raw_mode) -+ return -EACCES; -+ -+ buf_info = "rdonly"; -+ max_access = &env->prog->aux->max_rdonly_access; -+ } else { -+ buf_info = "rdwr"; -+ max_access = &env->prog->aux->max_rdwr_access; -+ } - return check_buffer_access(env, reg, regno, reg->off, - access_size, zero_size_allowed, -- "rdwr", -- &env->prog->aux->max_rdwr_access); -+ buf_info, max_access); - case PTR_TO_STACK: - return check_stack_range_initialized( - env, -@@ -4570,8 +4586,8 @@ static const struct bpf_reg_types mem_ty - PTR_TO_PACKET_META, - PTR_TO_MAP_VALUE, - PTR_TO_MEM, -- PTR_TO_RDONLY_BUF, -- PTR_TO_RDWR_BUF, -+ PTR_TO_BUF, -+ PTR_TO_BUF | MEM_RDONLY, - }, - }; - ---- a/net/core/bpf_sk_storage.c -+++ b/net/core/bpf_sk_storage.c -@@ -867,7 +867,7 @@ static struct bpf_iter_reg bpf_sk_storag - { offsetof(struct bpf_iter__bpf_sk_storage_map, sk), - PTR_TO_BTF_ID_OR_NULL }, - { offsetof(struct bpf_iter__bpf_sk_storage_map, value), -- PTR_TO_RDWR_BUF | PTR_MAYBE_NULL }, -+ PTR_TO_BUF | PTR_MAYBE_NULL }, - }, - .seq_info = &iter_seq_info, - }; ---- a/net/core/sock_map.c -+++ b/net/core/sock_map.c -@@ -1657,7 +1657,7 @@ static struct bpf_iter_reg sock_map_iter - .ctx_arg_info_size = 2, - .ctx_arg_info = { - { offsetof(struct bpf_iter__sockmap, key), -- PTR_TO_RDONLY_BUF | PTR_MAYBE_NULL }, -+ PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY }, - { offsetof(struct bpf_iter__sockmap, sk), - PTR_TO_BTF_ID_OR_NULL }, - }, diff --git a/queue-5.10/bpf-make-per_cpu_ptr-return-rdonly-ptr_to_mem.patch b/queue-5.10/bpf-make-per_cpu_ptr-return-rdonly-ptr_to_mem.patch deleted file mode 100644 index df23df48ee..0000000000 --- a/queue-5.10/bpf-make-per_cpu_ptr-return-rdonly-ptr_to_mem.patch +++ /dev/null @@ -1,120 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:50 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:44:01 +0000 -Subject: bpf: Make per_cpu_ptr return rdonly PTR_TO_MEM. -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-7-puranjay@kernel.org> - -From: Hao Luo - -commit 34d3a78c681e8e7844b43d1a2f4671a04249c821 upstream. - -Tag the return type of {per, this}_cpu_ptr with RDONLY_MEM. The -returned value of this pair of helpers is kernel object, which -can not be updated by bpf programs. Previously these two helpers -return PTR_OT_MEM for kernel objects of scalar type, which allows -one to directly modify the memory. Now with RDONLY_MEM tagging, -the verifier will reject programs that write into RDONLY_MEM. - -Fixes: 63d9b80dcf2c ("bpf: Introducte bpf_this_cpu_ptr()") -Fixes: eaa6bcb71ef6 ("bpf: Introduce bpf_per_cpu_ptr()") -Fixes: 4976b718c355 ("bpf: Introduce pseudo_btf_id") -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-8-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - kernel/bpf/helpers.c | 4 ++-- - kernel/bpf/verifier.c | 30 ++++++++++++++++++++++++++---- - 2 files changed, 28 insertions(+), 6 deletions(-) - ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -653,7 +653,7 @@ BPF_CALL_2(bpf_per_cpu_ptr, const void * - const struct bpf_func_proto bpf_per_cpu_ptr_proto = { - .func = bpf_per_cpu_ptr, - .gpl_only = false, -- .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL, -+ .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL | MEM_RDONLY, - .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID, - .arg2_type = ARG_ANYTHING, - }; -@@ -666,7 +666,7 @@ BPF_CALL_1(bpf_this_cpu_ptr, const void - const struct bpf_func_proto bpf_this_cpu_ptr_proto = { - .func = bpf_this_cpu_ptr, - .gpl_only = false, -- .ret_type = RET_PTR_TO_MEM_OR_BTF_ID, -+ .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | MEM_RDONLY, - .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID, - }; - ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -4014,15 +4014,30 @@ static int check_mem_access(struct bpf_v - mark_reg_unknown(env, regs, value_regno); - } - } -- } else if (reg->type == PTR_TO_MEM) { -+ } else if (base_type(reg->type) == PTR_TO_MEM) { -+ bool rdonly_mem = type_is_rdonly_mem(reg->type); -+ -+ if (type_may_be_null(reg->type)) { -+ verbose(env, "R%d invalid mem access '%s'\n", regno, -+ reg_type_str(env, reg->type)); -+ return -EACCES; -+ } -+ -+ if (t == BPF_WRITE && rdonly_mem) { -+ verbose(env, "R%d cannot write into %s\n", -+ regno, reg_type_str(env, reg->type)); -+ return -EACCES; -+ } -+ - if (t == BPF_WRITE && value_regno >= 0 && - is_pointer_value(env, value_regno)) { - verbose(env, "R%d leaks addr into mem\n", value_regno); - return -EACCES; - } -+ - err = check_mem_region_access(env, regno, off, size, - reg->mem_size, false); -- if (!err && t == BPF_READ && value_regno >= 0) -+ if (!err && value_regno >= 0 && (t == BPF_READ || rdonly_mem)) - mark_reg_unknown(env, regs, value_regno); - } else if (reg->type == PTR_TO_CTX) { - enum bpf_reg_type reg_type = SCALAR_VALUE; -@@ -5730,6 +5745,13 @@ static int check_helper_call(struct bpf_ - regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag; - regs[BPF_REG_0].mem_size = tsize; - } else { -+ /* MEM_RDONLY may be carried from ret_flag, but it -+ * doesn't apply on PTR_TO_BTF_ID. Fold it, otherwise -+ * it will confuse the check of PTR_TO_BTF_ID in -+ * check_mem_access(). -+ */ -+ ret_flag &= ~MEM_RDONLY; -+ - regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag; - regs[BPF_REG_0].btf_id = meta.ret_btf_id; - } -@@ -8387,7 +8409,7 @@ static int check_ld_imm(struct bpf_verif - mark_reg_known_zero(env, regs, insn->dst_reg); - - dst_reg->type = aux->btf_var.reg_type; -- switch (dst_reg->type) { -+ switch (base_type(dst_reg->type)) { - case PTR_TO_MEM: - dst_reg->mem_size = aux->btf_var.mem_size; - break; -@@ -10401,7 +10423,7 @@ static int check_pseudo_btf_id(struct bp - tname, PTR_ERR(ret)); - return -EINVAL; - } -- aux->btf_var.reg_type = PTR_TO_MEM; -+ aux->btf_var.reg_type = PTR_TO_MEM | MEM_RDONLY; - aux->btf_var.mem_size = tsize; - } else { - aux->btf_var.reg_type = PTR_TO_BTF_ID; diff --git a/queue-5.10/bpf-replace-arg_xxx_or_null-with-arg_xxx-ptr_maybe_null.patch b/queue-5.10/bpf-replace-arg_xxx_or_null-with-arg_xxx-ptr_maybe_null.patch deleted file mode 100644 index 02f6553f91..0000000000 --- a/queue-5.10/bpf-replace-arg_xxx_or_null-with-arg_xxx-ptr_maybe_null.patch +++ /dev/null @@ -1,189 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:24 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:43:57 +0000 -Subject: bpf: Replace ARG_XXX_OR_NULL with ARG_XXX | PTR_MAYBE_NULL -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-3-puranjay@kernel.org> - -From: Hao Luo - -commit 48946bd6a5d695c50b34546864b79c1f910a33c1 upstream. - -We have introduced a new type to make bpf_arg composable, by -reserving high bits of bpf_arg to represent flags of a type. - -One of the flags is PTR_MAYBE_NULL which indicates a pointer -may be NULL. When applying this flag to an arg_type, it means -the arg can take NULL pointer. This patch switches the -qualified arg_types to use this flag. The arg_types changed -in this patch include: - -1. ARG_PTR_TO_MAP_VALUE_OR_NULL -2. ARG_PTR_TO_MEM_OR_NULL -3. ARG_PTR_TO_CTX_OR_NULL -4. ARG_PTR_TO_SOCKET_OR_NULL -5. ARG_PTR_TO_ALLOC_MEM_OR_NULL -6. ARG_PTR_TO_STACK_OR_NULL - -This patch does not eliminate the use of these arg_types, instead -it makes them an alias to the 'ARG_XXX | PTR_MAYBE_NULL'. - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-3-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 12 +++++++----- - kernel/bpf/verifier.c | 36 +++++++++++++----------------------- - 2 files changed, 20 insertions(+), 28 deletions(-) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -297,13 +297,11 @@ enum bpf_arg_type { - ARG_PTR_TO_MAP_KEY, /* pointer to stack used as map key */ - ARG_PTR_TO_MAP_VALUE, /* pointer to stack used as map value */ - ARG_PTR_TO_UNINIT_MAP_VALUE, /* pointer to valid memory used to store a map value */ -- ARG_PTR_TO_MAP_VALUE_OR_NULL, /* pointer to stack used as map value or NULL */ - - /* the following constraints used to prototype bpf_memcmp() and other - * functions that access data on eBPF program stack - */ - ARG_PTR_TO_MEM, /* pointer to valid memory (stack, packet, map value) */ -- ARG_PTR_TO_MEM_OR_NULL, /* pointer to valid memory or NULL */ - ARG_PTR_TO_UNINIT_MEM, /* pointer to memory does not need to be initialized, - * helper function must fill all bytes or clear - * them in error case. -@@ -313,22 +311,26 @@ enum bpf_arg_type { - ARG_CONST_SIZE_OR_ZERO, /* number of bytes accessed from memory or 0 */ - - ARG_PTR_TO_CTX, /* pointer to context */ -- ARG_PTR_TO_CTX_OR_NULL, /* pointer to context or NULL */ - ARG_ANYTHING, /* any (initialized) argument is ok */ - ARG_PTR_TO_SPIN_LOCK, /* pointer to bpf_spin_lock */ - ARG_PTR_TO_SOCK_COMMON, /* pointer to sock_common */ - ARG_PTR_TO_INT, /* pointer to int */ - ARG_PTR_TO_LONG, /* pointer to long */ - ARG_PTR_TO_SOCKET, /* pointer to bpf_sock (fullsock) */ -- ARG_PTR_TO_SOCKET_OR_NULL, /* pointer to bpf_sock (fullsock) or NULL */ - ARG_PTR_TO_BTF_ID, /* pointer to in-kernel struct */ - ARG_PTR_TO_ALLOC_MEM, /* pointer to dynamically allocated memory */ -- ARG_PTR_TO_ALLOC_MEM_OR_NULL, /* pointer to dynamically allocated memory or NULL */ - ARG_CONST_ALLOC_SIZE_OR_ZERO, /* number of allocated bytes requested */ - ARG_PTR_TO_BTF_ID_SOCK_COMMON, /* pointer to in-kernel sock_common or bpf-mirrored bpf_sock */ - ARG_PTR_TO_PERCPU_BTF_ID, /* pointer to in-kernel percpu type */ - __BPF_ARG_TYPE_MAX, - -+ /* Extended arg_types. */ -+ ARG_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MAP_VALUE, -+ ARG_PTR_TO_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_MEM, -+ ARG_PTR_TO_CTX_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_CTX, -+ ARG_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET, -+ ARG_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | ARG_PTR_TO_ALLOC_MEM, -+ - /* This must be the last entry. Its purpose is to ensure the enum is - * wide enough to hold the higher bits reserved for bpf_type_flag. - */ ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -437,13 +437,9 @@ static bool arg_type_may_be_refcounted(e - return type == ARG_PTR_TO_SOCK_COMMON; - } - --static bool arg_type_may_be_null(enum bpf_arg_type type) -+static bool type_may_be_null(u32 type) - { -- return type == ARG_PTR_TO_MAP_VALUE_OR_NULL || -- type == ARG_PTR_TO_MEM_OR_NULL || -- type == ARG_PTR_TO_CTX_OR_NULL || -- type == ARG_PTR_TO_SOCKET_OR_NULL || -- type == ARG_PTR_TO_ALLOC_MEM_OR_NULL; -+ return type & PTR_MAYBE_NULL; - } - - /* Determine whether the function releases some resources allocated by another -@@ -4486,9 +4482,8 @@ static int process_spin_lock(struct bpf_ - - static bool arg_type_is_mem_ptr(enum bpf_arg_type type) - { -- return type == ARG_PTR_TO_MEM || -- type == ARG_PTR_TO_MEM_OR_NULL || -- type == ARG_PTR_TO_UNINIT_MEM; -+ return base_type(type) == ARG_PTR_TO_MEM || -+ base_type(type) == ARG_PTR_TO_UNINIT_MEM; - } - - static bool arg_type_is_mem_size(enum bpf_arg_type type) -@@ -4615,26 +4610,21 @@ static const struct bpf_reg_types *compa - [ARG_PTR_TO_MAP_KEY] = &map_key_value_types, - [ARG_PTR_TO_MAP_VALUE] = &map_key_value_types, - [ARG_PTR_TO_UNINIT_MAP_VALUE] = &map_key_value_types, -- [ARG_PTR_TO_MAP_VALUE_OR_NULL] = &map_key_value_types, - [ARG_CONST_SIZE] = &scalar_types, - [ARG_CONST_SIZE_OR_ZERO] = &scalar_types, - [ARG_CONST_ALLOC_SIZE_OR_ZERO] = &scalar_types, - [ARG_CONST_MAP_PTR] = &const_map_ptr_types, - [ARG_PTR_TO_CTX] = &context_types, -- [ARG_PTR_TO_CTX_OR_NULL] = &context_types, - [ARG_PTR_TO_SOCK_COMMON] = &sock_types, - #ifdef CONFIG_NET - [ARG_PTR_TO_BTF_ID_SOCK_COMMON] = &btf_id_sock_common_types, - #endif - [ARG_PTR_TO_SOCKET] = &fullsock_types, -- [ARG_PTR_TO_SOCKET_OR_NULL] = &fullsock_types, - [ARG_PTR_TO_BTF_ID] = &btf_ptr_types, - [ARG_PTR_TO_SPIN_LOCK] = &spin_lock_types, - [ARG_PTR_TO_MEM] = &mem_types, -- [ARG_PTR_TO_MEM_OR_NULL] = &mem_types, - [ARG_PTR_TO_UNINIT_MEM] = &mem_types, - [ARG_PTR_TO_ALLOC_MEM] = &alloc_mem_types, -- [ARG_PTR_TO_ALLOC_MEM_OR_NULL] = &alloc_mem_types, - [ARG_PTR_TO_INT] = &int_ptr_types, - [ARG_PTR_TO_LONG] = &int_ptr_types, - [ARG_PTR_TO_PERCPU_BTF_ID] = &percpu_btf_ptr_types, -@@ -4649,7 +4639,7 @@ static int check_reg_type(struct bpf_ver - const struct bpf_reg_types *compatible; - int i, j; - -- compatible = compatible_reg_types[arg_type]; -+ compatible = compatible_reg_types[base_type(arg_type)]; - if (!compatible) { - verbose(env, "verifier internal error: unsupported arg type %d\n", arg_type); - return -EFAULT; -@@ -4730,15 +4720,14 @@ static int check_func_arg(struct bpf_ver - return -EACCES; - } - -- if (arg_type == ARG_PTR_TO_MAP_VALUE || -- arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE || -- arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL) { -+ if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE || -+ base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) { - err = resolve_map_arg_type(env, meta, &arg_type); - if (err) - return err; - } - -- if (register_is_null(reg) && arg_type_may_be_null(arg_type)) -+ if (register_is_null(reg) && type_may_be_null(arg_type)) - /* A NULL register has a SCALAR_VALUE type, so skip - * type checking. - */ -@@ -4785,10 +4774,11 @@ skip_type_check: - err = check_helper_mem_access(env, regno, - meta->map_ptr->key_size, false, - NULL); -- } else if (arg_type == ARG_PTR_TO_MAP_VALUE || -- (arg_type == ARG_PTR_TO_MAP_VALUE_OR_NULL && -- !register_is_null(reg)) || -- arg_type == ARG_PTR_TO_UNINIT_MAP_VALUE) { -+ } else if (base_type(arg_type) == ARG_PTR_TO_MAP_VALUE || -+ base_type(arg_type) == ARG_PTR_TO_UNINIT_MAP_VALUE) { -+ if (type_may_be_null(arg_type) && register_is_null(reg)) -+ return 0; -+ - /* bpf_map_xxx(..., map_ptr, ..., value) call: - * check [value, value + map->value_size) validity - */ diff --git a/queue-5.10/bpf-replace-ptr_to_xxx_or_null-with-ptr_to_xxx-ptr_maybe_null.patch b/queue-5.10/bpf-replace-ptr_to_xxx_or_null-with-ptr_to_xxx-ptr_maybe_null.patch deleted file mode 100644 index 4f016bd92b..0000000000 --- a/queue-5.10/bpf-replace-ptr_to_xxx_or_null-with-ptr_to_xxx-ptr_maybe_null.patch +++ /dev/null @@ -1,799 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:31 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:43:59 +0000 -Subject: bpf: Replace PTR_TO_XXX_OR_NULL with PTR_TO_XXX | PTR_MAYBE_NULL -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-5-puranjay@kernel.org> - -From: Hao Luo - -commit c25b2ae136039ffa820c26138ed4a5e5f3ab3841 upstream. - -We have introduced a new type to make bpf_reg composable, by -allocating bits in the type to represent flags. - -One of the flags is PTR_MAYBE_NULL which indicates a pointer -may be NULL. This patch switches the qualified reg_types to -use this flag. The reg_types changed in this patch include: - -1. PTR_TO_MAP_VALUE_OR_NULL -2. PTR_TO_SOCKET_OR_NULL -3. PTR_TO_SOCK_COMMON_OR_NULL -4. PTR_TO_TCP_SOCK_OR_NULL -5. PTR_TO_BTF_ID_OR_NULL -6. PTR_TO_MEM_OR_NULL -7. PTR_TO_RDONLY_BUF_OR_NULL -8. PTR_TO_RDWR_BUF_OR_NULL - -[puranjay: backport notes - There was a reg_type_may_be_null() in adjust_ptr_min_max_vals() in - 5.10.x, but didn't exist in the upstream commit. This backport - converted that reg_type_may_be_null() to type_may_be_null() as well.] - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/r/20211217003152.48334-5-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 15 +- - include/linux/bpf_verifier.h | 4 - kernel/bpf/btf.c | 7 - - kernel/bpf/map_iter.c | 4 - kernel/bpf/verifier.c | 294 +++++++++++++++++++------------------------ - net/core/bpf_sk_storage.c | 2 - net/core/sock_map.c | 2 - 7 files changed, 152 insertions(+), 176 deletions(-) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -426,18 +426,14 @@ enum bpf_reg_type { - PTR_TO_CTX, /* reg points to bpf_context */ - CONST_PTR_TO_MAP, /* reg points to struct bpf_map */ - PTR_TO_MAP_VALUE, /* reg points to map element value */ -- PTR_TO_MAP_VALUE_OR_NULL,/* points to map elem value or NULL */ - PTR_TO_STACK, /* reg == frame_pointer + offset */ - PTR_TO_PACKET_META, /* skb->data - meta_len */ - PTR_TO_PACKET, /* reg points to skb->data */ - PTR_TO_PACKET_END, /* skb->data + headlen */ - PTR_TO_FLOW_KEYS, /* reg points to bpf_flow_keys */ - PTR_TO_SOCKET, /* reg points to struct bpf_sock */ -- PTR_TO_SOCKET_OR_NULL, /* reg points to struct bpf_sock or NULL */ - PTR_TO_SOCK_COMMON, /* reg points to sock_common */ -- PTR_TO_SOCK_COMMON_OR_NULL, /* reg points to sock_common or NULL */ - PTR_TO_TCP_SOCK, /* reg points to struct tcp_sock */ -- PTR_TO_TCP_SOCK_OR_NULL, /* reg points to struct tcp_sock or NULL */ - PTR_TO_TP_BUFFER, /* reg points to a writable raw tp's buffer */ - PTR_TO_XDP_SOCK, /* reg points to struct xdp_sock */ - /* PTR_TO_BTF_ID points to a kernel struct that does not need -@@ -455,16 +451,19 @@ enum bpf_reg_type { - * been checked for null. Used primarily to inform the verifier - * an explicit null check is required for this struct. - */ -- PTR_TO_BTF_ID_OR_NULL, - PTR_TO_MEM, /* reg points to valid memory region */ -- PTR_TO_MEM_OR_NULL, /* reg points to valid memory region or NULL */ - PTR_TO_RDONLY_BUF, /* reg points to a readonly buffer */ -- PTR_TO_RDONLY_BUF_OR_NULL, /* reg points to a readonly buffer or NULL */ - PTR_TO_RDWR_BUF, /* reg points to a read/write buffer */ -- PTR_TO_RDWR_BUF_OR_NULL, /* reg points to a read/write buffer or NULL */ - PTR_TO_PERCPU_BTF_ID, /* reg points to a percpu kernel variable */ - __BPF_REG_TYPE_MAX, - -+ /* Extended reg_types. */ -+ PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | PTR_TO_MAP_VALUE, -+ PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCKET, -+ PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | PTR_TO_SOCK_COMMON, -+ PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | PTR_TO_TCP_SOCK, -+ PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | PTR_TO_BTF_ID, -+ - /* This must be the last entry. Its purpose is to ensure the enum is - * wide enough to hold the higher bits reserved for bpf_type_flag. - */ ---- a/include/linux/bpf_verifier.h -+++ b/include/linux/bpf_verifier.h -@@ -17,6 +17,8 @@ - * that converting umax_value to int cannot overflow. - */ - #define BPF_MAX_VAR_SIZ (1 << 29) -+/* size of type_str_buf in bpf_verifier. */ -+#define TYPE_STR_BUF_LEN 64 - - /* Liveness marks, used for registers and spilled-regs (in stack slots). - * Read marks propagate upwards until they find a write mark; they record that -@@ -462,6 +464,8 @@ struct bpf_verifier_env { - u32 peak_states; - /* longest register parentage chain walked for liveness marking */ - u32 longest_mark_read_walk; -+ /* buffer used in reg_type_str() to generate reg_type string */ -+ char type_str_buf[TYPE_STR_BUF_LEN]; - }; - - __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log, ---- a/kernel/bpf/btf.c -+++ b/kernel/bpf/btf.c -@@ -4535,10 +4535,13 @@ bool btf_ctx_access(int off, int size, e - /* check for PTR_TO_RDONLY_BUF_OR_NULL or PTR_TO_RDWR_BUF_OR_NULL */ - for (i = 0; i < prog->aux->ctx_arg_info_size; i++) { - const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i]; -+ u32 type, flag; - -+ type = base_type(ctx_arg_info->reg_type); -+ flag = type_flag(ctx_arg_info->reg_type); - if (ctx_arg_info->offset == off && -- (ctx_arg_info->reg_type == PTR_TO_RDONLY_BUF_OR_NULL || -- ctx_arg_info->reg_type == PTR_TO_RDWR_BUF_OR_NULL)) { -+ (type == PTR_TO_RDWR_BUF || type == PTR_TO_RDONLY_BUF) && -+ (flag & PTR_MAYBE_NULL)) { - info->reg_type = ctx_arg_info->reg_type; - return true; - } ---- a/kernel/bpf/map_iter.c -+++ b/kernel/bpf/map_iter.c -@@ -174,9 +174,9 @@ static const struct bpf_iter_reg bpf_map - .ctx_arg_info_size = 2, - .ctx_arg_info = { - { offsetof(struct bpf_iter__bpf_map_elem, key), -- PTR_TO_RDONLY_BUF_OR_NULL }, -+ PTR_TO_RDONLY_BUF | PTR_MAYBE_NULL }, - { offsetof(struct bpf_iter__bpf_map_elem, value), -- PTR_TO_RDWR_BUF_OR_NULL }, -+ PTR_TO_RDWR_BUF | PTR_MAYBE_NULL }, - }, - }; - ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -404,18 +404,6 @@ static bool reg_type_not_null(enum bpf_r - type == PTR_TO_SOCK_COMMON; - } - --static bool reg_type_may_be_null(enum bpf_reg_type type) --{ -- return type == PTR_TO_MAP_VALUE_OR_NULL || -- type == PTR_TO_SOCKET_OR_NULL || -- type == PTR_TO_SOCK_COMMON_OR_NULL || -- type == PTR_TO_TCP_SOCK_OR_NULL || -- type == PTR_TO_BTF_ID_OR_NULL || -- type == PTR_TO_MEM_OR_NULL || -- type == PTR_TO_RDONLY_BUF_OR_NULL || -- type == PTR_TO_RDWR_BUF_OR_NULL; --} -- - static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg) - { - return reg->type == PTR_TO_MAP_VALUE && -@@ -424,12 +412,9 @@ static bool reg_may_point_to_spin_lock(c - - static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type) - { -- return type == PTR_TO_SOCKET || -- type == PTR_TO_SOCKET_OR_NULL || -- type == PTR_TO_TCP_SOCK || -- type == PTR_TO_TCP_SOCK_OR_NULL || -- type == PTR_TO_MEM || -- type == PTR_TO_MEM_OR_NULL; -+ return base_type(type) == PTR_TO_SOCKET || -+ base_type(type) == PTR_TO_TCP_SOCK || -+ base_type(type) == PTR_TO_MEM; - } - - static bool arg_type_may_be_refcounted(enum bpf_arg_type type) -@@ -492,37 +477,50 @@ static bool is_ptr_cast_function(enum bp - func_id == BPF_FUNC_skc_to_tcp_request_sock; - } - --/* string representation of 'enum bpf_reg_type' */ --static const char * const reg_type_str[] = { -- [NOT_INIT] = "?", -- [SCALAR_VALUE] = "inv", -- [PTR_TO_CTX] = "ctx", -- [CONST_PTR_TO_MAP] = "map_ptr", -- [PTR_TO_MAP_VALUE] = "map_value", -- [PTR_TO_MAP_VALUE_OR_NULL] = "map_value_or_null", -- [PTR_TO_STACK] = "fp", -- [PTR_TO_PACKET] = "pkt", -- [PTR_TO_PACKET_META] = "pkt_meta", -- [PTR_TO_PACKET_END] = "pkt_end", -- [PTR_TO_FLOW_KEYS] = "flow_keys", -- [PTR_TO_SOCKET] = "sock", -- [PTR_TO_SOCKET_OR_NULL] = "sock_or_null", -- [PTR_TO_SOCK_COMMON] = "sock_common", -- [PTR_TO_SOCK_COMMON_OR_NULL] = "sock_common_or_null", -- [PTR_TO_TCP_SOCK] = "tcp_sock", -- [PTR_TO_TCP_SOCK_OR_NULL] = "tcp_sock_or_null", -- [PTR_TO_TP_BUFFER] = "tp_buffer", -- [PTR_TO_XDP_SOCK] = "xdp_sock", -- [PTR_TO_BTF_ID] = "ptr_", -- [PTR_TO_BTF_ID_OR_NULL] = "ptr_or_null_", -- [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", -- [PTR_TO_MEM] = "mem", -- [PTR_TO_MEM_OR_NULL] = "mem_or_null", -- [PTR_TO_RDONLY_BUF] = "rdonly_buf", -- [PTR_TO_RDONLY_BUF_OR_NULL] = "rdonly_buf_or_null", -- [PTR_TO_RDWR_BUF] = "rdwr_buf", -- [PTR_TO_RDWR_BUF_OR_NULL] = "rdwr_buf_or_null", --}; -+/* string representation of 'enum bpf_reg_type' -+ * -+ * Note that reg_type_str() can not appear more than once in a single verbose() -+ * statement. -+ */ -+static const char *reg_type_str(struct bpf_verifier_env *env, -+ enum bpf_reg_type type) -+{ -+ char postfix[16] = {0}; -+ static const char * const str[] = { -+ [NOT_INIT] = "?", -+ [SCALAR_VALUE] = "inv", -+ [PTR_TO_CTX] = "ctx", -+ [CONST_PTR_TO_MAP] = "map_ptr", -+ [PTR_TO_MAP_VALUE] = "map_value", -+ [PTR_TO_STACK] = "fp", -+ [PTR_TO_PACKET] = "pkt", -+ [PTR_TO_PACKET_META] = "pkt_meta", -+ [PTR_TO_PACKET_END] = "pkt_end", -+ [PTR_TO_FLOW_KEYS] = "flow_keys", -+ [PTR_TO_SOCKET] = "sock", -+ [PTR_TO_SOCK_COMMON] = "sock_common", -+ [PTR_TO_TCP_SOCK] = "tcp_sock", -+ [PTR_TO_TP_BUFFER] = "tp_buffer", -+ [PTR_TO_XDP_SOCK] = "xdp_sock", -+ [PTR_TO_BTF_ID] = "ptr_", -+ [PTR_TO_PERCPU_BTF_ID] = "percpu_ptr_", -+ [PTR_TO_MEM] = "mem", -+ [PTR_TO_RDONLY_BUF] = "rdonly_buf", -+ [PTR_TO_RDWR_BUF] = "rdwr_buf", -+ }; -+ -+ if (type & PTR_MAYBE_NULL) { -+ if (base_type(type) == PTR_TO_BTF_ID || -+ base_type(type) == PTR_TO_PERCPU_BTF_ID) -+ strncpy(postfix, "or_null_", 16); -+ else -+ strncpy(postfix, "_or_null", 16); -+ } -+ -+ snprintf(env->type_str_buf, TYPE_STR_BUF_LEN, "%s%s", -+ str[base_type(type)], postfix); -+ return env->type_str_buf; -+} - - static char slot_type_char[] = { - [STACK_INVALID] = '?', -@@ -588,7 +586,7 @@ static void print_verifier_state(struct - continue; - verbose(env, " R%d", i); - print_liveness(env, reg->live); -- verbose(env, "=%s", reg_type_str[t]); -+ verbose(env, "=%s", reg_type_str(env, t)); - if (t == SCALAR_VALUE && reg->precise) - verbose(env, "P"); - if ((t == SCALAR_VALUE || t == PTR_TO_STACK) && -@@ -596,9 +594,8 @@ static void print_verifier_state(struct - /* reg->off should be 0 for SCALAR_VALUE */ - verbose(env, "%lld", reg->var_off.value + reg->off); - } else { -- if (t == PTR_TO_BTF_ID || -- t == PTR_TO_BTF_ID_OR_NULL || -- t == PTR_TO_PERCPU_BTF_ID) -+ if (base_type(t) == PTR_TO_BTF_ID || -+ base_type(t) == PTR_TO_PERCPU_BTF_ID) - verbose(env, "%s", kernel_type_name(reg->btf_id)); - verbose(env, "(id=%d", reg->id); - if (reg_type_may_be_refcounted_or_null(t)) -@@ -607,9 +604,8 @@ static void print_verifier_state(struct - verbose(env, ",off=%d", reg->off); - if (type_is_pkt_pointer(t)) - verbose(env, ",r=%d", reg->range); -- else if (t == CONST_PTR_TO_MAP || -- t == PTR_TO_MAP_VALUE || -- t == PTR_TO_MAP_VALUE_OR_NULL) -+ else if (base_type(t) == CONST_PTR_TO_MAP || -+ base_type(t) == PTR_TO_MAP_VALUE) - verbose(env, ",ks=%d,vs=%d", - reg->map_ptr->key_size, - reg->map_ptr->value_size); -@@ -679,7 +675,7 @@ static void print_verifier_state(struct - if (is_spilled_reg(&state->stack[i])) { - reg = &state->stack[i].spilled_ptr; - t = reg->type; -- verbose(env, "=%s", reg_type_str[t]); -+ verbose(env, "=%s", reg_type_str(env, t)); - if (t == SCALAR_VALUE && reg->precise) - verbose(env, "P"); - if (t == SCALAR_VALUE && tnum_is_const(reg->var_off)) -@@ -1577,7 +1573,7 @@ static int mark_reg_read(struct bpf_veri - break; - if (parent->live & REG_LIVE_DONE) { - verbose(env, "verifier BUG type %s var_off %lld off %d\n", -- reg_type_str[parent->type], -+ reg_type_str(env, parent->type), - parent->var_off.value, parent->off); - return -EFAULT; - } -@@ -2366,9 +2362,8 @@ static int mark_chain_precision_stack_fr - - static bool is_spillable_regtype(enum bpf_reg_type type) - { -- switch (type) { -+ switch (base_type(type)) { - case PTR_TO_MAP_VALUE: -- case PTR_TO_MAP_VALUE_OR_NULL: - case PTR_TO_STACK: - case PTR_TO_CTX: - case PTR_TO_PACKET: -@@ -2377,21 +2372,14 @@ static bool is_spillable_regtype(enum bp - case PTR_TO_FLOW_KEYS: - case CONST_PTR_TO_MAP: - case PTR_TO_SOCKET: -- case PTR_TO_SOCKET_OR_NULL: - case PTR_TO_SOCK_COMMON: -- case PTR_TO_SOCK_COMMON_OR_NULL: - case PTR_TO_TCP_SOCK: -- case PTR_TO_TCP_SOCK_OR_NULL: - case PTR_TO_XDP_SOCK: - case PTR_TO_BTF_ID: -- case PTR_TO_BTF_ID_OR_NULL: - case PTR_TO_RDONLY_BUF: -- case PTR_TO_RDONLY_BUF_OR_NULL: - case PTR_TO_RDWR_BUF: -- case PTR_TO_RDWR_BUF_OR_NULL: - case PTR_TO_PERCPU_BTF_ID: - case PTR_TO_MEM: -- case PTR_TO_MEM_OR_NULL: - return true; - default: - return false; -@@ -3252,7 +3240,7 @@ static int check_ctx_access(struct bpf_v - */ - *reg_type = info.reg_type; - -- if (*reg_type == PTR_TO_BTF_ID || *reg_type == PTR_TO_BTF_ID_OR_NULL) -+ if (base_type(*reg_type) == PTR_TO_BTF_ID) - *btf_id = info.btf_id; - else - env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size; -@@ -3318,7 +3306,7 @@ static int check_sock_access(struct bpf_ - } - - verbose(env, "R%d invalid %s access off=%d size=%d\n", -- regno, reg_type_str[reg->type], off, size); -+ regno, reg_type_str(env, reg->type), off, size); - - return -EACCES; - } -@@ -4057,7 +4045,7 @@ static int check_mem_access(struct bpf_v - } else { - mark_reg_known_zero(env, regs, - value_regno); -- if (reg_type_may_be_null(reg_type)) -+ if (type_may_be_null(reg_type)) - regs[value_regno].id = ++env->id_gen; - /* A load of ctx field could have different - * actual load size with the one encoded in the -@@ -4065,8 +4053,7 @@ static int check_mem_access(struct bpf_v - * a sub-register. - */ - regs[value_regno].subreg_def = DEF_NOT_SUBREG; -- if (reg_type == PTR_TO_BTF_ID || -- reg_type == PTR_TO_BTF_ID_OR_NULL) -+ if (base_type(reg_type) == PTR_TO_BTF_ID) - regs[value_regno].btf_id = btf_id; - } - regs[value_regno].type = reg_type; -@@ -4117,7 +4104,7 @@ static int check_mem_access(struct bpf_v - } else if (type_is_sk_pointer(reg->type)) { - if (t == BPF_WRITE) { - verbose(env, "R%d cannot write into %s\n", -- regno, reg_type_str[reg->type]); -+ regno, reg_type_str(env, reg->type)); - return -EACCES; - } - err = check_sock_access(env, insn_idx, regno, off, size, t); -@@ -4136,7 +4123,7 @@ static int check_mem_access(struct bpf_v - } else if (reg->type == PTR_TO_RDONLY_BUF) { - if (t == BPF_WRITE) { - verbose(env, "R%d cannot write into %s\n", -- regno, reg_type_str[reg->type]); -+ regno, reg_type_str(env, reg->type)); - return -EACCES; - } - err = check_buffer_access(env, reg, regno, off, size, false, -@@ -4152,7 +4139,7 @@ static int check_mem_access(struct bpf_v - mark_reg_unknown(env, regs, value_regno); - } else { - verbose(env, "R%d invalid mem access '%s'\n", regno, -- reg_type_str[reg->type]); -+ reg_type_str(env, reg->type)); - return -EACCES; - } - -@@ -4195,7 +4182,7 @@ static int check_xadd(struct bpf_verifie - is_sk_reg(env, insn->dst_reg)) { - verbose(env, "BPF_XADD stores into R%d %s is not allowed\n", - insn->dst_reg, -- reg_type_str[reg_state(env, insn->dst_reg)->type]); -+ reg_type_str(env, reg_state(env, insn->dst_reg)->type)); - return -EACCES; - } - -@@ -4392,9 +4379,9 @@ static int check_helper_mem_access(struc - register_is_null(reg)) - return 0; - -- verbose(env, "R%d type=%s expected=%s\n", regno, -- reg_type_str[reg->type], -- reg_type_str[PTR_TO_STACK]); -+ verbose(env, "R%d type=%s ", regno, -+ reg_type_str(env, reg->type)); -+ verbose(env, "expected=%s\n", reg_type_str(env, PTR_TO_STACK)); - return -EACCES; - } - } -@@ -4654,10 +4641,10 @@ static int check_reg_type(struct bpf_ver - goto found; - } - -- verbose(env, "R%d type=%s expected=", regno, reg_type_str[type]); -+ verbose(env, "R%d type=%s expected=", regno, reg_type_str(env, type)); - for (j = 0; j + 1 < i; j++) -- verbose(env, "%s, ", reg_type_str[compatible->types[j]]); -- verbose(env, "%s\n", reg_type_str[compatible->types[j]]); -+ verbose(env, "%s, ", reg_type_str(env, compatible->types[j])); -+ verbose(env, "%s\n", reg_type_str(env, compatible->types[j])); - return -EACCES; - - found: -@@ -5556,6 +5543,7 @@ static int check_helper_call(struct bpf_ - { - const struct bpf_func_proto *fn = NULL; - enum bpf_return_type ret_type; -+ enum bpf_type_flag ret_flag; - struct bpf_reg_state *regs; - struct bpf_call_arg_meta meta; - bool changes_data; -@@ -5668,6 +5656,7 @@ static int check_helper_call(struct bpf_ - - /* update return register (already marked as written above) */ - ret_type = fn->ret_type; -+ ret_flag = type_flag(fn->ret_type); - if (ret_type == RET_INTEGER) { - /* sets type to SCALAR_VALUE */ - mark_reg_unknown(env, regs, BPF_REG_0); -@@ -5686,25 +5675,23 @@ static int check_helper_call(struct bpf_ - return -EINVAL; - } - regs[BPF_REG_0].map_ptr = meta.map_ptr; -- if (type_may_be_null(ret_type)) { -- regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; -- } else { -- regs[BPF_REG_0].type = PTR_TO_MAP_VALUE; -- if (map_value_has_spin_lock(meta.map_ptr)) -- regs[BPF_REG_0].id = ++env->id_gen; -+ regs[BPF_REG_0].type = PTR_TO_MAP_VALUE | ret_flag; -+ if (!type_may_be_null(ret_type) && -+ map_value_has_spin_lock(meta.map_ptr)) { -+ regs[BPF_REG_0].id = ++env->id_gen; - } - } else if (base_type(ret_type) == RET_PTR_TO_SOCKET) { - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = PTR_TO_SOCKET_OR_NULL; -+ regs[BPF_REG_0].type = PTR_TO_SOCKET | ret_flag; - } else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) { - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON_OR_NULL; -+ regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON | ret_flag; - } else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) { - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = PTR_TO_TCP_SOCK_OR_NULL; -+ regs[BPF_REG_0].type = PTR_TO_TCP_SOCK | ret_flag; - } else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) { - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; -+ regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag; - regs[BPF_REG_0].mem_size = meta.mem_size; - } else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) { - const struct btf_type *t; -@@ -5724,23 +5711,17 @@ static int check_helper_call(struct bpf_ - tname, PTR_ERR(ret)); - return -EINVAL; - } -- regs[BPF_REG_0].type = -- (ret_type & PTR_MAYBE_NULL) ? -- PTR_TO_MEM_OR_NULL : PTR_TO_MEM; -+ regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag; - regs[BPF_REG_0].mem_size = tsize; - } else { -- regs[BPF_REG_0].type = -- (ret_type & PTR_MAYBE_NULL) ? -- PTR_TO_BTF_ID_OR_NULL : PTR_TO_BTF_ID; -+ regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag; - regs[BPF_REG_0].btf_id = meta.ret_btf_id; - } - } else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) { - int ret_btf_id; - - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = (ret_type & PTR_MAYBE_NULL) ? -- PTR_TO_BTF_ID_OR_NULL : -- PTR_TO_BTF_ID; -+ regs[BPF_REG_0].type = PTR_TO_BTF_ID | ret_flag; - ret_btf_id = *fn->ret_btf_id; - if (ret_btf_id == 0) { - verbose(env, "invalid return type %u of func %s#%d\n", -@@ -5755,7 +5736,7 @@ static int check_helper_call(struct bpf_ - return -EINVAL; - } - -- if (reg_type_may_be_null(regs[BPF_REG_0].type)) -+ if (type_may_be_null(regs[BPF_REG_0].type)) - regs[BPF_REG_0].id = ++env->id_gen; - - if (is_ptr_cast_function(func_id)) { -@@ -5856,25 +5837,25 @@ static bool check_reg_sane_offset(struct - - if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) { - verbose(env, "math between %s pointer and %lld is not allowed\n", -- reg_type_str[type], val); -+ reg_type_str(env, type), val); - return false; - } - - if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) { - verbose(env, "%s pointer offset %d is not allowed\n", -- reg_type_str[type], reg->off); -+ reg_type_str(env, type), reg->off); - return false; - } - - if (smin == S64_MIN) { - verbose(env, "math between %s pointer and register with unbounded min value is not allowed\n", -- reg_type_str[type]); -+ reg_type_str(env, type)); - return false; - } - - if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) { - verbose(env, "value %lld makes %s pointer be out of bounds\n", -- smin, reg_type_str[type]); -+ smin, reg_type_str(env, type)); - return false; - } - -@@ -6251,11 +6232,13 @@ static int adjust_ptr_min_max_vals(struc - return -EACCES; - } - -- switch (ptr_reg->type) { -- case PTR_TO_MAP_VALUE_OR_NULL: -+ if (ptr_reg->type & PTR_MAYBE_NULL) { - verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n", -- dst, reg_type_str[ptr_reg->type]); -+ dst, reg_type_str(env, ptr_reg->type)); - return -EACCES; -+ } -+ -+ switch (base_type(ptr_reg->type)) { - case CONST_PTR_TO_MAP: - /* smin_val represents the known value */ - if (known && smin_val == 0 && opcode == BPF_ADD) -@@ -6268,10 +6251,10 @@ static int adjust_ptr_min_max_vals(struc - case PTR_TO_XDP_SOCK: - reject: - verbose(env, "R%d pointer arithmetic on %s prohibited\n", -- dst, reg_type_str[ptr_reg->type]); -+ dst, reg_type_str(env, ptr_reg->type)); - return -EACCES; - default: -- if (reg_type_may_be_null(ptr_reg->type)) -+ if (type_may_be_null(ptr_reg->type)) - goto reject; - break; - } -@@ -7964,7 +7947,7 @@ static void mark_ptr_or_null_reg(struct - struct bpf_reg_state *reg, u32 id, - bool is_null) - { -- if (reg_type_may_be_null(reg->type) && reg->id == id && -+ if (type_may_be_null(reg->type) && reg->id == id && - !WARN_ON_ONCE(!reg->id)) { - if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || - !tnum_equals_const(reg->var_off, 0) || -@@ -7978,7 +7961,17 @@ static void mark_ptr_or_null_reg(struct - } - if (is_null) { - reg->type = SCALAR_VALUE; -- } else if (reg->type == PTR_TO_MAP_VALUE_OR_NULL) { -+ /* We don't need id and ref_obj_id from this point -+ * onwards anymore, thus we should better reset it, -+ * so that state pruning has chances to take effect. -+ */ -+ reg->id = 0; -+ reg->ref_obj_id = 0; -+ -+ return; -+ } -+ -+ if (base_type(reg->type) == PTR_TO_MAP_VALUE) { - const struct bpf_map *map = reg->map_ptr; - - if (map->inner_map_meta) { -@@ -7992,29 +7985,11 @@ static void mark_ptr_or_null_reg(struct - } else { - reg->type = PTR_TO_MAP_VALUE; - } -- } else if (reg->type == PTR_TO_SOCKET_OR_NULL) { -- reg->type = PTR_TO_SOCKET; -- } else if (reg->type == PTR_TO_SOCK_COMMON_OR_NULL) { -- reg->type = PTR_TO_SOCK_COMMON; -- } else if (reg->type == PTR_TO_TCP_SOCK_OR_NULL) { -- reg->type = PTR_TO_TCP_SOCK; -- } else if (reg->type == PTR_TO_BTF_ID_OR_NULL) { -- reg->type = PTR_TO_BTF_ID; -- } else if (reg->type == PTR_TO_MEM_OR_NULL) { -- reg->type = PTR_TO_MEM; -- } else if (reg->type == PTR_TO_RDONLY_BUF_OR_NULL) { -- reg->type = PTR_TO_RDONLY_BUF; -- } else if (reg->type == PTR_TO_RDWR_BUF_OR_NULL) { -- reg->type = PTR_TO_RDWR_BUF; -+ } else { -+ reg->type &= ~PTR_MAYBE_NULL; - } -- if (is_null) { -- /* We don't need id and ref_obj_id from this point -- * onwards anymore, thus we should better reset it, -- * so that state pruning has chances to take effect. -- */ -- reg->id = 0; -- reg->ref_obj_id = 0; -- } else if (!reg_may_point_to_spin_lock(reg)) { -+ -+ if (!reg_may_point_to_spin_lock(reg)) { - /* For not-NULL ptr, reg->ref_obj_id will be reset - * in release_reference(). - * -@@ -8341,7 +8316,7 @@ static int check_cond_jmp_op(struct bpf_ - */ - if (!is_jmp32 && BPF_SRC(insn->code) == BPF_K && - insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) && -- reg_type_may_be_null(dst_reg->type)) { -+ type_may_be_null(dst_reg->type)) { - /* Mark all identical registers in each branch as either - * safe or unknown depending R == 0 or R != 0 conditional. - */ -@@ -8570,7 +8545,7 @@ static int check_return_code(struct bpf_ - if (is_subprog) { - if (reg->type != SCALAR_VALUE) { - verbose(env, "At subprogram exit the register R0 is not a scalar value (%s)\n", -- reg_type_str[reg->type]); -+ reg_type_str(env, reg->type)); - return -EINVAL; - } - return 0; -@@ -8631,7 +8606,7 @@ static int check_return_code(struct bpf_ - - if (reg->type != SCALAR_VALUE) { - verbose(env, "At program exit the register R0 is not a known value (%s)\n", -- reg_type_str[reg->type]); -+ reg_type_str(env, reg->type)); - return -EINVAL; - } - -@@ -9379,7 +9354,7 @@ static bool regsafe(struct bpf_verifier_ - return true; - if (rcur->type == NOT_INIT) - return false; -- switch (rold->type) { -+ switch (base_type(rold->type)) { - case SCALAR_VALUE: - if (env->explore_alu_limits) - return false; -@@ -9400,6 +9375,22 @@ static bool regsafe(struct bpf_verifier_ - return false; - } - case PTR_TO_MAP_VALUE: -+ /* a PTR_TO_MAP_VALUE could be safe to use as a -+ * PTR_TO_MAP_VALUE_OR_NULL into the same map. -+ * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL- -+ * checked, doing so could have affected others with the same -+ * id, and we can't check for that because we lost the id when -+ * we converted to a PTR_TO_MAP_VALUE. -+ */ -+ if (type_may_be_null(rold->type)) { -+ if (!type_may_be_null(rcur->type)) -+ return false; -+ if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id))) -+ return false; -+ /* Check our ids match any regs they're supposed to */ -+ return check_ids(rold->id, rcur->id, idmap); -+ } -+ - /* If the new min/max/var_off satisfy the old ones and - * everything else matches, we are OK. - * 'id' is not compared, since it's only used for maps with -@@ -9411,20 +9402,6 @@ static bool regsafe(struct bpf_verifier_ - return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 && - range_within(rold, rcur) && - tnum_in(rold->var_off, rcur->var_off); -- case PTR_TO_MAP_VALUE_OR_NULL: -- /* a PTR_TO_MAP_VALUE could be safe to use as a -- * PTR_TO_MAP_VALUE_OR_NULL into the same map. -- * However, if the old PTR_TO_MAP_VALUE_OR_NULL then got NULL- -- * checked, doing so could have affected others with the same -- * id, and we can't check for that because we lost the id when -- * we converted to a PTR_TO_MAP_VALUE. -- */ -- if (rcur->type != PTR_TO_MAP_VALUE_OR_NULL) -- return false; -- if (memcmp(rold, rcur, offsetof(struct bpf_reg_state, id))) -- return false; -- /* Check our ids match any regs they're supposed to */ -- return check_ids(rold->id, rcur->id, idmap); - case PTR_TO_PACKET_META: - case PTR_TO_PACKET: - if (rcur->type != rold->type) -@@ -9453,11 +9430,8 @@ static bool regsafe(struct bpf_verifier_ - case PTR_TO_PACKET_END: - case PTR_TO_FLOW_KEYS: - case PTR_TO_SOCKET: -- case PTR_TO_SOCKET_OR_NULL: - case PTR_TO_SOCK_COMMON: -- case PTR_TO_SOCK_COMMON_OR_NULL: - case PTR_TO_TCP_SOCK: -- case PTR_TO_TCP_SOCK_OR_NULL: - case PTR_TO_XDP_SOCK: - /* Only valid matches are exact, which memcmp() above - * would have accepted -@@ -9979,17 +9953,13 @@ next: - /* Return true if it's OK to have the same insn return a different type. */ - static bool reg_type_mismatch_ok(enum bpf_reg_type type) - { -- switch (type) { -+ switch (base_type(type)) { - case PTR_TO_CTX: - case PTR_TO_SOCKET: -- case PTR_TO_SOCKET_OR_NULL: - case PTR_TO_SOCK_COMMON: -- case PTR_TO_SOCK_COMMON_OR_NULL: - case PTR_TO_TCP_SOCK: -- case PTR_TO_TCP_SOCK_OR_NULL: - case PTR_TO_XDP_SOCK: - case PTR_TO_BTF_ID: -- case PTR_TO_BTF_ID_OR_NULL: - return false; - default: - return true; -@@ -10207,7 +10177,7 @@ static int do_check(struct bpf_verifier_ - if (is_ctx_reg(env, insn->dst_reg)) { - verbose(env, "BPF_ST stores into R%d %s is not allowed\n", - insn->dst_reg, -- reg_type_str[reg_state(env, insn->dst_reg)->type]); -+ reg_type_str(env, reg_state(env, insn->dst_reg)->type)); - return -EACCES; - } - ---- a/net/core/bpf_sk_storage.c -+++ b/net/core/bpf_sk_storage.c -@@ -867,7 +867,7 @@ static struct bpf_iter_reg bpf_sk_storag - { offsetof(struct bpf_iter__bpf_sk_storage_map, sk), - PTR_TO_BTF_ID_OR_NULL }, - { offsetof(struct bpf_iter__bpf_sk_storage_map, value), -- PTR_TO_RDWR_BUF_OR_NULL }, -+ PTR_TO_RDWR_BUF | PTR_MAYBE_NULL }, - }, - .seq_info = &iter_seq_info, - }; ---- a/net/core/sock_map.c -+++ b/net/core/sock_map.c -@@ -1657,7 +1657,7 @@ static struct bpf_iter_reg sock_map_iter - .ctx_arg_info_size = 2, - .ctx_arg_info = { - { offsetof(struct bpf_iter__sockmap, key), -- PTR_TO_RDONLY_BUF_OR_NULL }, -+ PTR_TO_RDONLY_BUF | PTR_MAYBE_NULL }, - { offsetof(struct bpf_iter__sockmap, sk), - PTR_TO_BTF_ID_OR_NULL }, - }, diff --git a/queue-5.10/bpf-replace-ret_xxx_or_null-with-ret_xxx-ptr_maybe_null.patch b/queue-5.10/bpf-replace-ret_xxx_or_null-with-ret_xxx-ptr_maybe_null.patch deleted file mode 100644 index 75c461e286..0000000000 --- a/queue-5.10/bpf-replace-ret_xxx_or_null-with-ret_xxx-ptr_maybe_null.patch +++ /dev/null @@ -1,196 +0,0 @@ -From puranjay@kernel.org Tue Jun 10 16:45:37 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:43:58 +0000 -Subject: bpf: Replace RET_XXX_OR_NULL with RET_XXX | PTR_MAYBE_NULL -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-4-puranjay@kernel.org> - -From: Hao Luo - -commit 3c4807322660d4290ac9062c034aed6b87243861 upstream. - -We have introduced a new type to make bpf_ret composable, by -reserving high bits to represent flags. - -One of the flag is PTR_MAYBE_NULL, which indicates a pointer -may be NULL. When applying this flag to ret_types, it means -the returned value could be a NULL pointer. This patch -switches the qualified arg_types to use this flag. -The ret_types changed in this patch include: - -1. RET_PTR_TO_MAP_VALUE_OR_NULL -2. RET_PTR_TO_SOCKET_OR_NULL -3. RET_PTR_TO_TCP_SOCK_OR_NULL -4. RET_PTR_TO_SOCK_COMMON_OR_NULL -5. RET_PTR_TO_ALLOC_MEM_OR_NULL -6. RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL -7. RET_PTR_TO_BTF_ID_OR_NULL - -This patch doesn't eliminate the use of these names, instead -it makes them aliases to 'RET_PTR_TO_XXX | PTR_MAYBE_NULL'. - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-4-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - include/linux/bpf.h | 20 +++++++++++++------- - kernel/bpf/helpers.c | 2 +- - kernel/bpf/verifier.c | 49 ++++++++++++++++++++++++++----------------------- - 3 files changed, 40 insertions(+), 31 deletions(-) - ---- a/include/linux/bpf.h -+++ b/include/linux/bpf.h -@@ -343,16 +343,22 @@ enum bpf_return_type { - RET_INTEGER, /* function returns integer */ - RET_VOID, /* function doesn't return anything */ - RET_PTR_TO_MAP_VALUE, /* returns a pointer to map elem value */ -- RET_PTR_TO_MAP_VALUE_OR_NULL, /* returns a pointer to map elem value or NULL */ -- RET_PTR_TO_SOCKET_OR_NULL, /* returns a pointer to a socket or NULL */ -- RET_PTR_TO_TCP_SOCK_OR_NULL, /* returns a pointer to a tcp_sock or NULL */ -- RET_PTR_TO_SOCK_COMMON_OR_NULL, /* returns a pointer to a sock_common or NULL */ -- RET_PTR_TO_ALLOC_MEM_OR_NULL, /* returns a pointer to dynamically allocated memory or NULL */ -- RET_PTR_TO_BTF_ID_OR_NULL, /* returns a pointer to a btf_id or NULL */ -- RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, /* returns a pointer to a valid memory or a btf_id or NULL */ -+ RET_PTR_TO_SOCKET, /* returns a pointer to a socket */ -+ RET_PTR_TO_TCP_SOCK, /* returns a pointer to a tcp_sock */ -+ RET_PTR_TO_SOCK_COMMON, /* returns a pointer to a sock_common */ -+ RET_PTR_TO_ALLOC_MEM, /* returns a pointer to dynamically allocated memory */ - RET_PTR_TO_MEM_OR_BTF_ID, /* returns a pointer to a valid memory or a btf_id */ -+ RET_PTR_TO_BTF_ID, /* returns a pointer to a btf_id */ - __BPF_RET_TYPE_MAX, - -+ /* Extended ret_types. */ -+ RET_PTR_TO_MAP_VALUE_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_MAP_VALUE, -+ RET_PTR_TO_SOCKET_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCKET, -+ RET_PTR_TO_TCP_SOCK_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_TCP_SOCK, -+ RET_PTR_TO_SOCK_COMMON_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_SOCK_COMMON, -+ RET_PTR_TO_ALLOC_MEM_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_ALLOC_MEM, -+ RET_PTR_TO_BTF_ID_OR_NULL = PTR_MAYBE_NULL | RET_PTR_TO_BTF_ID, -+ - /* This must be the last entry. Its purpose is to ensure the enum is - * wide enough to hold the higher bits reserved for bpf_type_flag. - */ ---- a/kernel/bpf/helpers.c -+++ b/kernel/bpf/helpers.c -@@ -653,7 +653,7 @@ BPF_CALL_2(bpf_per_cpu_ptr, const void * - const struct bpf_func_proto bpf_per_cpu_ptr_proto = { - .func = bpf_per_cpu_ptr, - .gpl_only = false, -- .ret_type = RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL, -+ .ret_type = RET_PTR_TO_MEM_OR_BTF_ID | PTR_MAYBE_NULL, - .arg1_type = ARG_PTR_TO_PERCPU_BTF_ID, - .arg2_type = ARG_ANYTHING, - }; ---- a/kernel/bpf/verifier.c -+++ b/kernel/bpf/verifier.c -@@ -5555,6 +5555,7 @@ static int check_reference_leak(struct b - static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn_idx) - { - const struct bpf_func_proto *fn = NULL; -+ enum bpf_return_type ret_type; - struct bpf_reg_state *regs; - struct bpf_call_arg_meta meta; - bool changes_data; -@@ -5666,13 +5667,13 @@ static int check_helper_call(struct bpf_ - regs[BPF_REG_0].subreg_def = DEF_NOT_SUBREG; - - /* update return register (already marked as written above) */ -- if (fn->ret_type == RET_INTEGER) { -+ ret_type = fn->ret_type; -+ if (ret_type == RET_INTEGER) { - /* sets type to SCALAR_VALUE */ - mark_reg_unknown(env, regs, BPF_REG_0); -- } else if (fn->ret_type == RET_VOID) { -+ } else if (ret_type == RET_VOID) { - regs[BPF_REG_0].type = NOT_INIT; -- } else if (fn->ret_type == RET_PTR_TO_MAP_VALUE_OR_NULL || -- fn->ret_type == RET_PTR_TO_MAP_VALUE) { -+ } else if (base_type(ret_type) == RET_PTR_TO_MAP_VALUE) { - /* There is no offset yet applied, variable or fixed */ - mark_reg_known_zero(env, regs, BPF_REG_0); - /* remember map_ptr, so that check_map_access() -@@ -5685,28 +5686,27 @@ static int check_helper_call(struct bpf_ - return -EINVAL; - } - regs[BPF_REG_0].map_ptr = meta.map_ptr; -- if (fn->ret_type == RET_PTR_TO_MAP_VALUE) { -+ if (type_may_be_null(ret_type)) { -+ regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; -+ } else { - regs[BPF_REG_0].type = PTR_TO_MAP_VALUE; - if (map_value_has_spin_lock(meta.map_ptr)) - regs[BPF_REG_0].id = ++env->id_gen; -- } else { -- regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; - } -- } else if (fn->ret_type == RET_PTR_TO_SOCKET_OR_NULL) { -+ } else if (base_type(ret_type) == RET_PTR_TO_SOCKET) { - mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_SOCKET_OR_NULL; -- } else if (fn->ret_type == RET_PTR_TO_SOCK_COMMON_OR_NULL) { -+ } else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) { - mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON_OR_NULL; -- } else if (fn->ret_type == RET_PTR_TO_TCP_SOCK_OR_NULL) { -+ } else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) { - mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_TCP_SOCK_OR_NULL; -- } else if (fn->ret_type == RET_PTR_TO_ALLOC_MEM_OR_NULL) { -+ } else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) { - mark_reg_known_zero(env, regs, BPF_REG_0); - regs[BPF_REG_0].type = PTR_TO_MEM_OR_NULL; - regs[BPF_REG_0].mem_size = meta.mem_size; -- } else if (fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID_OR_NULL || -- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID) { -+ } else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) { - const struct btf_type *t; - - mark_reg_known_zero(env, regs, BPF_REG_0); -@@ -5725,30 +5725,33 @@ static int check_helper_call(struct bpf_ - return -EINVAL; - } - regs[BPF_REG_0].type = -- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ? -- PTR_TO_MEM : PTR_TO_MEM_OR_NULL; -+ (ret_type & PTR_MAYBE_NULL) ? -+ PTR_TO_MEM_OR_NULL : PTR_TO_MEM; - regs[BPF_REG_0].mem_size = tsize; - } else { - regs[BPF_REG_0].type = -- fn->ret_type == RET_PTR_TO_MEM_OR_BTF_ID ? -- PTR_TO_BTF_ID : PTR_TO_BTF_ID_OR_NULL; -+ (ret_type & PTR_MAYBE_NULL) ? -+ PTR_TO_BTF_ID_OR_NULL : PTR_TO_BTF_ID; - regs[BPF_REG_0].btf_id = meta.ret_btf_id; - } -- } else if (fn->ret_type == RET_PTR_TO_BTF_ID_OR_NULL) { -+ } else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) { - int ret_btf_id; - - mark_reg_known_zero(env, regs, BPF_REG_0); -- regs[BPF_REG_0].type = PTR_TO_BTF_ID_OR_NULL; -+ regs[BPF_REG_0].type = (ret_type & PTR_MAYBE_NULL) ? -+ PTR_TO_BTF_ID_OR_NULL : -+ PTR_TO_BTF_ID; - ret_btf_id = *fn->ret_btf_id; - if (ret_btf_id == 0) { -- verbose(env, "invalid return type %d of func %s#%d\n", -- fn->ret_type, func_id_name(func_id), func_id); -+ verbose(env, "invalid return type %u of func %s#%d\n", -+ base_type(ret_type), func_id_name(func_id), -+ func_id); - return -EINVAL; - } - regs[BPF_REG_0].btf_id = ret_btf_id; - } else { -- verbose(env, "unknown return type %d of func %s#%d\n", -- fn->ret_type, func_id_name(func_id), func_id); -+ verbose(env, "unknown return type %u of func %s#%d\n", -+ base_type(ret_type), func_id_name(func_id), func_id); - return -EINVAL; - } - diff --git a/queue-5.10/bpf-selftests-test-ptr_to_rdonly_mem.patch b/queue-5.10/bpf-selftests-test-ptr_to_rdonly_mem.patch deleted file mode 100644 index 9143f7eda4..0000000000 --- a/queue-5.10/bpf-selftests-test-ptr_to_rdonly_mem.patch +++ /dev/null @@ -1,96 +0,0 @@ -From stable+bounces-152309-greg=kroah.com@vger.kernel.org Tue Jun 10 16:47:07 2025 -From: Puranjay Mohan -Date: Tue, 10 Jun 2025 14:44:03 +0000 -Subject: bpf/selftests: Test PTR_TO_RDONLY_MEM -To: Greg KH -Cc: Hao Luo , Alexei Starovoitov , Andrii Nakryiko , Puranjay Mohan , stable@vger.kernel.org -Message-ID: <20250610144407.95865-9-puranjay@kernel.org> - -From: Hao Luo - -commit 9497c458c10b049438ef6e6ddda898edbc3ec6a8 upstream. - -This test verifies that a ksym of non-struct can not be directly -updated. - -Signed-off-by: Hao Luo -Signed-off-by: Alexei Starovoitov -Acked-by: Andrii Nakryiko -[Changed ASSERT_ERR_PTR() to CHECK()] -Signed-off-by: Puranjay Mohan -Link: https://lore.kernel.org/bpf/20211217003152.48334-10-haoluo@google.com -Cc: stable@vger.kernel.org # 5.10.x -Signed-off-by: Greg Kroah-Hartman ---- - tools/testing/selftests/bpf/prog_tests/ksyms_btf.c | 14 ++++ - tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c | 29 ++++++++++ - 2 files changed, 43 insertions(+) - create mode 100644 tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c - ---- a/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c -+++ b/tools/testing/selftests/bpf/prog_tests/ksyms_btf.c -@@ -6,6 +6,7 @@ - #include - #include "test_ksyms_btf.skel.h" - #include "test_ksyms_btf_null_check.skel.h" -+#include "test_ksyms_btf_write_check.skel.h" - - static int duration; - -@@ -81,6 +82,16 @@ static void test_null_check(void) - test_ksyms_btf_null_check__destroy(skel); - } - -+static void test_write_check(void) -+{ -+ struct test_ksyms_btf_write_check *skel; -+ -+ skel = test_ksyms_btf_write_check__open_and_load(); -+ CHECK(skel, "skel_open", "unexpected load of a prog writing to ksym memory\n"); -+ -+ test_ksyms_btf_write_check__destroy(skel); -+} -+ - void test_ksyms_btf(void) - { - int percpu_datasec; -@@ -106,4 +117,7 @@ void test_ksyms_btf(void) - - if (test__start_subtest("null_check")) - test_null_check(); -+ -+ if (test__start_subtest("write_check")) -+ test_write_check(); - } ---- /dev/null -+++ b/tools/testing/selftests/bpf/progs/test_ksyms_btf_write_check.c -@@ -0,0 +1,29 @@ -+// SPDX-License-Identifier: GPL-2.0 -+/* Copyright (c) 2021 Google */ -+ -+#include "vmlinux.h" -+ -+#include -+ -+extern const int bpf_prog_active __ksym; /* int type global var. */ -+ -+SEC("raw_tp/sys_enter") -+int handler(const void *ctx) -+{ -+ int *active; -+ __u32 cpu; -+ -+ cpu = bpf_get_smp_processor_id(); -+ active = (int *)bpf_per_cpu_ptr(&bpf_prog_active, cpu); -+ if (active) { -+ /* Kernel memory obtained from bpf_{per,this}_cpu_ptr -+ * is read-only, should _not_ pass verification. -+ */ -+ /* WRITE_ONCE */ -+ *(volatile int *)active = -1; -+ } -+ -+ return 0; -+} -+ -+char _license[] SEC("license") = "GPL"; diff --git a/queue-5.10/series b/queue-5.10/series index 39cf2a26fa..e69d789894 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -344,12 +344,4 @@ net_sched-sch_sfq-handle-bigger-packets.patch net_sched-sch_sfq-don-t-allow-1-packet-limit.patch net_sched-sch_sfq-use-a-temporary-work-area-for-validating-configuration.patch net_sched-sch_sfq-move-the-limit-validation.patch -bpf-introduce-composable-reg-ret-and-arg-types.patch -bpf-replace-arg_xxx_or_null-with-arg_xxx-ptr_maybe_null.patch -bpf-replace-ret_xxx_or_null-with-ret_xxx-ptr_maybe_null.patch -bpf-replace-ptr_to_xxx_or_null-with-ptr_to_xxx-ptr_maybe_null.patch -bpf-introduce-mem_rdonly-flag.patch -bpf-make-per_cpu_ptr-return-rdonly-ptr_to_mem.patch -bpf-add-mem_rdonly-for-helper-args-that-are-pointers-to-rdonly-mem.patch -bpf-selftests-test-ptr_to_rdonly_mem.patch mm-huge_memory-fix-dereferencing-invalid-pmd-migration-entry.patch