bpf: Fix copy_map_value, zero_map_value
authorKumar Kartikeya Dwivedi <memxor@gmail.com>
Mon, 14 Nov 2022 19:15:24 +0000 (00:45 +0530)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 15 Nov 2022 05:52:45 +0000 (21:52 -0800)
The current offset needs to also skip over the already copied region in
addition to the size of the next field. This case manifests where there
are gaps between adjacent special fields.

It was observed that for a map value with size 48, having fields at:
off:  0, 16, 32
size: 4, 16, 16

The current code does:

memcpy(dst + 0, src + 0, 0)
memcpy(dst + 4, src + 4, 12)
memcpy(dst + 20, src + 20, 12)
memcpy(dst + 36, src + 36, 12)

With the fix, it is done correctly as:

memcpy(dst + 0, src + 0, 0)
memcpy(dst + 4, src + 4, 12)
memcpy(dst + 32, src + 32, 0)
memcpy(dst + 48, src + 48, 0)

Fixes: 4d7d7f69f4b1 ("bpf: Adapt copy_map_value for multiple offset case")
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20221114191547.1694267-4-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
include/linux/bpf.h

index 1a66a1d..f08eb2d 100644 (file)
@@ -360,7 +360,7 @@ static inline void bpf_obj_memcpy(struct btf_field_offs *foffs,
                u32 sz = next_off - curr_off;
 
                memcpy(dst + curr_off, src + curr_off, sz);
-               curr_off += foffs->field_sz[i];
+               curr_off += foffs->field_sz[i] + sz;
        }
        memcpy(dst + curr_off, src + curr_off, size - curr_off);
 }
@@ -390,7 +390,7 @@ static inline void bpf_obj_memzero(struct btf_field_offs *foffs, void *dst, u32
                u32 sz = next_off - curr_off;
 
                memset(dst + curr_off, 0, sz);
-               curr_off += foffs->field_sz[i];
+               curr_off += foffs->field_sz[i] + sz;
        }
        memset(dst + curr_off, 0, size - curr_off);
 }