[PATCH bpf-next 1/2] bpf: Limit local storage value size to max kmalloc_nolock() allocation

From: Jonathan Bastari Thamrin via B4 Relay

Date: Wed Nov 04 2026 - 06:43:33 EST


From: Jonathan Bastari Thamrin <thamrinjonathan@xxxxxxxxx>

Since commit f484f4a3e058 ("bpf: Replace bpf memory allocator
with kmalloc_nolock() in local storage") for task and cgroup
local storage and commit 5063e7758899 ("bpf: Use kmalloc_nolock()
universally in local storage") for the rest, elements are
allocated using kmalloc_nolock() which has a maximum
allocation size of KMALLOC_MAX_CACHE_SIZE. Map creation still
doesn't match this and accepts values up to ~64KB. This causes
map updates to fail with ENOMEM due to the map not being able
to store anything.

BPF_LOCAL_STORAGE_MAX_VALUE_SIZE is now based on
KMALLOC_MAX_CACHE_SIZE and maps with larger values fail on
creation with E2BIG. Cgroup storage (BPF_MAP_TYPE_CGROUP_STORAGE)
still uses the previous limit as its own constant since it
allocates with kmalloc().

Fixes: f484f4a3e058 ("bpf: Replace bpf memory allocator with kmalloc_nolock() in local storage")
Fixes: 5063e7758899 ("bpf: Use kmalloc_nolock() universally in local storage")
Reported-by: Slava Imameev <slava.imameev@xxxxxxxxxxxxxxx>
Closes: https://lore.kernel.org/bpf/20260410014341.47043-1-slava.imameev@xxxxxxxxxxxxxxx/
Suggested-by: Alexei Starovoitov <ast@xxxxxxxxxx>
Link: https://lore.kernel.org/bpf/CAADnVQKeFF--bgnZZSU12UY0muuwYA=7EdzLyOi837oZs+bXTA@xxxxxxxxxxxxxx/
Signed-off-by: Jonathan Bastari Thamrin <thamrinjonathan@xxxxxxxxx>
---
include/linux/bpf_local_storage.h | 10 +++++-----
kernel/bpf/local_storage.c | 13 +++++++++++--
2 files changed, 16 insertions(+), 7 deletions(-)

diff --git a/include/linux/bpf_local_storage.h b/include/linux/bpf_local_storage.h
index 6c643ac51079..e1ce75b0fb0a 100644
--- a/include/linux/bpf_local_storage.h
+++ b/include/linux/bpf_local_storage.h
@@ -117,13 +117,13 @@ bpf_local_storage_unpin_owner(struct bpf_local_storage *local_storage)
last = refcount_dec_and_test(&local_storage->owner_refcnt);
}

-/* U16_MAX is much more than enough for sk local storage
- * considering a tcp_sock is ~2k.
+/* Elements come from kmalloc_nolock() where the max size
+ * is KMALLOC_MAX_CACHE_SIZE.
*/
-#define BPF_LOCAL_STORAGE_MAX_VALUE_SIZE \
+#define BPF_LOCAL_STORAGE_MAX_VALUE_SIZE \
min_t(u32, \
- (KMALLOC_MAX_SIZE - MAX_BPF_STACK - \
- sizeof(struct bpf_local_storage_elem)), \
+ (KMALLOC_MAX_CACHE_SIZE - \
+ offsetof(struct bpf_local_storage_elem, sdata.data)), \
(U16_MAX - sizeof(struct bpf_local_storage_elem)))

#define SELEM(_SDATA) \
diff --git a/kernel/bpf/local_storage.c b/kernel/bpf/local_storage.c
index 83cd527a2542..22a9841d4fd5 100644
--- a/kernel/bpf/local_storage.c
+++ b/kernel/bpf/local_storage.c
@@ -18,6 +18,15 @@
#define LOCAL_STORAGE_CREATE_FLAG_MASK \
(BPF_F_NUMA_NODE | BPF_F_ACCESS_MASK)

+/* Cgroup storage allocates with kmalloc() where the max size is
+ * larger than kmalloc_nolock() used by other local storages.
+ */
+#define BPF_CGROUP_STORAGE_MAX_VALUE_SIZE \
+ min_t(u32, \
+ (KMALLOC_MAX_SIZE - MAX_BPF_STACK - \
+ sizeof(struct bpf_local_storage_elem)), \
+ (U16_MAX - sizeof(struct bpf_local_storage_elem)))
+
struct bpf_cgroup_storage_map {
struct bpf_map map;

@@ -296,12 +305,12 @@ static int cgroup_storage_get_next_key(struct bpf_map *_map, void *key,

static struct bpf_map *cgroup_storage_map_alloc(union bpf_attr *attr)
{
- __u32 max_value_size = BPF_LOCAL_STORAGE_MAX_VALUE_SIZE;
+ __u32 max_value_size = BPF_CGROUP_STORAGE_MAX_VALUE_SIZE;
int numa_node = bpf_map_attr_numa_node(attr);
struct bpf_cgroup_storage_map *map;

/* percpu is bound by PCPU_MIN_UNIT_SIZE, non-percu
- * is the same as other local storages.
+ * uses the cgroup storage limit above
*/
if (attr->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
max_value_size = min_t(__u32, max_value_size,

--
2.56.0