Patch "bpf: Check the remaining info_cnt before repeating btf fields" has been added to the 6.11-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    bpf: Check the remaining info_cnt before repeating btf fields

to the 6.11-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     bpf-check-the-remaining-info_cnt-before-repeating-bt.patch
and it can be found in the queue-6.11 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 5d6df866a454ac2c4a0b3353b77e2616a172c337
Author: Hou Tao <houtao1@xxxxxxxxxx>
Date:   Tue Oct 8 15:11:13 2024 +0800

    bpf: Check the remaining info_cnt before repeating btf fields
    
    [ Upstream commit 797d73ee232dd1833dec4824bc53a22032e97c1c ]
    
    When trying to repeat the btf fields for array of nested struct, it
    doesn't check the remaining info_cnt. The following splat will be
    reported when the value of ret * nelems is greater than BTF_FIELDS_MAX:
    
      ------------[ cut here ]------------
      UBSAN: array-index-out-of-bounds in ../kernel/bpf/btf.c:3951:49
      index 11 is out of range for type 'btf_field_info [11]'
      CPU: 6 UID: 0 PID: 411 Comm: test_progs ...... 6.11.0-rc4+ #1
      Tainted: [O]=OOT_MODULE
      Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS ...
      Call Trace:
       <TASK>
       dump_stack_lvl+0x57/0x70
       dump_stack+0x10/0x20
       ubsan_epilogue+0x9/0x40
       __ubsan_handle_out_of_bounds+0x6f/0x80
       ? kallsyms_lookup_name+0x48/0xb0
       btf_parse_fields+0x992/0xce0
       map_create+0x591/0x770
       __sys_bpf+0x229/0x2410
       __x64_sys_bpf+0x1f/0x30
       x64_sys_call+0x199/0x9f0
       do_syscall_64+0x3b/0xc0
       entry_SYSCALL_64_after_hwframe+0x4b/0x53
      RIP: 0033:0x7fea56f2cc5d
      ......
       </TASK>
      ---[ end trace ]---
    
    Fix it by checking the remaining info_cnt in btf_repeat_fields() before
    repeating the btf fields.
    
    Fixes: 64e8ee814819 ("bpf: look into the types of the fields of a struct type recursively.")
    Signed-off-by: Hou Tao <houtao1@xxxxxxxxxx>
    Acked-by: Eduard Zingerman <eddyz87@xxxxxxxxx>
    Link: https://lore.kernel.org/r/20241008071114.3718177-2-houtao@xxxxxxxxxxxxxxx
    Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 9b068afd17953..5f4f1d0bc23a4 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -3528,7 +3528,7 @@ static int btf_get_field_type(const struct btf *btf, const struct btf_type *var_
  *   (i + 1) * elem_size
  * where i is the repeat index and elem_size is the size of an element.
  */
-static int btf_repeat_fields(struct btf_field_info *info,
+static int btf_repeat_fields(struct btf_field_info *info, int info_cnt,
 			     u32 field_cnt, u32 repeat_cnt, u32 elem_size)
 {
 	u32 i, j;
@@ -3548,6 +3548,12 @@ static int btf_repeat_fields(struct btf_field_info *info,
 		}
 	}
 
+	/* The type of struct size or variable size is u32,
+	 * so the multiplication will not overflow.
+	 */
+	if (field_cnt * (repeat_cnt + 1) > info_cnt)
+		return -E2BIG;
+
 	cur = field_cnt;
 	for (i = 0; i < repeat_cnt; i++) {
 		memcpy(&info[cur], &info[0], field_cnt * sizeof(info[0]));
@@ -3592,7 +3598,7 @@ static int btf_find_nested_struct(const struct btf *btf, const struct btf_type *
 		info[i].off += off;
 
 	if (nelems > 1) {
-		err = btf_repeat_fields(info, ret, nelems - 1, t->size);
+		err = btf_repeat_fields(info, info_cnt, ret, nelems - 1, t->size);
 		if (err == 0)
 			ret *= nelems;
 		else
@@ -3686,10 +3692,10 @@ static int btf_find_field_one(const struct btf *btf,
 
 	if (ret == BTF_FIELD_IGNORE)
 		return 0;
-	if (nelems > info_cnt)
+	if (!info_cnt)
 		return -E2BIG;
 	if (nelems > 1) {
-		ret = btf_repeat_fields(info, 1, nelems - 1, sz);
+		ret = btf_repeat_fields(info, info_cnt, 1, nelems - 1, sz);
 		if (ret < 0)
 			return ret;
 	}




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux