Re: [PATCH v2] bpf: Annotate bpf_obj_memcpy with data_race

Andrii Nakryiko <[email protected]>
Newsgroups org.kernel.vger.bpf,org.kernel.vger.linux-kernel
Message-ID <CAEf4BzYf+LBqAncYEJNLz8bhSU2HWvnOMzrRyMcr_uczd2MP_g@mail.gmail.com>
On Thu, Aug 20, 2026 at 4:11 AM quanyeyang via B4 Relay
<[email protected]> wrote:
>
> From: quanyeyang <[email protected]>
>
> syzbot reported KCSAN write-write races when two tasks concurrently
> update the same map value. Both accesses reach the ordinary memcpy()
> paths in bpf_obj_memcpy() through copy_map_value().
>
> Unlocked in-place updates of published map values are intentionally not
> serialized and may produce torn values. Callers requiring consistency
> must provide synchronization appropriate for the map type.
> bpf_long_memcpy() already annotates the same behavior for long-aligned
> copies.
>
> Annotate the ordinary memcpy() sites in bpf_obj_memcpy() with
> data_race(), matching bpf_long_memcpy(). This documents the existing
> concurrency semantics and suppresses KCSAN reports for these intentional
> races without changing synchronization or map update behavior.
>
> Reported-by: [email protected]
> Closes: https://syzkaller.appspot.com/bug?extid=44044637ef892e79ca2b
> Signed-off-by: quanyeyang <[email protected]>
> ---
> The annotations remain in the common bpf_obj_memcpy() helper, matching
> bpf_long_memcpy(). This keeps the existing copy helper interfaces
> unchanged. A narrower annotation would require propagating the
> concurrency context through copy_map_value() or introducing separate
> copy helpers.
>
> The following checkpatch warnings are expected:
>
> - DATA_RACE is reported for the three annotations because checkpatch
>   only recognizes an immediately adjacent comment. Their shared
>   rationale is documented above bpf_obj_memcpy().
> - MISSING_FIXES_TAG is reported because the commit references syzkaller.
>   No Fixes tag is included because this documents long-standing
>   intentional lockless semantics rather than a regression introduced
>   by a particular commit.
> ---
> Changes in v2:
> - Drop the BPF_F_LOCK recommendation because it is unavailable for
>   per-CPU maps.
> - Scope the concurrency description to unlocked in-place updates of
>   published map values.
> - Fold the redundant commit message paragraphs.
> - Link to v1:
>   https://patch.msgid.link/[email protected]
>
> To: Alexei Starovoitov <[email protected]>
> To: Daniel Borkmann <[email protected]>
> To: Andrii Nakryiko <[email protected]>
> To: Eduard Zingerman <[email protected]>
> To: Kumar Kartikeya Dwivedi <[email protected]>
> To: Martin KaFai Lau <[email protected]>
> To: Song Liu <[email protected]>
> To: Yonghong Song <[email protected]>
> To: Jiri Olsa <[email protected]>
> To: Emil Tsalapatis <[email protected]>
> To: John Fastabend <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> ---
>  include/linux/bpf.h | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 7719f6528445..10d1186ef3b4 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -560,7 +560,14 @@ static inline void bpf_long_memcpy(void *dst, const void *src, u32 size)
>                 data_race(*ldst++ = *lsrc++);
>  }
>
> -/* copy everything but bpf_spin_lock, bpf_timer, and kptrs. There could be one of each. */
> +/*
> + * Copy everything but bpf_spin_lock, bpf_timer, and kptrs. There could
> + * be one of each.
> + *
> + * When this helper performs an unlocked in-place update of a published
> + * map value, the ordinary byte copies may intentionally race with
> + * concurrent updates and the resulting value may be torn.
> + */

kind of "obviously", so might as well keep original comment as is, IMO

>  static inline void bpf_obj_memcpy(struct btf_record *rec,
>                                   void *dst, void *src, u32 size,
>                                   bool long_memcpy)
> @@ -572,7 +579,7 @@ static inline void bpf_obj_memcpy(struct btf_record *rec,
>                 if (long_memcpy)
>                         bpf_long_memcpy(dst, src, round_up(size, 8));
>                 else
> -                       memcpy(dst, src, size);
> +                       data_race(memcpy(dst, src, size));
>                 return;
>         }
>
> @@ -580,10 +587,10 @@ static inline void bpf_obj_memcpy(struct btf_record *rec,
>                 u32 next_off = rec->fields[i].offset;
>                 u32 sz = next_off - curr_off;
>
> -               memcpy(dst + curr_off, src + curr_off, sz);
> +               data_race(memcpy(dst + curr_off, src + curr_off, sz));
>                 curr_off += rec->fields[i].size + sz;
>         }
> -       memcpy(dst + curr_off, src + curr_off, size - curr_off);
> +       data_race(memcpy(dst + curr_off, src + curr_off, size - curr_off));
>  }
>

The change looks good, but Signed-off-by requires real and properly
cased full name, please update and resend the patch

pw-bot: cr

>  static inline void copy_map_value(struct bpf_map *map, void *dst, void *src)
>
> ---
> base-commit: bd5f485f3f026225b86573e559af0b7254ef4184
> change-id: 20260819-bpf-kcsan-obj-memcpy-67042b1fce7d
>
> Best regards,
> --
> quanyeyang <[email protected]>
>
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.