summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2026-09-21 04:38:32 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-21 17:12:39 +0000
commit5da4a9f26fca03ccd8afcc88f5c709c459c00ab8 (patch)
tree6ab0d66f36ebf4b13a276346f5e532b9f24c18ef /include/linux
parent89835699ef4e0240758429e0e85d3bbd4154065e (diff)
downloadlinux-next-5da4a9f26fca03ccd8afcc88f5c709c459c00ab8.tar.gz
linux-next-5da4a9f26fca03ccd8afcc88f5c709c459c00ab8.zip
bpf: Preserve stack initialization for generic output buffers
Partial-output helpers such as bpf_snprintf() do not read incoming buffer contents, but may leave some bytes untouched. Let them accept uninitialized storage without promising full initialization to callers that cannot read uninitialized stack memory. Make this the default for generic MEM_UNINIT buffers, including __uninit kfunc arguments. Allow invalid stack bytes through the output check but leave them invalid when uninitialized stack reads are not allowed. Scrub initialized bytes and scalar spills as possible writes, retaining the existing restrictions on spilled pointers and special stack objects. Retain the output annotation for variable-sized arguments and track their raw-mode eligibility separately. Callers allowed uninitialized stack reads can continue treating the potentially written range as initialized. For constant ranges, defer that initialization until all inputs are checked. Keep prior stack contents live for generic outputs when the caller cannot read uninitialized stack memory. Such calls do not define the entire range, so liveness must preserve initialization facts that remain relevant after the call. Dynptr and iterator constructors still define their storage. Annotate the snprintf, sysctl name, d_path, snprintf_btf and branch-record destinations with MEM_UNINIT, and document that generic __uninit kfuncs may leave bytes untouched. This also changes readback from existing full-writing helpers: without permission to read uninitialized stack memory, programs must initialize those bytes themselves before reading them after a call. Suggested-by: Eduard Zingerman <eddyz87@gmail.com> Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://patch.msgid.link/20260921023843.411943-9-memxor@gmail.com
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf.h5
-rw-r--r--include/linux/bpf_verifier.h8
2 files changed, 9 insertions, 4 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5033b934ffd9..fd22db8bc6c5 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -781,7 +781,10 @@ enum bpf_type_flag {
*/
PTR_UNTRUSTED = BIT(6 + BPF_BASE_TYPE_BITS),
- /* MEM can be uninitialized. */
+ /*
+ * MEM can be uninitialized. Generic memory outputs need not be fully
+ * initialized by the callee.
+ */
MEM_UNINIT = BIT(7 + BPF_BASE_TYPE_BITS),
/* DYNPTR points to memory local to the bpf program. */
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 9ddbb20ec1e9..92f528c45605 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -1547,12 +1547,14 @@ struct ref_obj_desc {
};
/*
- * Memory arguments a call fills in, indexed by argument slot. The verifier allows the
- * stack to be uninitialized if the range is a known constant. Stack slots are marked as
- * STACK_MISC by check_mem_access() after all arguments have been checked.
+ * Generic MEM_UNINIT arguments, indexed by ABI slot. var_size_mask excludes
+ * variable-sized buffers from raw mode without losing the output annotation.
+ * size records constant ranges to mark initialized after checking all arguments,
+ * only when the caller is allowed to read uninitialized stack memory.
*/
struct arg_raw_mem_desc {
u16 mask;
+ u16 var_size_mask;
int size[MAX_BPF_FUNC_ARGS];
};