eapol: Work around an apparent GCC 8.3 bug

With GCC 8.3 on Rasberry Pi, iwd sends invalid EAPoL 1_of_4 packets:

< PAE: len 99                                                          8.785095
    Interface Index: 27
    EAPoL: len 99
        Protocol Version: 2 (802.1X-2004)
        Type: 3 (Key)
        Length: 95
        Checking mic len 16
        Frame len 99
        key data len 22
        Checking mic len 24
        Frame len 107
        Bad MIC len, malformed packet?
        02 03 00 5f 02 00 8a 00 10 00 00 00 00 00 00 00  ..._............
        02 94 40 a3 da c3 2b aa b7 a6 a5 5f 25 0a ae 74  ..@...+...._%..t
        b0 8d e2 62 9c 90 c9 e9 fd a5 33 1b e1 b4 9b 81  ...b......3.....
        42 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  B...............
        00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
        00 00 16

The trouble seems to be that eapol_key_data_append() correctly sets the
key_data_length field (the last 2 bytes of the message), but the actual
packet_length is not being set properly.

Dropping to O0 optimization level results in GCC correctly computing
the packet length.
This commit is contained in:
Denis Kenzior 2021-04-07 16:47:40 -05:00
parent 5b4a7fc377
commit 3284ed4e8e
1 changed files with 15 additions and 0 deletions

View File

@ -1025,6 +1025,17 @@ static void eapol_set_key_timeout(struct eapol_sm *sm,
}
}
/*
* GCC version 8.3 seems to have trouble correctly calculating
* ek->header.packet_len when optimization is enabled. This results in iwd
* sending invalid 1_of_4 packets (with the KDE payload missing). Work
* around this by dropping to O0 for this function when old GCC versions
* are used
*/
#if __GNUC__ < 9
#pragma GCC optimize ("O0")
#endif
/* 802.11-2016 Section 12.7.6.2 */
static void eapol_send_ptk_1_of_4(struct eapol_sm *sm)
{
@ -1068,6 +1079,10 @@ static void eapol_send_ptk_1_of_4(struct eapol_sm *sm)
eapol_sm_write(sm, (struct eapol_frame *) ek, false);
}
#if __GNUC__ < 9
#pragma GCC reset_options
#endif
static void eapol_ptk_1_of_4_retry(struct l_timeout *timeout, void *user_data)
{
struct eapol_sm *sm = user_data;