This is split in two for easier review and I also intend to commit it
like this.

The first diff shuffles setting of if_index around so that it's
available in all switch cases and uses it consistently instead of
ifm->ifm_index.

That way we can copy the if_name == NULL check into each case block
preventing crashes when an interface disappears at just the wrong
moment.

OK?

(btw. I found this because I transmogrified slaacd into gelatod and kn@
reported a crash while running in debug mode so I could spot what's
wrong with it. Much harder to find in slaacd...)

commit 2880598cb424e5d889ecdbf06d9d72d777b11569
Author: Florian Obser <flor...@narrans.de>
Date:   Wed Nov 17 20:13:55 2021 +0100

    normalize if_index handling in route messages

diff --git frontend.c frontend.c
index 72d7929c5df..29446c11e16 100644
--- frontend.c
+++ frontend.c
@@ -793,30 +793,28 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
        switch (rtm->rtm_type) {
        case RTM_IFINFO:
                ifm = (struct if_msghdr *)rtm;
-               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
+               if_index = ifm->ifm_index;
+               if_name = if_indextoname(if_index, ifnamebuf);
                if (if_name == NULL) {
-                       log_debug("RTM_IFINFO: lost if %d", ifm->ifm_index);
-                       if_index = ifm->ifm_index;
+                       log_debug("RTM_IFINFO: lost if %d", if_index);
                        frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0,
                            &if_index, sizeof(if_index));
                        remove_iface(if_index);
+                       break;
+               }
+               xflags = get_xflags(if_name);
+               if (xflags == -1 || !(xflags & (IFXF_AUTOCONF6 |
+                   IFXF_AUTOCONF6TEMP))) {
+                       log_debug("RTM_IFINFO: %s(%d) no(longer) autoconf6", 
if_name,
+                           if_index);
+                       frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
+                           0, &if_index, sizeof(if_index));
+                       remove_iface(if_index);
                } else {
-                       xflags = get_xflags(if_name);
-                       if (xflags == -1 || !(xflags & (IFXF_AUTOCONF6 |
-                           IFXF_AUTOCONF6TEMP))) {
-                               log_debug("RTM_IFINFO: %s(%d) no(longer) "
-                                  "autoconf6", if_name, ifm->ifm_index);
-                               if_index = ifm->ifm_index;
-                               frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0,
-                                   0, &if_index, sizeof(if_index));
-                               remove_iface(if_index);
-                       } else {
-                               update_iface(ifm->ifm_index, if_name);
+                       update_iface(if_index, if_name);
 #ifndef        SMALL
-                               update_autoconf_addresses(ifm->ifm_index,
-                                   if_name);
+                       update_autoconf_addresses(if_index, if_name);
 #endif /* SMALL */
-                       }
                }
                break;
        case RTM_IFANNOUNCE:
@@ -830,27 +828,29 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                break;
        case RTM_NEWADDR:
                ifm = (struct if_msghdr *)rtm;
-               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
-               log_debug("RTM_NEWADDR: %s[%u]", if_name, ifm->ifm_index);
-               update_iface(ifm->ifm_index, if_name);
+               if_index = ifm->ifm_index;
+               if_name = if_indextoname(if_index, ifnamebuf);
+               log_debug("RTM_NEWADDR: %s[%u]", if_name, if_index);
+               update_iface(if_index, if_name);
                break;
        case RTM_DELADDR:
                ifm = (struct if_msghdr *)rtm;
-               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
+               if_index = ifm->ifm_index;
+               if_name = if_indextoname(if_index, ifnamebuf);
                if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family
                    == AF_INET6) {
-                       del_addr.if_index = ifm->ifm_index;
+                       del_addr.if_index = if_index;
                        memcpy(&del_addr.addr, rti_info[RTAX_IFA], sizeof(
                            del_addr.addr));
                        frontend_imsg_compose_engine(IMSG_DEL_ADDRESS,
                                    0, 0, &del_addr, sizeof(del_addr));
-                       log_debug("RTM_DELADDR: %s[%u]", if_name,
-                           ifm->ifm_index);
+                       log_debug("RTM_DELADDR: %s[%u]", if_name, if_index);
                }
                break;
        case RTM_CHGADDRATTR:
                ifm = (struct if_msghdr *)rtm;
-               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
+               if_index = ifm->ifm_index;
+               if_name = if_indextoname(if_index, ifnamebuf);
                if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family
                    == AF_INET6) {
                        sin6 = (struct sockaddr_in6 *) rti_info[RTAX_IFA];
@@ -869,13 +869,13 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                        }
 
 #ifndef        SMALL
