BPF is the last user of the deprecated[1] strncpy() in the kernel. Replace it with a length check via strnlen() on the source followed by memcpy(). Normally strscpy() would be used in this case, but skel_internal.h is shared between kernel and userspace tools, and strscpy() is not available in the userspace build context. The source map_name is a NUL-terminated C string (the only caller passes the "__loader.map" 12 character string literal). The destination attr.map_name is char[BPF_OBJ_NAME_LEN] (16 bytes) in union bpf_attr, ultimately passed to the bpf() syscall. The bpf(BPF_MAP_CREATE) syscall, through bpf_obj_name_cpy(), requires a NUL terminator within this 16-byte array, rejecting names that use all 16 bytes. Valid names are therefore at most 15 characters, but this wasn't being checked via the skel_map_create() path. Add a matching check and refuse 16+ character strings early, as they would be refused later by bpf_obj_name_cpy(). The attr is pre-zeroed with memset() at the top of the function, so the last byte of attr.map_name is always NUL, meaning the memcpy() of just the non-NUL characters from the source will always produce a NUL-terminated destination string. Link: https://github.com/KSPP/linux/issues/90 [1] Suggested-by: Sun Jian Signed-off-by: Kees Cook --- v4: Reformat commit log slightly, confirm last user of strnlen in -next v3: https://lore.kernel.org/lkml/20260324161605.make.168-kees@kernel.org/ v2: https://lore.kernel.org/lkml/20260324053036.it.906-kees@kernel.org/ v1: https://lore.kernel.org/lkml/20260324040535.work.851-kees@kernel.org/ Cc: Alexei Starovoitov Cc: Jiri Olsa Cc: sun jian Cc: Andrii Nakryiko Cc: Eduard Zingerman Cc: Daniel Borkmann Cc: Martin KaFai Lau Cc: Song Liu Cc: Yonghong Song Cc: John Fastabend Cc: KP Singh Cc: Stanislav Fomichev Cc: Hao Luo Cc: --- tools/lib/bpf/skel_internal.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/lib/bpf/skel_internal.h b/tools/lib/bpf/skel_internal.h index 6a8f5c7a02eb..2d38c387f43c 100644 --- a/tools/lib/bpf/skel_internal.h +++ b/tools/lib/bpf/skel_internal.h @@ -236,6 +236,7 @@ static inline int skel_map_create(enum bpf_map_type map_type, { const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size); union bpf_attr attr; + size_t map_name_len; memset(&attr, 0, attr_sz); @@ -243,7 +244,12 @@ static inline int skel_map_create(enum bpf_map_type map_type, attr.excl_prog_hash = (unsigned long) excl_prog_hash; attr.excl_prog_hash_size = excl_prog_hash_sz; - strncpy(attr.map_name, map_name, sizeof(attr.map_name)); + /* attr.map_name must be NUL-terminated, like bpf_obj_name_cpy() */ + map_name_len = strnlen(map_name, sizeof(attr.map_name)); + if (map_name_len == sizeof(attr.map_name)) + return -EINVAL; + memcpy(attr.map_name, map_name, map_name_len); + attr.key_size = key_size; attr.value_size = value_size; attr.max_entries = max_entries; -- 2.34.1