net: atlantic: fix double free in ring reinit logic
authorIgor Russkikh <irusskikh@marvell.com>
Wed, 13 Dec 2023 09:40:44 +0000 (10:40 +0100)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 14 Dec 2023 11:10:59 +0000 (12:10 +0100)
Driver has a logic leak in ring data allocation/free,
where double free may happen in aq_ring_free if system is under
stress and driver init/deinit is happening.

The probability is higher to get this during suspend/resume cycle.

Verification was done simulating same conditions with

    stress -m 2000 --vm-bytes 20M --vm-hang 10 --backoff 1000
    while true; do sudo ifconfig enp1s0 down; sudo ifconfig enp1s0 up; done

Fixed by explicitly clearing pointers to NULL on deallocation

Fixes: 018423e90bee ("net: ethernet: aquantia: Add ring support code")
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Closes: https://lore.kernel.org/netdev/CAHk-=wiZZi7FcvqVSUirHBjx0bBUZ4dFrMDVLc3+3HCrtq0rBA@mail.gmail.com/
Signed-off-by: Igor Russkikh <irusskikh@marvell.com>
Link: https://lore.kernel.org/r/20231213094044.22988-1-irusskikh@marvell.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/aquantia/atlantic/aq_ring.c

index 694daeaf3e6150b3c0581f354bad9ce5a93eed0b..e1885c1eb100a1fa67c0588832a991718728562c 100644 (file)
@@ -938,11 +938,14 @@ void aq_ring_free(struct aq_ring_s *self)
                return;
 
        kfree(self->buff_ring);
+       self->buff_ring = NULL;
 
-       if (self->dx_ring)
+       if (self->dx_ring) {
                dma_free_coherent(aq_nic_get_dev(self->aq_nic),
                                  self->size * self->dx_size, self->dx_ring,
                                  self->dx_ring_pa);
+               self->dx_ring = NULL;
+       }
 }
 
 unsigned int aq_ring_fill_stats_data(struct aq_ring_s *self, u64 *data)