Hi Vladimir,

> ic_close_dev contains a generalization of the logic to not close a
> network interface if it's the host port for a DSA switch. This logic is
> disguised behind an iteration through the lowers of ic_dev in
> ic_close_dev.
> 
> When no interface for ipconfig can be found, ic_dev is NULL, and
> ic_close_dev:
> - dereferences a NULL pointer when assigning selected_dev
> - would attempt to search through the lower interfaces of a NULL
>   net_device pointer
> 
> So we should protect against that case.
> 
> The "lower_dev" iterator variable was shortened to "lower" in order to
> keep the 80 character limit.
> 
> Fixes: f68cbaed67cb ("net: ipconfig: avoid use-after-free in ic_close_devs")
> Fixes: 46acf7bdbc72 ("Revert "net: ipv4: handle DSA enabled master network 
> devices"")
> Signed-off-by: Vladimir Oltean <vladimir.olt...@nxp.com>

Tested-by: Heiko Thiery <heiko.thi...@gmail.com>

> ---
>  net/ipv4/ipconfig.c | 14 ++++++++------
>  1 file changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
> index 47db1bfdaaa0..bc2f6ca97152 100644
> --- a/net/ipv4/ipconfig.c
> +++ b/net/ipv4/ipconfig.c
> @@ -309,7 +309,7 @@ static int __init ic_open_devs(void)
>   */
>  static void __init ic_close_devs(void)
>  {
> -     struct net_device *selected_dev = ic_dev->dev;
> +     struct net_device *selected_dev = ic_dev ? ic_dev->dev : NULL;
>       struct ic_device *d, *next;
>       struct net_device *dev;
>  
> @@ -317,16 +317,18 @@ static void __init ic_close_devs(void)
>       next = ic_first_dev;
>       while ((d = next)) {
>               bool bring_down = (d != ic_dev);
> -             struct net_device *lower_dev;
> +             struct net_device *lower;
>               struct list_head *iter;
>  
>               next = d->next;
>               dev = d->dev;
>  
> -             netdev_for_each_lower_dev(selected_dev, lower_dev, iter) {
> -                     if (dev == lower_dev) {
> -                             bring_down = false;
> -                             break;
> +             if (selected_dev) {
> +                     netdev_for_each_lower_dev(selected_dev, lower, iter) {
> +                             if (dev == lower) {
> +                                     bring_down = false;
> +                                     break;
> +                             }
>                       }
>               }
>               if (bring_down) {
> -- 
> 2.25.1


Thank you.

-- 
Heiko

Reply via email to