Hi,

If rt_ifa_addlocal() in in_ifinit() fails, the address has been
added to the interface address list, but the local route is missing.
This inconsistency can result in a panic later.

panic: kernel diagnostic assertion "ifa == rt->rt_ifa" failed: file 
"/crypt/home/bluhm/openbsd/cvs/src/sys/netinet/if_ether.c", line 206

I have seen this crash in production on a 5.9 system and could
reproduce it on -current by inducing an error in rt_ifa_addlocal().

So in case of an error, remove the interface address to get a
consistent state again.

ok?

bluhm

Index: netinet/in.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/in.c,v
retrieving revision 1.130
diff -u -p -u -p -r1.130 in.c
--- netinet/in.c        5 Dec 2016 15:31:43 -0000       1.130
+++ netinet/in.c        17 Dec 2016 01:27:30 -0000
@@ -603,7 +603,7 @@ in_ifinit(struct ifnet *ifp, struct in_i
 {
        u_int32_t i = sin->sin_addr.s_addr;
        struct sockaddr_in oldaddr;
-       int error = 0;
+       int error = 0, rterror;
 
        splsoftassert(IPL_SOFTNET);
 
@@ -633,10 +633,16 @@ in_ifinit(struct ifnet *ifp, struct in_i
         * error occured, put back the original address.
         */
        ifa_add(ifp, &ia->ia_ifa);
-       rt_ifa_addlocal(&ia->ia_ifa);
+       rterror = rt_ifa_addlocal(&ia->ia_ifa);
 
        if (error)
                goto out;
+       if (rterror) {
+               if (!newaddr)
+                       ifa_del(ifp, &ia->ia_ifa);
+               error = rterror;
+               goto out;
+       }
 
        if (ia->ia_netmask == 0) {
                if (IN_CLASSA(i))

Reply via email to