Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/net fix interface address list traversal in if_detach():



details:   https://anonhg.NetBSD.org/src/rev/13ab9b710374
branches:  trunk
changeset: 555217:13ab9b710374
user:      drochner <drochner%NetBSD.org@localhost>
date:      Tue Nov 11 20:33:46 2003 +0000

description:
fix interface address list traversal in if_detach():
The code was assuming that interface addresses are removed one-by-one.
With IPv6 and multicasts, removal of one address can remove other
addresses as side effect, which caused accesses of free()d memory.

diffstat:

 sys/net/if.c |  15 +++++++++------
 1 files changed, 9 insertions(+), 6 deletions(-)

diffs (58 lines):

diff -r 15b704ca0507 -r 13ab9b710374 sys/net/if.c
--- a/sys/net/if.c      Tue Nov 11 20:25:26 2003 +0000
+++ b/sys/net/if.c      Tue Nov 11 20:33:46 2003 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if.c,v 1.133 2003/11/10 20:03:29 jonathan Exp $        */
+/*     $NetBSD: if.c,v 1.134 2003/11/11 20:33:46 drochner Exp $        */
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.133 2003/11/10 20:03:29 jonathan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.134 2003/11/11 20:33:46 drochner Exp $");
 
 #include "opt_inet.h"
 
@@ -544,7 +544,7 @@
        struct ifnet *ifp;
 {
        struct socket so;
-       struct ifaddr *ifa, *next;
+       struct ifaddr *ifa, **ifap;
 #ifdef IFAREF_DEBUG
        struct ifaddr *last_ifa = NULL;
 #endif
@@ -581,8 +581,8 @@
         * Rip all the addresses off the interface.  This should make
         * all of the routes go away.
         */
-       for (ifa = TAILQ_FIRST(&ifp->if_addrlist); ifa; ifa = next) {
-               next = TAILQ_NEXT(ifa, ifa_list);
+       ifap = &TAILQ_FIRST(&ifp->if_addrlist); /* XXX abstraction violation */
+       while ((ifa = *ifap)) {
                family = ifa->ifa_addr->sa_family;
 #ifdef IFAREF_DEBUG
                printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
@@ -591,8 +591,10 @@
                        panic("if_detach: loop detected");
                last_ifa = ifa;
 #endif
-               if (family == AF_LINK)
+               if (family == AF_LINK) {
+                       ifap = &TAILQ_NEXT(ifa, ifa_list);
                        continue;
+               }
                dp = pffinddomain(family);
 #ifdef DIAGNOSTIC
                if (dp == NULL)
@@ -617,6 +619,7 @@
                         */
                        printf("if_detach: WARNING: AF %d not purged\n",
                            family);
+                       TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
                }
        }
 



Home | Main Index | Thread Index | Old Index