From 475219144ab390c53fecc1365a2b1509ab4aecad Mon Sep 17 00:00:00 2001 From: wangchen Date: Fri, 23 Aug 2024 11:41:55 +0800 Subject: [PATCH] devif:fix issue about devif_callback being released wrongly,resulting in no access to it Signed-off-by: wangchen --- net/devif/devif.h | 1 + net/devif/devif_callback.c | 92 ++++++++++++++++++++++++++------------ 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/net/devif/devif.h b/net/devif/devif.h index dafcc8ebab24e..d76a881be9129 100644 --- a/net/devif/devif.h +++ b/net/devif/devif.h @@ -272,6 +272,7 @@ struct devif_callback_s FAR devif_callback_event_t event; FAR void *priv; uint16_t flags; + uint8_t free_flags; }; /**************************************************************************** diff --git a/net/devif/devif_callback.c b/net/devif/devif_callback.c index dc3bf13dad7cb..59f13c5d32133 100644 --- a/net/devif/devif_callback.c +++ b/net/devif/devif_callback.c @@ -39,6 +39,13 @@ #include "netdev/netdev.h" #include "devif/devif.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define DEVIF_CB_DONT_FREE (1 << 0) +#define DEVIF_CB_PEND_FREE (1 << 1) + /**************************************************************************** * Private Data ****************************************************************************/ @@ -88,35 +95,6 @@ static void devif_callback_free(FAR struct net_driver_s *dev, } #endif - /* Remove the callback structure from the device notification list if - * it is supposed to be in the device notification list. - */ - - if (dev != NULL) - { - /* Find the callback structure in the device event list */ - - for (prev = NULL, curr = dev->d_devcb; - curr != NULL && curr != cb; - prev = curr, curr = curr->nxtdev) - { - } - - /* Remove the structure from the device event list */ - - if (curr != NULL) - { - if (prev) - { - prev->nxtdev = cb->nxtdev; - } - else - { - dev->d_devcb = cb->nxtdev; - } - } - } - /* Remove the callback structure from the data notification list if * it is supposed to be in the data notification list. */ @@ -165,6 +143,48 @@ static void devif_callback_free(FAR struct net_driver_s *dev, } } + /* check if the callback structure has DEVIF_CB_DONT_FREE,it indicates + * the callback can't be free immediately,setting DEVIF_CB_PEND_FREE + * flag with the callback,it indicates the callback will be free + * finally + */ + + if (cb->free_flags & DEVIF_CB_DONT_FREE) + { + cb->free_flags |= DEVIF_CB_PEND_FREE; + net_unlock(); + return; + } + + /* Remove the callback structure from the device notification list if + * it is supposed to be in the device notification list. + */ + + if (dev != NULL) + { + /* Find the callback structure in the device event list */ + + for (prev = NULL, curr = dev->d_devcb; + curr != NULL && curr != cb; + prev = curr, curr = curr->nxtdev) + { + } + + /* Remove the structure from the device event list */ + + if (curr != NULL) + { + if (prev) + { + prev->nxtdev = cb->nxtdev; + } + else + { + dev->d_devcb = cb->nxtdev; + } + } + } + /* If this is a preallocated or a batch allocated callback store it in * the free callbacks list. Else free it. */ @@ -572,12 +592,26 @@ uint16_t devif_dev_event(FAR struct net_driver_s *dev, uint16_t flags) if (cb->event != NULL && devif_event_trigger(flags, cb->flags)) { + cb->free_flags |= DEVIF_CB_DONT_FREE; + /* Yes.. perform the callback. Actions perform by the callback * may delete the current list entry or add a new list entry to * beginning of the list (which will be ignored on this pass) */ flags = cb->event(dev, cb->priv, flags); + cb->free_flags &= ~DEVIF_CB_DONT_FREE; + + /* update the next callback to prevent previously recorded the + * next callback from being deleted + */ + + next = cb->nxtdev; + if ((cb->free_flags & DEVIF_CB_PEND_FREE) != 0) + { + cb->free_flags &= ~DEVIF_CB_PEND_FREE; + devif_callback_free(dev, cb, NULL, NULL); + } } }