Commit 478622e8 authored by Helmut Schaa's avatar Helmut Schaa Committed by Johannes Berg

mac80211: reject setting masked mac addresses

If a driver registers an address mask we should ensure that no
interface gets an address assigned that isn't covered by the
registered address mask. This prevents invalid configurations
from reaching the device and causing problems.
Signed-off-by: default avatarHelmut Schaa <helmut.schaa@googlemail.com>
[change function flow to reduce indentation, fix locking]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0624760c
...@@ -223,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) ...@@ -223,6 +223,47 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
return 0; return 0;
} }
static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
{
struct ieee80211_sub_if_data *sdata;
u64 new, mask, tmp;
u8 *m;
int ret = 0;
if (is_zero_ether_addr(local->hw.wiphy->addr_mask))
return 0;
m = addr;
new = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
m = local->hw.wiphy->addr_mask;
mask = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
continue;
m = sdata->vif.addr;
tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
if ((new & ~mask) != (tmp & ~mask)) {
ret = -EINVAL;
break;
}
}
mutex_unlock(&local->iflist_mtx);
return ret;
}
static int ieee80211_change_mac(struct net_device *dev, void *addr) static int ieee80211_change_mac(struct net_device *dev, void *addr)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
...@@ -232,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) ...@@ -232,6 +273,10 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
if (ieee80211_sdata_running(sdata)) if (ieee80211_sdata_running(sdata))
return -EBUSY; return -EBUSY;
ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
if (ret)
return ret;
ret = eth_mac_addr(dev, sa); ret = eth_mac_addr(dev, sa);
if (ret == 0) if (ret == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment