In kernel, per-CPU map elements are stored with
round_up(map->value_size, 8) bytes. On UAPI lookup paths, it copies the
rounded size for each CPU into a temporary buffer.

However, copy_map_value_long() passes 'map->value_size' to
bpf_obj_memcpy(). When the map has special fields, bpf_obj_memcpy() copies
around those fields with memcpy(), and does not copy the tail padding
between 'map->value_size' and round_up(map->value_size, 8).

The temporary UAPI lookup buffers are allocated without __GFP_ZERO. As a
result, when the per-CPU map's value size is not equal to
round_up(map->value_size, 8), UAPI LOOKUP_ELEM and its variants can return
stale heap contents from that padding to user space. The same issue
applies to bpf_iter for per-CPU maps.

Pass round_up(map->value_size, 8) to bpf_obj_memcpy() from
copy_map_value_long(), so per-CPU maps both with and without special
fields copy the entire per-CPU slot. Remove the now redundant round_up()
from bpf_obj_memcpy()'s long_memcpy path.

Fixes: 448325199f57 ("bpf: Add copy_map_value_long to copy to remote percpu 
memory")
Signed-off-by: Leon Hwang <[email protected]>
---
 include/linux/bpf.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 7719f6528445..ba09795e0bfd 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -570,7 +570,7 @@ static inline void bpf_obj_memcpy(struct btf_record *rec,
 
        if (IS_ERR_OR_NULL(rec)) {
                if (long_memcpy)
-                       bpf_long_memcpy(dst, src, round_up(size, 8));
+                       bpf_long_memcpy(dst, src, size);
                else
                        memcpy(dst, src, size);
                return;
@@ -593,7 +593,7 @@ static inline void copy_map_value(struct bpf_map *map, void 
*dst, void *src)
 
 static inline void copy_map_value_long(struct bpf_map *map, void *dst, void 
*src)
 {
-       bpf_obj_memcpy(map->record, dst, src, map->value_size, true);
+       bpf_obj_memcpy(map->record, dst, src, round_up(map->value_size, 8), 
true);
 }
 
 static inline void bpf_obj_swap_uptrs(const struct btf_record *rec, void *dst, 
void *src)
-- 
2.54.0


Reply via email to