From 290834df69556b903b49f2a45671cc62b44f13bb Mon Sep 17 00:00:00 2001 From: Beniamino Galvani Date: Fri, 28 Apr 2017 17:59:30 +0200 Subject: [PATCH] nl80211: Fix race condition in detecting MAC change Commit 3e0272ca00ce1df35b45e7d739dd7e935f13fd84 ('nl80211: Re-read MAC address on RTM_NEWLINK') added the detection of external changes to MAC address when the interface is brought up. If the interface state is changed quickly enough, wpa_supplicant may receive the netlink message for the !IFF_UP event when the interface has already been brought up and would ignore the next netlink IFF_UP message, missing the MAC change. Fix this by also reloading the MAC address when a !IFF_UP event is received with the interface up, because this implies that the interface went down and up again, possibly changing the address. Signed-off-by: Beniamino Galvani --- src/drivers/driver_nl80211.c | 47 +++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index af1cb84..24fad29 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -933,6 +933,30 @@ nl80211_find_drv(struct nl80211_global *global, int idx, u8 *buf, size_t len) } +static void nl80211_refresh_mac(struct wpa_driver_nl80211_data *drv, + int ifindex) +{ + struct i802_bss *bss; + u8 addr[ETH_ALEN]; + + bss = get_bss_ifindex(drv, ifindex); + if (bss && + linux_get_ifhwaddr(drv->global->ioctl_sock, + bss->ifname, addr) < 0) { + wpa_printf(MSG_DEBUG, + "nl80211: %s: failed to re-read MAC address", + bss->ifname); + } else if (bss && os_memcmp(addr, bss->addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, + "nl80211: Own MAC address on ifindex %d (%s) changed from " + MACSTR " to " MACSTR, + ifindex, bss->ifname, + MAC2STR(bss->addr), MAC2STR(addr)); + os_memcpy(bss->addr, addr, ETH_ALEN); + } +} + + static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, struct ifinfomsg *ifi, u8 *buf, size_t len) @@ -997,6 +1021,8 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, namebuf[0] = '\0'; if (if_indextoname(ifi->ifi_index, namebuf) && linux_iface_up(drv->global->ioctl_sock, namebuf) > 0) { + /* Re-read MAC address as it may have changed */ + nl80211_refresh_mac(drv, ifi->ifi_index); wpa_printf(MSG_DEBUG, "nl80211: Ignore interface down " "event since interface %s is up", namebuf); drv->ignore_if_down_event = 0; @@ -1044,27 +1070,8 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, "event since interface %s is marked " "removed", drv->first_bss->ifname); } else { - struct i802_bss *bss; - u8 addr[ETH_ALEN]; - /* Re-read MAC address as it may have changed */ - bss = get_bss_ifindex(drv, ifi->ifi_index); - if (bss && - linux_get_ifhwaddr(drv->global->ioctl_sock, - bss->ifname, addr) < 0) { - wpa_printf(MSG_DEBUG, - "nl80211: %s: failed to re-read MAC address", - bss->ifname); - } else if (bss && - os_memcmp(addr, bss->addr, ETH_ALEN) != 0) { - wpa_printf(MSG_DEBUG, - "nl80211: Own MAC address on ifindex %d (%s) changed from " - MACSTR " to " MACSTR, - ifi->ifi_index, bss->ifname, - MAC2STR(bss->addr), - MAC2STR(addr)); - os_memcpy(bss->addr, addr, ETH_ALEN); - } + nl80211_refresh_mac(drv, ifi->ifi_index); wpa_printf(MSG_DEBUG, "nl80211: Interface up"); drv->if_disabled = 0; -- 2.9.3