2020-06-12 15:59:37

by Markus Theil

[permalink] [raw]
Subject: [PATCH v2 0/2] Fixes for 802.1X in mesh mode

In order to support 802.1X in mesh mode, userspace should be able
to rx and tx eapol frames, after an initial MPM, before a second AMPE.

Some checks regarding mesh forwarding were conflicting with this.
Therefore this little series adds some checks for control port frames
and disables mesh path lookups on the tx side or drop of unencrypted
frames on the rx side.

Markus Theil (2):
mac80211: skip mpath lookup also for control port tx
mac80211: allow rx of mesh eapol frames with default rx key

net/mac80211/rx.c | 27 +++++++++++++++++++++++++++
net/mac80211/tx.c | 13 ++++++++++---
2 files changed, 37 insertions(+), 3 deletions(-)

--
2.27.0


2020-06-12 15:59:37

by Markus Theil

[permalink] [raw]
Subject: [PATCH v2 2/2] mac80211: allow rx of mesh eapol frames with default rx key

Without this patch, eapol frames cannot be received in mesh
mode, when 802.1X should be used. Initially only a MGTK is
defined, which is found and set as rx->key, when there are
no other keys set. ieee80211_drop_unencrypted would then
drop these eapol frames, as they are data frames without
encryption and there exists some rx->key.

Fix this by differentiating between mesh eapol frames and
other data frames with existing rx->key. Allow mesh mesh
eapol frames only if they are for our vif address.

With this patch in-place, ieee80211_rx_h_mesh_fwding continues
after the ieee80211_drop_unencrypted check and notices, that
these eapol frames have to be delivered locally, as they should.

Signed-off-by: Markus Theil <[email protected]>
---
net/mac80211/rx.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 21854a61a2b7..e1368c99fa8f 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2396,6 +2396,7 @@ static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)

static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct sk_buff *skb = rx->skb;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);

@@ -2406,12 +2407,36 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
if (status->flag & RX_FLAG_DECRYPTED)
return 0;

+ /* check mesh EAPOL frames first */
+ if (unlikely(rx->sta && ieee80211_vif_is_mesh(&rx->sdata->vif) && ieee80211_is_data(fc))) {
+ struct ieee80211s_hdr *mesh_hdr;
+ u16 hdr_len = ieee80211_hdrlen(fc);
+ u16 ethertype_offset;
+ __be16 ethertype;
+
+ /* make sure fixed part of mesh header is there, also checks skb len */
+ if (!pskb_may_pull(rx->skb, hdr_len + 6))
+ return -EACCES;
+
+ mesh_hdr = (struct ieee80211s_hdr *)(skb->data + hdr_len);
+ ethertype_offset = hdr_len + ieee80211_get_mesh_hdrlen(mesh_hdr)
+ + sizeof(rfc1042_header);
+ if (!pskb_may_pull(rx->skb, ethertype_offset + sizeof(ethertype)) ||
+ !ether_addr_equal(hdr->addr1, rx->sdata->vif.addr))
+ return -EACCES;
+
+ skb_copy_bits(rx->skb, ethertype_offset, &ethertype, 2);
+ if (ethertype == rx->sdata->control_port_protocol)
+ goto out;
+ }
+
/* Drop unencrypted frames if key is set. */
if (unlikely(!ieee80211_has_protected(fc) &&
!ieee80211_is_any_nullfunc(fc) &&
ieee80211_is_data(fc) && rx->key))
return -EACCES;

+out:
return 0;
}

--
2.27.0

2020-06-12 15:59:54

by Markus Theil

[permalink] [raw]
Subject: [PATCH v2 1/2] mac80211: skip mpath lookup also for control port tx

When using 802.1X over mesh networks, at first an ordinary
mesh peering is established, then the 802.1X EAPOL dialog
happens, afterwards an authenticated mesh peering exchange
(AMPE) happens, finally the peering is complete and we can
set the STA authorized flag.

As 802.1X is an intermediate step here and key material is
not yet exchanged for stations we have to skip mesh path lookup
for these EAPOL frames. Otherwise the already configure mesh
group encryption key would be used to send a mesh path request
which no one can decipher, because we didn't already establish
key material on both peers, like with SAE and directly using AMPE.

Signed-off-by: Markus Theil <[email protected]>
---
net/mac80211/tx.c | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e9ce658141f5..bd86f85a5b73 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3933,6 +3933,7 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
struct sk_buff *next;
+ u32 ctrl_flags_adapted;

if (unlikely(skb->len < ETH_HLEN)) {
kfree_skb(skb);
@@ -3996,8 +3997,12 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
skb_list_walk_safe(skb, skb, next) {
skb_mark_not_on_list(skb);

+ ctrl_flags_adapted = ctrl_flags;
+ if (sdata->control_port_protocol == skb->protocol)
+ ctrl_flags_adapted |= IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
+
skb = ieee80211_build_hdr(sdata, skb, info_flags,
- sta, ctrl_flags, cookie);
+ sta, ctrl_flags_adapted, cookie);
if (IS_ERR(skb)) {
kfree_skb_list(next);
goto out;
@@ -5370,8 +5375,10 @@ int ieee80211_tx_control_port(struct wiphy *wiphy, struct net_device *dev,
proto != cpu_to_be16(ETH_P_PREAUTH))
return -EINVAL;

- if (proto == sdata->control_port_protocol)
- ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO;
+ if (proto == sdata->control_port_protocol) {
+ ctrl_flags |= IEEE80211_TX_CTRL_PORT_CTRL_PROTO |
+ IEEE80211_TX_CTRL_SKIP_MPATH_LOOKUP;
+ }

if (unencrypted)
flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
--
2.27.0

2020-06-16 08:02:53

by Chen, Rong A

[permalink] [raw]
Subject: [mac80211] e073cf2b3e: hwsim.wpas_mesh_dynamic_interface_remove.fail

Greeting,

FYI, we noticed the following commit (built with gcc-9):

commit: e073cf2b3e0529efab7f0be441ebdcc45428f48d ("[PATCH v2 2/2] mac80211: allow rx of mesh eapol frames with default rx key")
url: https://github.com/0day-ci/linux/commits/Markus-Theil/Fixes-for-802-1X-in-mesh-mode/20200613-000022
base: https://git.kernel.org/cgit/linux/kernel/git/jberg/mac80211-next.git master

in testcase: hwsim
with following parameters:

group: hwsim-33



on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):




If you fix the issue, kindly add following tag
Reported-by: kernel test robot <[email protected]>




2020-06-14 18:00:19 ./run-tests.py wpas_mesh_dynamic_interface_remove
DEV: wlan0: 02:00:00:00:00:00
DEV: wlan1: 02:00:00:00:01:00
DEV: wlan2: 02:00:00:00:02:00
APDEV: wlan3
APDEV: wlan4
START wpas_mesh_dynamic_interface_remove 1/1
Test: wpa_supplicant mesh with dynamic interface and removal
mesh5 address 42:00:00:00:05:00
dev1->dev2 unicast data delivery failed
Traceback (most recent call last):
File "./run-tests.py", line 523, in main
t(dev)
File "/lkp/benchmarks/hwsim/tests/hwsim/test_wpas_mesh.py", line 789, in test_wpas_mesh_dynamic_interface_remove
check_mesh_joined_connected([wpas5, dev[0]], connectivity=True)
File "/lkp/benchmarks/hwsim/tests/hwsim/test_wpas_mesh.py", line 120, in check_mesh_joined_connected
check_mesh_connected2(dev, timeout0=timeout0, connectivity=connectivity)
File "/lkp/benchmarks/hwsim/tests/hwsim/test_wpas_mesh.py", line 116, in check_mesh_connected2
hwsim_utils.test_connectivity(dev[0], dev[1])
File "/lkp/benchmarks/hwsim/tests/hwsim/hwsim_utils.py", line 195, in test_connectivity
raise Exception(last_err)
Exception: dev1->dev2 unicast data delivery failed
FAIL wpas_mesh_dynamic_interface_remove 6.713899 2020-06-14 18:00:26.839319
passed 0 test case(s)
skipped 0 test case(s)
failed tests: wpas_mesh_dynamic_interface_remove



To reproduce:

# build kernel
cd linux
cp config-5.7.0-rc6-02487-ge073cf2b3e052 .config
make HOSTCC=gcc-9 CC=gcc-9 ARCH=x86_64 olddefconfig prepare modules_prepare bzImage

git clone https://github.com/intel/lkp-tests.git
cd lkp-tests
bin/lkp qemu -k <bzImage> job-script # job-script is attached in this email



Thanks,
Rong Chen


Attachments:
(No filename) (2.42 kB)
config-5.7.0-rc6-02487-ge073cf2b3e052 (206.11 kB)
job-script (4.81 kB)
dmesg.xz (79.00 kB)
hwsim (46.05 kB)
Download all attachments