Re: slaacd(8): prevent crash when interface disappears

2021-11-28 Thread Florian Obser
On 2021-11-28 05:13 UTC, Klemens Nanni  wrote:
> On Thu, Nov 18, 2021 at 09:02:00AM +0100, Florian Obser wrote:
>> This might be the crash kn@ was seeing once in a blue moon.
>
> I somewhat doubt it, since slaacd crashed on my notebook using trunk(4)
> over em(4) and athn(4), none of these interface get destroyed.
>
> I toggle the autoconf, set IPs, etc. but once trunk0 has its interface
> index, it'll stay the same until reboot.

Oh, but this is not just about autoconf interfaces, it's about *all*
interfaces. Look at the RTM_NEWADDR case in handle_route_message().

If it gets a NULL if_name for *any* interface it happily passes this to
update_iface() -> get_flags() -> strlcpy -> boom. It doesn't yet know if
it's an autoconf interface, it currently tries to figure that out.

You can probably crash slaacd like this:

while :; do ifconfig vether0 inet 2001:db8::23/64; ifconfig vether0 destroy; 
done

The route socket is restricted to AF_INET6, so you need to fiddle around
with IPv6 addresses...

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



Re: slaacd(8): prevent crash when interface disappears

2021-11-28 Thread Klemens Nanni
On Thu, Nov 18, 2021 at 09:02:00AM +0100, Florian Obser wrote:
> 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 
> Date:   Wed Nov 17 20:13:55 2021 +0100
> 
> normalize if_index handling in route messages

OK kn

> commit e8882f2329db1789914358c1c6b56ddec74fc35f
> Author: Florian Obser 
> 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.

OK kn

> This might be the crash kn@ was seeing once in a blue moon.

I somewhat doubt it, since slaacd crashed on my notebook using trunk(4)
over em(4) and athn(4), none of these interface get destroyed.

I toggle the autoconf, set IPs, etc. but once trunk0 has its interface
index, it'll stay the same until reboot.



Re: slaacd(8): prevent crash when interface disappears

2021-11-27 Thread Florian Obser
anyone?

On 2021-11-18 09:02 +01, Florian Obser  wrote:
> 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 
> 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,
>   _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, _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, _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(_addr.addr, rti_info[RTAX_IFA], sizeof(
>   del_addr.addr));
>   frontend_imsg_compose_engine(IMSG_DEL_ADDRESS,
>   0, 0, _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 

slaacd(8): prevent crash when interface disappears

2021-11-18 Thread Florian Obser
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 
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,
_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, _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, _index, sizeof(if_index));
-   remove_iface(if_index);
-   } else {
-   update_iface(ifm->ifm_index, if_name);
+   update_iface(if_index, if_name);
 #ifndefSMALL
-   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(_addr.addr, rti_info[RTAX_IFA], sizeof(
del_addr.addr));
frontend_imsg_compose_engine(IMSG_DEL_ADDRESS,
0, 0, _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