diff mbox series

hw/net/e1000: fix memory leak in timer_del()

Message ID 551d9eaf-dce0-4cf0-95b1-d2347bfaa1a6@gmail.com (mailing list archive)
State New
Headers show
Series hw/net/e1000: fix memory leak in timer_del() | expand

Commit Message

Zheng Huang March 27, 2025, 11:28 a.m. UTC
Hi,
This patch addresses a memory leak bug in the usages of `timer_del()`.
The issue arisesfrom the incorrect use of the ambiguous timer API 
`timer_del()`, which does not free the timer object. The leak sanitizer
report this issue during fuzzing. The correct API `timer_free()` freed
the timer object instead.

In addition, I'd like to ask for a way to fix all 100+ wrong usages. In my
opinion, the best way to fix this is to hide to `timer_del()` API and
eliminate all usages of it.

ps: Sorry for the mistake in subject of the previous mail.

Signed-off-by: Zheng Huang <hz1624917200@outlook.com>


---
 hw/net/e1000.c       | 6 +++---
 hw/net/e1000e_core.c | 8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

Comments

Prasad Pandit March 27, 2025, 12:40 p.m. UTC | #1
Hello,

On Thu, 27 Mar 2025 at 16:59, Zheng Huang <hz1624917200@gmail.com> wrote:
> This patch addresses a memory leak bug in the usages of `timer_del()`.
> The issue arisesfrom the incorrect use of the ambiguous timer API
> `timer_del()`, which does not free the timer object. The leak sanitizer
> report this issue during fuzzing. The correct API `timer_free()` freed
> the timer object instead.
>
> In addition, I'd like to ask for a way to fix all 100+ wrong usages. In my
> opinion, the best way to fix this is to hide to `timer_del()` API and
> eliminate all usages of it.
>
> @@ -379,9 +379,9 @@ static void e1000_reset_hold(Object *obj, ResetType type)
>      E1000BaseClass *edc = E1000_GET_CLASS(d);
>      uint8_t *macaddr = d->conf.macaddr.a;
>
> -    timer_del(d->autoneg_timer);
> -    timer_del(d->mit_timer);
> -    timer_del(d->flush_queue_timer);
> +    timer_free(d->autoneg_timer);
> +    timer_free(d->mit_timer);
> +    timer_free(d->flush_queue_timer);
>      d->mit_timer_on = 0;
>      d->mit_irq_level = 0;
>      d->mit_ide = 0;
> diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
> index 2413858790..61fdc8a3e9 100644
> --- a/hw/net/e1000e_core.c
> +++ b/hw/net/e1000e_core.c
> @@ -127,7 +127,7 @@ static inline void
>  e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
>  {
>      if (timer->running) {
> -        timer_del(timer->timer);
> +        timer_free(timer->timer);
>          timer->running = false;
>      }
>  }
> @@ -360,13 +360,13 @@ e1000e_intrmgr_fire_all_timers(E1000ECore *core)
>      int i;
>
>      if (core->itr.running) {
> -        timer_del(core->itr.timer);
> +        timer_free(core->itr.timer);
>          e1000e_intrmgr_on_throttling_timer(&core->itr);
>      }
>
>      for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
>          if (core->eitr[i].running) {
> -            timer_del(core->eitr[i].timer);
> +            timer_free(core->eitr[i].timer);
>              e1000e_intrmgr_on_msix_throttling_timer(&core->eitr[i]);
>          }
>      }
> @@ -3452,7 +3452,7 @@ static void e1000e_reset(E1000ECore *core, bool sw)
>  {
>      int i;
>
> -    timer_del(core->autoneg_timer);
> +    timer_free(core->autoneg_timer);
>
>      e1000e_intrmgr_reset(core);

* I doubt if this is correct; Because timer_del() API explicitly says
-> /* stop a timer, but do not dealloc it */

* Secondly: autoneg_timer/mit_timer/flush_queue_timer objects are
freed in 'pci_e1000_uninit()/e1000e_pci_uninit()' functions via
timer_free() calls. So the memory leak could be because the respective
*_pci__uninit() function is not called?

Thank you.
---
  - Prasad
Zheng Huang March 28, 2025, 2:44 a.m. UTC | #2
Hello Prasad,

在 2025/3/27 20:40, Prasad Pandit wrote:
>> @@ -360,13 +360,13 @@ e1000e_intrmgr_fire_all_timers(E1000ECore *core)
>>      int i;
>>
>>      if (core->itr.running) {
>> -        timer_del(core->itr.timer);
>> +        timer_free(core->itr.timer);
>>          e1000e_intrmgr_on_throttling_timer(&core->itr);
>>      }
>>
>>      for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
>>          if (core->eitr[i].running) {
>> -            timer_del(core->eitr[i].timer);
>> +            timer_free(core->eitr[i].timer);
>>              e1000e_intrmgr_on_msix_throttling_timer(&core->eitr[i]);
>>          }
>>      }
>> @@ -3452,7 +3452,7 @@ static void e1000e_reset(E1000ECore *core, bool sw)
>>  {
>>      int i;
>>
>> -    timer_del(core->autoneg_timer);
>> +    timer_free(core->autoneg_timer);
>>
>>      e1000e_intrmgr_reset(core);
> 
> * I doubt if this is correct; Because timer_del() API explicitly says
> -> /* stop a timer, but do not dealloc it */
> 
> * Secondly: autoneg_timer/mit_timer/flush_queue_timer objects are
> freed in 'pci_e1000_uninit()/e1000e_pci_uninit()' functions via
> timer_free() calls. So the memory leak could be because the respective
> *_pci__uninit() function is not called?

Yes, you are right. I mistakenly assumed that there's no way to reenable a
`_del()`ed timer. Thank you sincerely for pointing out this. I'll check the
usage carefully in other occurences.

Best regard,
Zheng
diff mbox series

Patch

diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 3d0b227703..5dddf9e0a7 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -379,9 +379,9 @@  static void e1000_reset_hold(Object *obj, ResetType type)
     E1000BaseClass *edc = E1000_GET_CLASS(d);
     uint8_t *macaddr = d->conf.macaddr.a;
 
-    timer_del(d->autoneg_timer);
-    timer_del(d->mit_timer);
-    timer_del(d->flush_queue_timer);
+    timer_free(d->autoneg_timer);
+    timer_free(d->mit_timer);
+    timer_free(d->flush_queue_timer);
     d->mit_timer_on = 0;
     d->mit_irq_level = 0;
     d->mit_ide = 0;
diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c
index 2413858790..61fdc8a3e9 100644
--- a/hw/net/e1000e_core.c
+++ b/hw/net/e1000e_core.c
@@ -127,7 +127,7 @@  static inline void
 e1000e_intrmgr_stop_timer(E1000IntrDelayTimer *timer)
 {
     if (timer->running) {
-        timer_del(timer->timer);
+        timer_free(timer->timer);
         timer->running = false;
     }
 }
@@ -360,13 +360,13 @@  e1000e_intrmgr_fire_all_timers(E1000ECore *core)
     int i;
 
     if (core->itr.running) {
-        timer_del(core->itr.timer);
+        timer_free(core->itr.timer);
         e1000e_intrmgr_on_throttling_timer(&core->itr);
     }
 
     for (i = 0; i < E1000E_MSIX_VEC_NUM; i++) {
         if (core->eitr[i].running) {
-            timer_del(core->eitr[i].timer);
+            timer_free(core->eitr[i].timer);
             e1000e_intrmgr_on_msix_throttling_timer(&core->eitr[i]);
         }
     }
@@ -3452,7 +3452,7 @@  static void e1000e_reset(E1000ECore *core, bool sw)
 {
     int i;
 
-    timer_del(core->autoneg_timer);
+    timer_free(core->autoneg_timer);
 
     e1000e_intrmgr_reset(core);