realtek: fix memory leak in netevent handler
authorJan Hoffmann <jan@3e8.eu>
Wed, 8 Feb 2023 21:53:32 +0000 (22:53 +0100)
committerSander Vanheule <sander@svanheule.net>
Mon, 13 Feb 2023 11:14:16 +0000 (12:14 +0100)
The net_event_work struct is allocated, but only freed in a single case.
Move the allocation to the branch where it is actually needed, and free
it after the work has been done.

Fixes: 03e1d93e0779 ("realtek: add driver support for routing offload")
Signed-off-by: Jan Hoffmann <jan@3e8.eu>
target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/common.c
target/linux/realtek/files-5.15/drivers/net/dsa/rtl83xx/common.c

index 15e6ed0926964c458a40ee93a814bc8404ae8e4a..d2d677230010671e13e598e3d2165de7caf97231 100644 (file)
@@ -1286,6 +1286,8 @@ static void rtl83xx_net_event_work_do(struct work_struct *work)
        struct rtl838x_switch_priv *priv = net_work->priv;
 
        rtl83xx_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac);
+
+       kfree(net_work);
 }
 
 static int rtl83xx_netevent_event(struct notifier_block *this,
@@ -1299,13 +1301,6 @@ static int rtl83xx_netevent_event(struct notifier_block *this,
 
        priv = container_of(this, struct rtl838x_switch_priv, ne_nb);
 
-       net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
-       if (!net_work)
-               return NOTIFY_BAD;
-
-       INIT_WORK(&net_work->work, rtl83xx_net_event_work_do);
-       net_work->priv = priv;
-
        switch (event) {
        case NETEVENT_NEIGH_UPDATE:
                if (n->tbl != &arp_tbl)
@@ -1314,10 +1309,16 @@ static int rtl83xx_netevent_event(struct notifier_block *this,
                port = rtl83xx_port_dev_lower_find(dev, priv);
                if (port < 0 || !(n->nud_state & NUD_VALID)) {
                        pr_debug("%s: Neigbour invalid, not updating\n", __func__);
-                       kfree(net_work);
                        return NOTIFY_DONE;
                }
 
+               net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
+               if (!net_work)
+                       return NOTIFY_BAD;
+
+               INIT_WORK(&net_work->work, rtl83xx_net_event_work_do);
+               net_work->priv = priv;
+
                net_work->mac = ether_addr_to_u64(n->ha);
                net_work->gw_addr = *(__be32 *) n->primary_key;
 
index 1fa92ae220e048e6d0136f40c54ee375a804c802..3216d7eb835f1f38ea3b656f65d5099dd430ad02 100644 (file)
@@ -1282,6 +1282,8 @@ static void rtl83xx_net_event_work_do(struct work_struct *work)
        struct rtl838x_switch_priv *priv = net_work->priv;
 
        rtl83xx_l3_nexthop_update(priv, net_work->gw_addr, net_work->mac);
+
+       kfree(net_work);
 }
 
 static int rtl83xx_netevent_event(struct notifier_block *this,
@@ -1295,13 +1297,6 @@ static int rtl83xx_netevent_event(struct notifier_block *this,
 
        priv = container_of(this, struct rtl838x_switch_priv, ne_nb);
 
-       net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
-       if (!net_work)
-               return NOTIFY_BAD;
-
-       INIT_WORK(&net_work->work, rtl83xx_net_event_work_do);
-       net_work->priv = priv;
-
        switch (event) {
        case NETEVENT_NEIGH_UPDATE:
                if (n->tbl != &arp_tbl)
@@ -1310,10 +1305,16 @@ static int rtl83xx_netevent_event(struct notifier_block *this,
                port = rtl83xx_port_dev_lower_find(dev, priv);
                if (port < 0 || !(n->nud_state & NUD_VALID)) {
                        pr_debug("%s: Neigbour invalid, not updating\n", __func__);
-                       kfree(net_work);
                        return NOTIFY_DONE;
                }
 
+               net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC);
+               if (!net_work)
+                       return NOTIFY_BAD;
+
+               INIT_WORK(&net_work->work, rtl83xx_net_event_work_do);
+               net_work->priv = priv;
+
                net_work->mac = ether_addr_to_u64(n->ha);
                net_work->gw_addr = *(__be32 *) n->primary_key;