Commit ea2e6467ac36 ("bpf: Return hashes of maps in BPF_OBJ_GET_INFO_BY_FD") started copying struct bpf_map_info in from userspace in order to read the new hash and hash_size input fields. Before that, the kernel ignored the contents of the user buffer and returned a zeroed structure with only the output fields filled in. Some output fields are only set for certain maps: btf_id, btf_key_type_id and btf_value_type_id when the map has BTF (and btf_vmlinux_id for struct_ops maps, ifindex, netns_dev and netns_ino when the map is offloaded). For all other maps, these fields now return whatever userspace passed in before. This breaks userspace which reuses one bpf_map_info for several queries. Restore the original behavior by keeping only hash and hash_size from the user copy and zeroing everything else before the output fields are filled in. Fixes: ea2e6467ac36 ("bpf: Return hashes of maps in BPF_OBJ_GET_INFO_BY_FD") Reported-by: Quentin Monnet Reported-by: Tianyi Chen Signed-off-by: Daniel Borkmann Cc: KP Singh --- kernel/bpf/syscall.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 654f896af265..0b11ba9837c2 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -5437,8 +5437,9 @@ static int bpf_map_get_info_by_fd(struct file *file, union bpf_attr __user *uattr) { struct bpf_map_info __user *uinfo = u64_to_user_ptr(attr->info.info); + u32 info_len = attr->info.info_len, len, hash_size; struct bpf_map_info info; - u32 info_len = attr->info.info_len, len; + u64 hash; int err; len = offsetofend(struct bpf_map_info, hash_size); @@ -5450,7 +5451,11 @@ static int bpf_map_get_info_by_fd(struct file *file, memset(&info, 0, sizeof(info)); if (copy_from_user(&info, uinfo, info_len)) return -EFAULT; - + hash = info.hash; + hash_size = info.hash_size; + memset(&info, 0, sizeof(info)); + info.hash = hash; + info.hash_size = hash_size; info.type = map->map_type; info.id = map->id; info.key_size = map->key_size; -- 2.43.0