Patch "net: sched: cls_u32: Fix allocation size in u32_init()" has been added to the 5.10-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

    net: sched: cls_u32: Fix allocation size in u32_init()

to the 5.10-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:
     net-sched-cls_u32-fix-allocation-size-in-u32_init.patch
and it can be found in the queue-5.10 subdirectory.

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



commit 92f74f6a2bdd40e346abe604de41f609bfef1ad0
Author: Gustavo A. R. Silva <gustavoars@xxxxxxxxxx>
Date:   Wed Oct 4 15:19:37 2023 +0200

    net: sched: cls_u32: Fix allocation size in u32_init()
    
    [ Upstream commit c4d49196ceec80e30e8d981410d73331b49b7850 ]
    
    commit d61491a51f7e ("net/sched: cls_u32: Replace one-element array
    with flexible-array member") incorrecly replaced an instance of
    `sizeof(*tp_c)` with `struct_size(tp_c, hlist->ht, 1)`. This results
    in a an over-allocation of 8 bytes.
    
    This change is wrong because `hlist` in `struct tc_u_common` is a
    pointer:
    
    net/sched/cls_u32.c:
    struct tc_u_common {
            struct tc_u_hnode __rcu *hlist;
            void                    *ptr;
            int                     refcnt;
            struct idr              handle_idr;
            struct hlist_node       hnode;
            long                    knodes;
    };
    
    So, the use of `struct_size()` makes no sense: we don't need to allocate
    any extra space for a flexible-array member. `sizeof(*tp_c)` is just fine.
    
    So, `struct_size(tp_c, hlist->ht, 1)` translates to:
    
    sizeof(*tp_c) + sizeof(tp_c->hlist->ht) ==
    sizeof(struct tc_u_common) + sizeof(struct tc_u_knode *) ==
                                                    144 + 8  == 0x98 (byes)
                                                         ^^^
                                                          |
                                                    unnecessary extra
                                                    allocation size
    
    $ pahole -C tc_u_common net/sched/cls_u32.o
    struct tc_u_common {
            struct tc_u_hnode *        hlist;                /*     0     8 */
            void *                     ptr;                  /*     8     8 */
            int                        refcnt;               /*    16     4 */
    
            /* XXX 4 bytes hole, try to pack */
    
            struct idr                 handle_idr;           /*    24    96 */
            /* --- cacheline 1 boundary (64 bytes) was 56 bytes ago --- */
            struct hlist_node          hnode;                /*   120    16 */
            /* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
            long int                   knodes;               /*   136     8 */
    
            /* size: 144, cachelines: 3, members: 6 */
            /* sum members: 140, holes: 1, sum holes: 4 */
            /* last cacheline: 16 bytes */
    };
    
    And with `sizeof(*tp_c)`, we have:
    
            sizeof(*tp_c) == sizeof(struct tc_u_common) == 144 == 0x90 (bytes)
    
    which is the correct and original allocation size.
    
    Fix this issue by replacing `struct_size(tp_c, hlist->ht, 1)` with
    `sizeof(*tp_c)`, and avoid allocating 8 too many bytes.
    
    The following difference in binary output is expected and reflects the
    desired change:
    
    | net/sched/cls_u32.o
    | @@ -6148,7 +6148,7 @@
    | include/linux/slab.h:599
    |     2cf5:      mov    0x0(%rip),%rdi        # 2cfc <u32_init+0xfc>
    |                        2cf8: R_X86_64_PC32     kmalloc_caches+0xc
    |-    2cfc:      mov    $0x98,%edx
    |+    2cfc:      mov    $0x90,%edx
    
    Reported-by: Alejandro Colomar <alx@xxxxxxxxxx>
    Closes: https://lore.kernel.org/lkml/09b4a2ce-da74-3a19-6961-67883f634d98@xxxxxxxxxx/
    Signed-off-by: Gustavo A. R. Silva <gustavoars@xxxxxxxxxx>
    Acked-by: Jamal Hadi Salim <jhs@xxxxxxxxxxxx>
    Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index b2d2ba561eba1..f2a0c10682fc8 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -364,7 +364,7 @@ static int u32_init(struct tcf_proto *tp)
 	idr_init(&root_ht->handle_idr);
 
 	if (tp_c == NULL) {
-		tp_c = kzalloc(struct_size(tp_c, hlist->ht, 1), GFP_KERNEL);
+		tp_c = kzalloc(sizeof(*tp_c), GFP_KERNEL);
 		if (tp_c == NULL) {
 			kfree(root_ht);
 			return -ENOBUFS;



[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