-                       log_debug("RTM_CHGADDRATTR: %s -%s",
+                       log_debug("RTM_CHGADDRATTR: %s - %s",
                            sin6_to_str(sin6),
                            flags_to_str(ifr6.ifr_ifru.ifru_flags6));
 #endif /* SMALL */
 
                        if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DUPLICATED) {
-                               dup_addr.if_index = ifm->ifm_index;
+                               dup_addr.if_index = if_index;
                                dup_addr.addr = *sin6;
                                frontend_imsg_compose_engine(IMSG_DUP_ADDRESS,
                                    0, 0, &dup_addr, sizeof(dup_addr));
@@ -902,10 +902,10 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                rl = (struct sockaddr_rtlabel *)rti_info[RTAX_LABEL];
                if (strcmp(rl->sr_label, SLAACD_RTA_LABEL) != 0)
                        break;
+               if_index = ifm->ifm_index;
+               if_name = if_indextoname(if_index, ifnamebuf);
 
-               if_name = if_indextoname(ifm->ifm_index, ifnamebuf);
-
-               del_route.if_index = ifm->ifm_index;
+               del_route.if_index = if_index;
                memcpy(&del_route.gw, rti_info[RTAX_GATEWAY],
                    sizeof(del_route.gw));
                in6 = &del_route.gw.sin6_addr;

commit e8882f2329db1789914358c1c6b56ddec74fc35f
Author: Florian Obser <flor...@narrans.de>
Date:   Wed Nov 17 20:17:29 2021 +0100

    Make sure the interface still exists before updating it.
    
    When we get a route message, for example an address being added
    (RTM_NEWADDR, but the problem exists with most of the route messages)
    and the interface gets unplugged at just the right moment
    if_nametoindex(3) will return NULL. We will pass NULL through
    update_iface() to get_xflags() which will then crash because we
    dereference the NULL pointer there.
    
    This might be the crash kn@ was seeing once in a blue moon.

diff --git frontend.c frontend.c
index 29446c11e16..329f93c39ae 100644
--- frontend.c
+++ frontend.c
@@ -830,6 +830,14 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                ifm = (struct if_msghdr *)rtm;
                if_index = ifm->ifm_index;
                if_name = if_indextoname(if_index, ifnamebuf);
+               if (if_name == NULL) {
+                       log_debug("RTM_NEWADDR: lost if %d", if_index);
+                       frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0,
+                           &if_index, sizeof(if_index));
+                       remove_iface(if_index);
+                       break;
+               }
+
                log_debug("RTM_NEWADDR: %s[%u]", if_name, if_index);
                update_iface(if_index, if_name);
                break;
@@ -837,6 +845,13 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                ifm = (struct if_msghdr *)rtm;
                if_index = ifm->ifm_index;
                if_name = if_indextoname(if_index, ifnamebuf);
+               if (if_name == NULL) {
+                       log_debug("RTM_DELADDR: lost if %d", if_index);
+                       frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0,
+                           &if_index, sizeof(if_index));
+                       remove_iface(if_index);
+                       break;
+               }
                if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family
                    == AF_INET6) {
                        del_addr.if_index = if_index;
@@ -851,6 +866,13 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                ifm = (struct if_msghdr *)rtm;
                if_index = ifm->ifm_index;
                if_name = if_indextoname(if_index, ifnamebuf);
+               if (if_name == NULL) {
+                       log_debug("RTM_CHGADDRATTR: lost if %d", if_index);
+                       frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0,
+                           &if_index, sizeof(if_index));
+                       remove_iface(if_index);
+                       break;
+               }
                if (rtm->rtm_addrs & RTA_IFA && rti_info[RTAX_IFA]->sa_family
                    == AF_INET6) {
                        sin6 = (struct sockaddr_in6 *) rti_info[RTAX_IFA];
@@ -904,6 +926,13 @@ handle_route_message(struct rt_msghdr *rtm, struct 
sockaddr **rti_info)
                        break;
                if_index = ifm->ifm_index;
                if_name = if_indextoname(if_index, ifnamebuf);
+               if (if_name == NULL) {
+                       log_debug("RTM_DELETE: lost if %d", if_index);
+                       frontend_imsg_compose_engine(IMSG_REMOVE_IF, 0, 0,
+                           &if_index, sizeof(if_index));
+                       remove_iface(if_index);
+                       break;
+               }
 
                del_route.if_index = if_index;
                memcpy(&del_route.gw, rti_info[RTAX_GATEWAY],

-- 
I'm not entirely sure you are real.

Reply via email to