iwd not connecting on Raspberry Pi with Raspbian
by Patrick Häcker
Hello,
I try to get iwd running on a Raspberry Pi using a Raspbian kernel (5.4.59).
The needed kernel options should be added (https://github.com/raspberrypi/
linux/issues/3547), wpa_supplicant works, I compiled a kernel adding
CONFIG_KEY_DH_OPERATIONS (which was the only remaining complaint by iwd),
upgraded to iwd 1.8 but had no success.
Now I am running out of ideas what else to try. The (hopefully) relevant part
of iwd running in debug mode for 2.4 GHz:
> src/station.c:station_autoconnect_next() Considering autoconnecting to BSS
> '98:9b:cb:4b:b1:cc' with SSID: auenstein, freq: 2472, rank: 7090,
> strength: -5600
> src/station.c:station_enter_state() Old State: autoconnect_quick, new
> state: connecting
> src/station.c:station_netdev_event() Associating
> src/netdev.c:netdev_unicast_notify() Unicast notification 59
> src/netdev.c:netdev_mlme_notify() MLME notification Connect(46)
> src/netdev.c:netdev_connect_event()
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/wiphy.c:wiphy_reg_notify() Notification of command Reg Change(36)
> src/wiphy.c:wiphy_update_reg_domain() New reg domain country code for
> (global) is DE
> 4-Way handshake failed for ifindex: 3, reason: 15
> src/station.c:station_connect_cb() 3, result: 3
> src/station.c:station_disassociated() 3
> src/station.c:station_enter_state() Old State: connecting, new state:
> disconnected
And the same for 5.6 GHz with a different error:
> src/station.c:station_autoconnect_next() Considering autoconnecting to BSS
> '98:9b:cb:4b:b1:cd' with SSID: auenstein5G, freq: 5600, rank: 4592,
> strength: -6500
> src/station.c:station_enter_state() Old State:
> autoconnect_quick, new state: connecting
> src/station.c:station_netdev_event() Associating
> src/netdev.c:netdev_unicast_notify() Unicast notification 59
> src/netdev.c:netdev_mlme_notify() MLME notification Connect(46)
> src/netdev.c:netdev_connect_event()
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/wiphy.c:wiphy_reg_notify() Notification of command Reg Change(36)
> src/wiphy.c:wiphy_update_reg_domain() New reg domain country code for
> (global) is DE
> src/netdev.c:netdev_link_notify() event 16 on ifindex 3
> src/netdev.c:netdev_mlme_notify() MLME notification Disconnect(48)
> src/netdev.c:netdev_disconnect_event()
> Received Deauthentication event, reason: 2, from_ap: false
> src/station.c:station_disconnect_event() 3
> src/station.c:station_disassociated() 3
> src/station.c:station_enter_state() Old State: connecting, new state:
> disconnected
I could imagine, that there is still a kernel module missing, but this is just
guessing. Any hints how to continue debugging?
I still think that iwd would be a good match for the Raspberry Pi and ideally
after this issue is fixed most Raspberry Pi user can switch to iwd if they
like.
Kind regards
Patrick
1 year, 8 months
[PATCH v3 00/15] Test Runner rewrite
by James Prestwood
*-v3:
* Fixed rebase issue
James Prestwood (15):
auto-t: prepare autotests for test-runner re-write
auto-t: introduce pure python test-runner re-write
auto-t: hostapd.py: update to work with test-runner rewrite
auto-t: testutil.py: update to work with test-runner rewrite
auto-t: ofono.py: fix timeout cleanup and wait for service
auto-t: iwd.py: update to work with test-runner rewrite
auto-t: iwd.py: fix multiple timeout cleanup issues
auto-t: remove wiphy.py
auto-t: fix hidden network test
auto-t: fix testSAE autoconnect_test.py
auto-t: skip ofono tests if ofonod isn't running
auto-t: replace hard-coded interfaces
auto-t: remove device.wait_for_connected
tools: post test-runner rewrite cleanup
doc: update test runner docs
.gitignore | 1 -
Makefile.am | 7 -
.../{test.py => connection_test.py} | 0
.../testAP/{test.py => connection_test.py} | 9 +-
autotests/testAP/failure_test.py | 6 +-
autotests/testAPRoam/connection_test.py | 2 -
.../testBSSBlacklist/all_blacklisted_test.py | 4 -
autotests/testBSSBlacklist/bad_pass_test.py | 4 -
autotests/testBSSBlacklist/connection_test.py | 1 -
.../testBSSBlacklist/temp_blacklist_test.py | 4 -
.../connect_command_test.py | 42 +-
.../disconnect_by_ap_test.py | 4 +-
.../testEAP-AKA-ofono/connection_test.py | 4 +
.../connection_test.py | 4 +
autotests/testEAP-AKA/connection_test.py | 1 -
.../testEAP-PEAPv0-CryptoBinding/ISK_test.py | 1 -
.../NoISK_test.py | 1 -
.../testEAP-PEAPv0-CryptoBinding/main.conf | 2 -
autotests/testEAP-PWD/connection_test.py | 1 -
.../testEAP-SIM-ofono/connection_test.py | 4 +
autotests/testEAP-SIM/connection_test.py | 1 -
.../connection_test.py | 11 +-
.../testEAP-TTLS-CHAP/connection_test.py | 1 -
.../testEAP-TTLS-MSCHAP/connection_test.py | 1 -
autotests/testEAP-TTLS-PAP/connection_test.py | 1 -
autotests/testEAP-WPS-Frag/wps_frag_test.py | 4 +-
autotests/testEAP-WPS/four_digit_pin_test.py | 4 +-
autotests/testEAP-WPS/pin_test.py | 4 +-
autotests/testEAP-WPS/push_button_test.py | 5 +-
autotests/testFILS/fils_256_test.py | 1 -
autotests/testFILS/fils_384_test.py | 1 -
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 18 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
autotests/testHiddenNetworks/validation.py | 8 +-
autotests/testOWE/connection_test.py | 1 -
autotests/testOWE/renegotiate_test.py | 1 -
.../{test.py => connection_test.py} | 2 +-
.../testPreauth-roam/eaptls-preauth-1.conf | 3 +-
.../testPreauth-roam/eaptls-preauth-2.conf | 3 +-
.../{test.py => connection_test.py} | 0
autotests/testSAE/autoconnect_test.py | 15 +-
autotests/testSAE/clogging_test.py | 3 +-
autotests/testSAE/connection_test.py | 10 +-
autotests/testSAE/group_20_connection_test.py | 10 +-
.../testSAQuery-spoofing/connection_test.py | 2 +-
autotests/testSAQuery/connection_test.py | 2 +-
autotests/util/config.py | 6 +
autotests/util/hostapd.py | 57 +-
autotests/util/iwd.py | 124 +-
autotests/util/ofono.py | 25 +-
autotests/util/testutil.py | 7 +-
autotests/util/wiphy.py | 32 -
doc/test-runner.txt | 117 +-
tools/test-runner | 1246 +++++++++++++++++
59 files changed, 1456 insertions(+), 384 deletions(-)
rename autotests/testAP-no-support/{test.py => connection_test.py} (100%)
rename autotests/testAP/{test.py => connection_test.py} (94%)
delete mode 100644 autotests/testEAP-PEAPv0-CryptoBinding/main.conf
rename autotests/testFT-8021x-roam/{test.py => connection_test.py} (99%)
rename autotests/testFT-FILS-SHA256/{test.py => connection_test.py} (99%)
rename autotests/testFT-FILS-SHA384/{test.py => connection_test.py} (99%)
rename autotests/testFT-PSK-over-DS/{test.py => connection_test.py} (99%)
rename autotests/testFT-PSK-roam/{test.py => connection_test.py} (95%)
rename autotests/testFT-SAE-roam/{test.py => connection_test.py} (99%)
rename autotests/testHT-VHT/{test.py => connection_test.py} (98%)
rename autotests/testPreauth-roam/{test.py => connection_test.py} (98%)
rename autotests/testRSSIAgent/{test.py => connection_test.py} (100%)
create mode 100644 autotests/util/config.py
delete mode 100644 autotests/util/wiphy.py
create mode 100755 tools/test-runner
--
2.21.1
1 year, 8 months
[PATCH] ap: Pass extra IEs between mgmt frames and user
by Andrew Zaborowski
Allow passing user callbacks to add extra IEs to the AP's beacons and
other frames. I considered a few ways for the user to pass this data
without callbacks but so far this seems to be the easiest and most
versatile way. Unfortunately the config is no longer static in a way
that could be completely contained in an l_settings for example.
Similarly pass the string of IEs from STA association frames to the user
through the AP events. I dropped ap_event_station_added_data.rsn_ie
because that probably would have never been very useful and the RSN IE
is included in the IE array in any case.
---
src/ap.c | 59 +++++++++++++++++++++++++++++++++++++++++++++-----------
src/ap.h | 10 +++++++++-
2 files changed, 57 insertions(+), 12 deletions(-)
diff --git a/src/ap.c b/src/ap.c
index 1cee185c..3e3df5a8 100644
--- a/src/ap.c
+++ b/src/ap.c
@@ -88,6 +88,8 @@ struct sta_state {
struct l_uintset *rates;
uint32_t assoc_resp_cmd_id;
struct ap_state *ap;
+ uint8_t *assoc_ies;
+ size_t assoc_ies_len;
uint8_t *assoc_rsne;
struct eapol_sm *sm;
struct handshake_state *hs;
@@ -159,7 +161,7 @@ static void ap_sta_free(void *data)
struct ap_state *ap = sta->ap;
l_uintset_free(sta->rates);
- l_free(sta->assoc_rsne);
+ l_free(sta->assoc_ies);
if (sta->assoc_resp_cmd_id)
l_genl_family_cancel(ap->nl80211, sta->assoc_resp_cmd_id);
@@ -272,7 +274,8 @@ static void ap_new_rsna(struct sta_state *sta)
if (ap->event_func) {
struct ap_event_station_added_data event_data = {};
event_data.mac = sta->addr;
- event_data.rsn_ie = sta->assoc_rsne;
+ event_data.assoc_ies = sta->assoc_ies;
+ event_data.assoc_ies_len = sta->assoc_ies_len;
ap->event_func(AP_EVENT_STATION_ADDED, &event_data,
ap->user_data);
}
@@ -491,6 +494,12 @@ static size_t ap_build_beacon_pr_tail(struct ap_state *ap, bool pr,
len += wsc_ie_size;
l_free(wsc_ie);
+ if (ap->config->write_mgmt_frame_ies)
+ len += ap->config->write_mgmt_frame_ies(
+ pr ? MPDU_MANAGEMENT_SUBTYPE_PROBE_RESPONSE :
+ MPDU_MANAGEMENT_SUBTYPE_BEACON,
+ out_buf + len, ap->user_data);
+
return len;
}
@@ -505,7 +514,12 @@ static void ap_set_beacon_cb(struct l_genl_msg *msg, void *user_data)
static void ap_update_beacon(struct ap_state *ap)
{
struct l_genl_msg *cmd;
- uint8_t head[256], tail[256];
+ size_t extra_ies_len = ap->config->get_mgmt_frame_ies_len ?
+ ap->config->get_mgmt_frame_ies_len(
+ MPDU_MANAGEMENT_SUBTYPE_BEACON,
+ ap->user_data) : 0;
+ uint8_t head[256];
+ uint8_t tail[256 + extra_ies_len];
size_t head_len, tail_len;
uint64_t wdev_id = netdev_get_wdev_id(ap->netdev);
static const uint8_t bcast_addr[6] = {
@@ -1058,7 +1072,11 @@ static uint32_t ap_assoc_resp(struct ap_state *ap, struct sta_state *sta,
bool reassoc, l_genl_msg_func_t callback)
{
const uint8_t *addr = netdev_get_address(ap->netdev);
- uint8_t mpdu_buf[128];
+ size_t extra_ies_len = ap->config->get_mgmt_frame_ies_len ?
+ ap->config->get_mgmt_frame_ies_len(
+ MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_RESPONSE,
+ ap->user_data) : 0;
+ uint8_t mpdu_buf[128 + extra_ies_len];
struct mmpdu_header *mpdu = (void *) mpdu_buf;
struct mmpdu_association_response *resp;
size_t ies_len = 0;
@@ -1134,6 +1152,11 @@ static uint32_t ap_assoc_resp(struct ap_state *ap, struct sta_state *sta,
l_free(wsc_ie);
}
+ if (ap->config->write_mgmt_frame_ies)
+ ies_len += ap->config->write_mgmt_frame_ies(
+ MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_RESPONSE,
+ resp->ies + ies_len, ap->user_data);
+
send_frame:
return ap_send_mgmt_frame(ap, mpdu, resp->ies + ies_len - mpdu_buf,
true, callback, sta);
@@ -1335,6 +1358,8 @@ static void ap_assoc_reassoc(struct sta_state *sta, bool reassoc,
sta->wsc_v2 = wsc_req.version2;
event_data.mac = sta->addr;
+ event_data.assoc_ies = ies;
+ event_data.assoc_ies_len = ies_len;
ap->event_func(AP_EVENT_REGISTRATION_START, &event_data,
ap->user_data);
@@ -1384,13 +1409,16 @@ static void ap_assoc_reassoc(struct sta_state *sta, bool reassoc,
sta->rates = rates;
- if (sta->assoc_rsne)
- l_free(sta->assoc_rsne);
+ l_free(sta->assoc_ies);
- if (rsn)
- sta->assoc_rsne = l_memdup(rsn, rsn[1] + 2);
- else
+ if (rsn) {
+ sta->assoc_ies = l_memdup(ies, ies_len);
+ sta->assoc_ies_len = ies_len;
+ sta->assoc_rsne = sta->assoc_ies + (rsn - ies);
+ } else {
+ sta->assoc_ies = NULL;
sta->assoc_rsne = NULL;
+ }
sta->assoc_resp_cmd_id = ap_assoc_resp(ap, sta, sta->addr, 0, reassoc,
ap_success_assoc_resp_cb);
@@ -1635,7 +1663,11 @@ static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,
struct ie_tlv_iter iter;
const uint8_t *bssid = netdev_get_address(ap->netdev);
bool match = false;
- uint8_t resp[512];
+ size_t extra_ies_len = ap->config->get_mgmt_frame_ies_len ?
+ ap->config->get_mgmt_frame_ies_len(
+ MPDU_MANAGEMENT_SUBTYPE_PROBE_RESPONSE,
+ ap->user_data) : 0;
+ uint8_t resp[512 + extra_ies_len];
uint8_t *wsc_data;
ssize_t wsc_data_len;
@@ -1931,7 +1963,12 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
{
struct l_genl_msg *cmd;
- uint8_t head[256], tail[256];
+ size_t extra_ies_len = ap->config->get_mgmt_frame_ies_len ?
+ ap->config->get_mgmt_frame_ies_len(
+ MPDU_MANAGEMENT_SUBTYPE_BEACON,
+ ap->user_data) : 0;
+ uint8_t head[256];
+ uint8_t tail[256 + extra_ies_len];
size_t head_len, tail_len;
uint32_t dtim_period = 3;
diff --git a/src/ap.h b/src/ap.h
index cb5238d1..19b72a33 100644
--- a/src/ap.h
+++ b/src/ap.h
@@ -22,6 +22,7 @@
struct ap_state;
struct iovec;
+enum mpdu_management_subtype;
enum ap_event_type {
AP_EVENT_START_FAILED,
@@ -36,7 +37,8 @@ enum ap_event_type {
struct ap_event_station_added_data {
const uint8_t *mac;
- const uint8_t *rsn_ie;
+ const uint8_t *assoc_ies;
+ size_t assoc_ies_len;
};
struct ap_event_station_removed_data {
@@ -46,6 +48,8 @@ struct ap_event_station_removed_data {
struct ap_event_registration_start_data {
const uint8_t *mac;
+ const uint8_t *assoc_ies;
+ size_t assoc_ies_len;
};
struct ap_event_registration_success_data {
@@ -64,6 +68,10 @@ struct ap_config {
unsigned int authorized_macs_num;
char *wsc_name;
struct wsc_primary_device_type wsc_primary_device_type;
+ size_t (*get_mgmt_frame_ies_len)(enum mpdu_management_subtype type,
+ void *user_data);
+ size_t (*write_mgmt_frame_ies)(enum mpdu_management_subtype type,
+ uint8_t *out_buf, void *user_data);
bool no_cck_rates : 1;
};
--
2.25.1
1 year, 8 months
[PATCH v2 00/15] Test Runner rewrite
by James Prestwood
**-v2:
* Remove hwsim returning radio ID, and updated test-runner to track
ID internally.
James Prestwood (15):
auto-t: prepare autotests for test-runner re-write
auto-t: introduce pure python test-runner re-write
auto-t: hostapd.py: update to work with test-runner rewrite
auto-t: testutil.py: update to work with test-runner rewrite
auto-t: ofono.py: fix timeout cleanup and wait for service
auto-t: iwd.py: update to work with test-runner rewrite
auto-t: iwd.py: fix multiple timeout cleanup issues
auto-t: remove wiphy.py
auto-t: fix hidden network test
auto-t: fix testSAE autoconnect_test.py
auto-t: skip ofono tests if ofonod isn't running
auto-t: replace hard-coded interfaces
auto-t: remove device.wait_for_connected
tools: post test-runner rewrite cleanup
doc: update test runner docs
.gitignore | 1 -
Makefile.am | 7 -
.../{test.py => connection_test.py} | 0
.../testAP/{test.py => connection_test.py} | 9 +-
autotests/testAP/failure_test.py | 6 +-
autotests/testAPRoam/connection_test.py | 2 -
.../testBSSBlacklist/all_blacklisted_test.py | 4 -
autotests/testBSSBlacklist/bad_pass_test.py | 4 -
autotests/testBSSBlacklist/connection_test.py | 1 -
.../testBSSBlacklist/temp_blacklist_test.py | 4 -
.../connect_command_test.py | 42 +-
.../disconnect_by_ap_test.py | 4 +-
.../testEAP-AKA-ofono/connection_test.py | 4 +
.../connection_test.py | 4 +
autotests/testEAP-AKA/connection_test.py | 1 -
.../testEAP-PEAPv0-CryptoBinding/ISK_test.py | 1 -
.../NoISK_test.py | 1 -
.../testEAP-PEAPv0-CryptoBinding/main.conf | 2 -
autotests/testEAP-PWD/connection_test.py | 1 -
.../testEAP-SIM-ofono/connection_test.py | 4 +
autotests/testEAP-SIM/connection_test.py | 1 -
.../connection_test.py | 11 +-
.../testEAP-TTLS-CHAP/connection_test.py | 1 -
.../testEAP-TTLS-MSCHAP/connection_test.py | 1 -
autotests/testEAP-TTLS-PAP/connection_test.py | 1 -
autotests/testEAP-WPS-Frag/wps_frag_test.py | 4 +-
autotests/testEAP-WPS/four_digit_pin_test.py | 4 +-
autotests/testEAP-WPS/pin_test.py | 4 +-
autotests/testEAP-WPS/push_button_test.py | 5 +-
autotests/testFILS/fils_256_test.py | 1 -
autotests/testFILS/fils_384_test.py | 1 -
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 18 +-
.../{test.py => connection_test.py} | 2 +-
.../{test.py => connection_test.py} | 2 +-
autotests/testHiddenNetworks/validation.py | 8 +-
autotests/testOWE/connection_test.py | 1 -
autotests/testOWE/renegotiate_test.py | 1 -
.../{test.py => connection_test.py} | 2 +-
.../testPreauth-roam/eaptls-preauth-1.conf | 3 +-
.../testPreauth-roam/eaptls-preauth-2.conf | 3 +-
.../{test.py => connection_test.py} | 0
autotests/testSAE/autoconnect_test.py | 15 +-
autotests/testSAE/clogging_test.py | 3 +-
autotests/testSAE/connection_test.py | 10 +-
autotests/testSAE/group_20_connection_test.py | 10 +-
.../testSAQuery-spoofing/connection_test.py | 2 +-
autotests/testSAQuery/connection_test.py | 2 +-
autotests/util/config.py | 6 +
autotests/util/hostapd.py | 57 +-
autotests/util/iwd.py | 124 +-
autotests/util/ofono.py | 25 +-
autotests/util/testutil.py | 7 +-
autotests/util/wiphy.py | 32 -
doc/test-runner.txt | 117 +-
tools/test-runner | 1246 +++++++
tools/test-runner.c | 3310 -----------------
60 files changed, 1456 insertions(+), 3694 deletions(-)
rename autotests/testAP-no-support/{test.py => connection_test.py} (100%)
rename autotests/testAP/{test.py => connection_test.py} (94%)
delete mode 100644 autotests/testEAP-PEAPv0-CryptoBinding/main.conf
rename autotests/testFT-8021x-roam/{test.py => connection_test.py} (99%)
rename autotests/testFT-FILS-SHA256/{test.py => connection_test.py} (99%)
rename autotests/testFT-FILS-SHA384/{test.py => connection_test.py} (99%)
rename autotests/testFT-PSK-over-DS/{test.py => connection_test.py} (99%)
rename autotests/testFT-PSK-roam/{test.py => connection_test.py} (95%)
rename autotests/testFT-SAE-roam/{test.py => connection_test.py} (99%)
rename autotests/testHT-VHT/{test.py => connection_test.py} (98%)
rename autotests/testPreauth-roam/{test.py => connection_test.py} (98%)
rename autotests/testRSSIAgent/{test.py => connection_test.py} (100%)
create mode 100644 autotests/util/config.py
delete mode 100644 autotests/util/wiphy.py
create mode 100755 tools/test-runner
delete mode 100644 tools/test-runner.c
--
2.21.1
1 year, 8 months
[PATCH 1/8] wscutil: Use a utility for building authorized_macs
by Andrew Zaborowski
Add the wfa_build_authorized_macs function (wfa_ prefix following the
wfa_extract_ naming) and use it in wsc_build_probe_response. The logic
is changed slightly to treat the first 6-zeros address in the array as
the end of the array.
---
src/wscutil.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/src/wscutil.c b/src/wscutil.c
index d78a0354..f15cd215 100644
--- a/src/wscutil.c
+++ b/src/wscutil.c
@@ -2094,6 +2094,20 @@ static void build_wsc_state(struct wsc_attr_builder *builder,
wsc_attr_builder_put_u8(builder, 1); \
wsc_attr_builder_put_u8(builder, 0x20)
+static void wfa_build_authorized_macs(struct wsc_attr_builder *builder,
+ const uint8_t authorized_macs[static 30])
+{
+ int count;
+
+ for (count = 1; count < 5; count++)
+ if (util_mem_is_zero(authorized_macs + count * 6, 6))
+ break;
+
+ wsc_attr_builder_put_u8(builder, WSC_WFA_EXTENSION_AUTHORIZED_MACS);
+ wsc_attr_builder_put_u8(builder, count * 6);
+ wsc_attr_builder_put_bytes(builder, authorized_macs, count * 6);
+}
+
uint8_t *wsc_build_credential(const struct wsc_credential *in, size_t *out_len)
{
struct wsc_attr_builder *builder;
@@ -2204,21 +2218,9 @@ uint8_t *wsc_build_probe_response(
START_WFA_VENDOR_EXTENSION();
- if (!util_mem_is_zero(probe_response->authorized_macs, 30)) {
- int count;
-
- for (count = 1; count < 5; count++)
- if (util_mem_is_zero(probe_response->authorized_macs +
- count * 6, 30 - count * 6))
- break;
-
- wsc_attr_builder_put_u8(builder,
- WSC_WFA_EXTENSION_AUTHORIZED_MACS);
- wsc_attr_builder_put_u8(builder, count * 6);
- wsc_attr_builder_put_bytes(builder,
- probe_response->authorized_macs,
- count * 6);
- }
+ if (!util_mem_is_zero(probe_response->authorized_macs, 6))
+ wfa_build_authorized_macs(builder,
+ probe_response->authorized_macs);
if (probe_response->reg_config_methods) {
wsc_attr_builder_put_u8(builder,
--
2.25.1
1 year, 8 months
[PATCH 01/11] wscutil: Add wsc_build_beacon
by Andrew Zaborowski
---
src/wscutil.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/wscutil.h | 1 +
2 files changed, 60 insertions(+)
diff --git a/src/wscutil.c b/src/wscutil.c
index d78a0354..f24e67ed 100644
--- a/src/wscutil.c
+++ b/src/wscutil.c
@@ -2124,6 +2124,65 @@ static void build_credential(struct wsc_attr_builder *builder,
l_free(data);
}
+uint8_t *wsc_build_beacon(const struct wsc_beacon *beacon, size_t *out_len)
+{
+ struct wsc_attr_builder *builder;
+ uint8_t *ret;
+
+ builder = wsc_attr_builder_new(512);
+ build_version(builder, 0x10);
+ build_wsc_state(builder, beacon->state);
+
+ if (beacon->ap_setup_locked)
+ build_ap_setup_locked(builder, true);
+
+ if (beacon->selected_registrar) {
+ build_selected_registrar(builder, true);
+ build_device_password_id(builder, beacon->device_password_id);
+ build_selected_registrar_configuration_methods(builder,
+ beacon->selected_reg_config_methods);
+ }
+
+ /* These two "should be provided" if dual-band */
+ if (beacon->rf_bands & (beacon->rf_bands - 1)) {
+ if (beacon->selected_registrar)
+ build_uuid_e(builder, beacon->uuid_e);
+
+ build_rf_bands(builder, beacon->rf_bands);
+ }
+
+ if (!beacon->version2)
+ goto done;
+
+ START_WFA_VENDOR_EXTENSION();
+
+ if (!util_mem_is_zero(beacon->authorized_macs, 30)) {
+ int count;
+
+ for (count = 1; count < 5; count++)
+ if (util_mem_is_zero(beacon->authorized_macs + count * 6,
+ 30 - count * 6))
+ break;
+
+ wsc_attr_builder_put_u8(builder,
+ WSC_WFA_EXTENSION_AUTHORIZED_MACS);
+ wsc_attr_builder_put_u8(builder, count * 6);
+ wsc_attr_builder_put_bytes(builder, beacon->authorized_macs,
+ count * 6);
+ }
+
+ if (beacon->reg_config_methods) {
+ wsc_attr_builder_put_u8(builder,
+ WSC_WFA_EXTENSION_REGISTRAR_CONFIGRATION_METHODS);
+ wsc_attr_builder_put_u8(builder, 2);
+ wsc_attr_builder_put_u16(builder, beacon->reg_config_methods);
+ }
+
+done:
+ ret = wsc_attr_builder_free(builder, false, out_len);
+ return ret;
+}
+
uint8_t *wsc_build_probe_request(const struct wsc_probe_request *probe_request,
size_t *out_len)
{
diff --git a/src/wscutil.h b/src/wscutil.h
index 45d72fbb..5bb26d84 100644
--- a/src/wscutil.h
+++ b/src/wscutil.h
@@ -604,6 +604,7 @@ int wsc_parse_wsc_done(const uint8_t *pdu, uint32_t len, struct wsc_done *out);
uint8_t *wsc_build_credential(const struct wsc_credential *in, size_t *out_len);
+uint8_t *wsc_build_beacon(const struct wsc_beacon *beacon, size_t *out_len);
uint8_t *wsc_build_probe_request(const struct wsc_probe_request *probe_request,
size_t *out_len);
uint8_t *wsc_build_probe_response(
--
2.25.1
1 year, 8 months
[PATCH 01/16] hwsim: return radio ID on create
by James Prestwood
Hwsim was relying on some internal behavior of mac80211_hwsim where new
radios are created with ID's starting at zero and incremented. While
this is a reasonable assumption its better to obtain the actual radio
ID since mac80211_hwsim returns it in the radio creation callback.
Now hwsim will return the radio ID when creating radios. Negative returns
are still errors, but any value >= 0 indicates the radio ID of the newly
created radio.
---
tools/hwsim.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/tools/hwsim.c b/tools/hwsim.c
index 02053fa1..467ccd2d 100644
--- a/tools/hwsim.c
+++ b/tools/hwsim.c
@@ -216,6 +216,7 @@ static void create_callback(struct l_genl_msg *msg, void *user_data)
radio_id = err;
l_info("Created new radio with id %u", radio_id);
+ exit_status = radio_id;
} else {
l_warn("Failed to get create return value");
exit_status = EXIT_FAILURE;
@@ -2605,7 +2606,8 @@ static void usage(void)
printf("\thwsim [options]\n");
printf("Options:\n"
"\t-L, --list [id] List simulated radios\n"
- "\t-C, --create Create new simulated radio\n"
+ "\t-C, --create Create new simulated radio. The "
+ "return value is the new radio ID\n"
"\t-D, --destroy <id> Destroy existing radio\n"
"\t-n, --name <name> Name of a radio to be created\n"
"\t-i, --nointerface Do not create VIF\n"
@@ -2632,6 +2634,7 @@ static const struct option main_options[] = {
int main(int argc, char *argv[])
{
int actions = 0;
+ int ret;
for (;;) {
int opt;
@@ -2729,7 +2732,9 @@ int main(int argc, char *argv[])
goto done;
}
- exit_status = l_main_run_with_signal(signal_handler, NULL);
+ ret = l_main_run_with_signal(signal_handler, NULL);
+ if (ret)
+ exit_status = ret;
l_genl_family_free(hwsim);
l_genl_family_free(nl80211);
--
2.21.1
1 year, 8 months
[PATCH 1/2] ap: Move AP parameters to a struct
by Andrew Zaborowski
To limit the number of ap_start parameters, group basic AP config
parameters in the ap_config struct that is passed as a pointer and owned
by the ap_state.
---
src/ap.c | 134 +++++++++++++++++++++++++++++++------------------------
src/ap.h | 23 ++++++++--
2 files changed, 96 insertions(+), 61 deletions(-)
diff --git a/src/ap.c b/src/ap.c
index 51ee23a8..ff8ced18 100644
--- a/src/ap.c
+++ b/src/ap.c
@@ -53,10 +53,7 @@ struct ap_state {
ap_event_func_t event_func;
ap_stopped_func_t stopped_func;
void *user_data;
- char *ssid;
- uint8_t channel;
- uint8_t *authorized_macs;
- int authorized_macs_num;
+ struct ap_config *config;
unsigned int ciphers;
enum ie_rsn_cipher_suite group_cipher;
@@ -73,7 +70,6 @@ struct ap_state {
bool started : 1;
bool gtk_set : 1;
- bool no_cck_rates : 1;
};
struct sta_state {
@@ -94,6 +90,30 @@ struct sta_state {
static uint32_t netdev_watch;
+void ap_config_free(struct ap_config *config)
+{
+ if (unlikely(!config))
+ return;
+
+ l_free(config->ssid);
+
+ if (config->psk) {
+ explicit_bzero(config->psk, strlen(config->psk));
+ l_free(config->psk);
+ }
+
+ if (config->authorized_macs) {
+ uint8_t **mac;
+
+ for (mac = config->authorized_macs; *mac; mac++)
+ l_free(mac);
+
+ l_free(config->authorized_macs);
+ }
+
+ l_free(config);
+}
+
static void ap_sta_free(void *data)
{
struct sta_state *sta = data;
@@ -121,8 +141,6 @@ static void ap_reset(struct ap_state *ap)
{
struct netdev *netdev = ap->netdev;
- l_free(ap->ssid);
-
explicit_bzero(ap->pmk, sizeof(ap->pmk));
if (ap->mlme_watch)
@@ -138,7 +156,9 @@ static void ap_reset(struct ap_state *ap)
if (ap->rates)
l_uintset_free(ap->rates);
- l_free(ap->authorized_macs);
+ ap_config_free(ap->config);
+ ap->config = NULL;
+
ap->started = false;
}
@@ -318,7 +338,8 @@ static size_t ap_build_beacon_pr_head(struct ap_state *ap,
/* SSID IE */
ie_tlv_builder_next(&builder, IE_TYPE_SSID);
- ie_tlv_builder_set_data(&builder, ap->ssid, strlen(ap->ssid));
+ ie_tlv_builder_set_data(&builder, ap->config->ssid,
+ strlen(ap->config->ssid));
/* Supported Rates IE */
ie_tlv_builder_next(&builder, IE_TYPE_SUPPORTED_RATES);
@@ -343,7 +364,7 @@ static size_t ap_build_beacon_pr_head(struct ap_state *ap,
/* DSSS Parameter Set IE for DSSS, HR, ERP and HT PHY rates */
ie_tlv_builder_next(&builder, IE_TYPE_DSSS_PARAMETER_SET);
- ie_tlv_builder_set_data(&builder, &ap->channel, 1);
+ ie_tlv_builder_set_data(&builder, &ap->config->channel, 1);
ie_tlv_builder_finalize(&builder, &len);
return 36 + len;
@@ -375,7 +396,8 @@ static uint32_t ap_send_mgmt_frame(struct ap_state *ap,
struct l_genl_msg *msg;
uint32_t ifindex = netdev_get_ifindex(ap->netdev);
uint32_t id;
- uint32_t ch_freq = scan_channel_to_freq(ap->channel, SCAN_BAND_2_4_GHZ);
+ uint32_t ch_freq = scan_channel_to_freq(ap->config->channel,
+ SCAN_BAND_2_4_GHZ);
msg = l_genl_msg_new_sized(NL80211_CMD_FRAME, 128 + frame_len);
@@ -386,7 +408,7 @@ static uint32_t ap_send_mgmt_frame(struct ap_state *ap,
l_genl_msg_append_attr(msg, NL80211_ATTR_DONT_WAIT_FOR_ACK,
0, NULL);
- if (ap->no_cck_rates)
+ if (ap->config->no_cck_rates)
l_genl_msg_append_attr(msg, NL80211_ATTR_TX_NO_CCK_RATE, 0,
NULL);
@@ -446,7 +468,8 @@ static void ap_start_rsna(struct sta_state *sta, const uint8_t *gtk_rsc)
sta->hs = netdev_handshake_state_new(netdev);
handshake_state_set_event_func(sta->hs, ap_handshake_event, sta);
- handshake_state_set_ssid(sta->hs, (void *)ap->ssid, strlen(ap->ssid));
+ handshake_state_set_ssid(sta->hs, (void *) ap->config->ssid,
+ strlen(ap->config->ssid));
handshake_state_set_authenticator(sta->hs, true);
handshake_state_set_authenticator_ie(sta->hs, bss_rsne);
handshake_state_set_supplicant_ie(sta->hs, sta->assoc_rsne);
@@ -900,8 +923,8 @@ static void ap_assoc_reassoc(struct sta_state *sta, bool reassoc,
break;
}
- if (!rates || !ssid || !rsn || ssid_len != strlen(ap->ssid) ||
- memcmp(ssid, ap->ssid, ssid_len)) {
+ if (!rates || !ssid || !rsn || ssid_len != strlen(ap->config->ssid) ||
+ memcmp(ssid, ap->config->ssid, ssid_len)) {
err = MMPDU_REASON_CODE_INVALID_IE;
goto bad_frame;
}
@@ -1125,8 +1148,8 @@ static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,
if (!ssid || ssid_len == 0) /* Wildcard SSID */
match = true;
- else if (ssid && ssid_len == strlen(ap->ssid) && /* Specific SSID */
- !memcmp(ssid, ap->ssid, ssid_len))
+ else if (ssid && ssid_len == strlen(ap->config->ssid) && /* One SSID */
+ !memcmp(ssid, ap->config->ssid, ssid_len))
match = true;
else if (ssid_list) { /* SSID List */
ie_tlv_iter_init(&iter, ssid_list, ssid_list_len);
@@ -1138,15 +1161,16 @@ static void ap_probe_req_cb(const struct mmpdu_header *hdr, const void *body,
ssid = (const char *) ie_tlv_iter_get_data(&iter);
ssid_len = ie_tlv_iter_get_length(&iter);
- if (ssid_len == strlen(ap->ssid) &&
- !memcmp(ssid, ap->ssid, ssid_len)) {
+ if (ssid_len == strlen(ap->config->ssid) &&
+ !memcmp(ssid, ap->config->ssid,
+ ssid_len)) {
match = true;
break;
}
}
}
- if (dsss_channel != 0 && dsss_channel != ap->channel)
+ if (dsss_channel != 0 && dsss_channel != ap->config->channel)
match = false;
if (!match)
@@ -1247,14 +1271,14 @@ static void ap_auth_cb(const struct mmpdu_header *hdr, const void *body,
memcmp(hdr->address_3, bssid, 6))
return;
- if (ap->authorized_macs) {
- int i;
+ if (ap->config->authorized_macs) {
+ uint8_t *const *mac;
- for (i = 0; i < ap->authorized_macs_num; i++)
- if (!memcmp(from, ap->authorized_macs + i * 6, 6))
+ for (mac = ap->config->authorized_macs; *mac; mac++)
+ if (!memcmp(from, *mac, 6))
break;
- if (i == ap->authorized_macs_num) {
+ if (!*mac) {
ap_auth_reply(ap, from, MMPDU_REASON_CODE_UNSPECIFIED);
return;
}
@@ -1374,7 +1398,8 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
uint32_t nl_akm = CRYPTO_AKM_PSK;
uint32_t wpa_version = NL80211_WPA_VERSION_2;
uint32_t auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM;
- uint32_t ch_freq = scan_channel_to_freq(ap->channel, SCAN_BAND_2_4_GHZ);
+ uint32_t ch_freq = scan_channel_to_freq(ap->config->channel,
+ SCAN_BAND_2_4_GHZ);
uint32_t ch_width = NL80211_CHAN_WIDTH_20;
static const uint8_t bcast_addr[6] = {
@@ -1389,7 +1414,7 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
return NULL;
cmd = l_genl_msg_new_sized(NL80211_CMD_START_AP, 256 + head_len +
- tail_len + strlen(ap->ssid));
+ tail_len + strlen(ap->config->ssid));
/* SET_BEACON attrs */
l_genl_msg_append_attr(cmd, NL80211_ATTR_BEACON_HEAD, head_len, head);
@@ -1403,8 +1428,8 @@ static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
&ap->beacon_interval);
l_genl_msg_append_attr(cmd, NL80211_ATTR_DTIM_PERIOD, 4, &dtim_period);
l_genl_msg_append_attr(cmd, NL80211_ATTR_IFINDEX, 4, &ifindex);
- l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID, strlen(ap->ssid),
- ap->ssid);
+ l_genl_msg_append_attr(cmd, NL80211_ATTR_SSID, strlen(ap->config->ssid),
+ ap->config->ssid);
l_genl_msg_append_attr(cmd, NL80211_ATTR_HIDDEN_SSID, 4,
&hidden_ssid);
l_genl_msg_append_attr(cmd, NL80211_ATTR_CIPHER_SUITES_PAIRWISE, 4,
@@ -1462,11 +1487,14 @@ static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
* @event_func is required and must react to AP_EVENT_START_FAILED
* and AP_EVENT_STOPPING by forgetting the ap_state struct, which
* is going to be freed automatically.
- * @channel is optional.
+ * In the @config struct only .ssid and .psk need to be non-NUL,
+ * other fields are optional. If @ap_start succeeds, the returned
+ * ap_state takes ownership of @config and the caller shouldn't
+ * free it or any of the memory pointed to by its members (they
+ * also can't be static). In principle there's no reason that the
+ * caller shouldn't read/update some of the members though.
*/
-struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
- const char *psk, int channel, bool no_cck_rates,
- const uint8_t **authorized_macs,
+struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
ap_event_func_t event_func, void *user_data)
{
struct ap_state *ap;
@@ -1476,30 +1504,14 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
ap = l_new(struct ap_state, 1);
ap->nl80211 = l_genl_family_new(iwd_get_genl(), NL80211_GENL_NAME);
- ap->ssid = l_strdup(ssid);
+ ap->config = config;
ap->netdev = netdev;
- ap->no_cck_rates = no_cck_rates;
ap->event_func = event_func;
ap->user_data = user_data;
- if (channel)
- ap->channel = channel;
- else {
+ if (!config->channel)
/* TODO: Start a Get Survey to decide the channel */
- ap->channel = 6;
- }
-
- if (authorized_macs) {
- int i;
-
- for (i = 0; authorized_macs[i]; i++);
- ap->authorized_macs = l_malloc(i * 6);
- ap->authorized_macs_num = i;
-
- for (i = 0; authorized_macs[i]; i++)
- memcpy(ap->authorized_macs + i * 6, authorized_macs[i],
- 6);
- }
+ config->channel = 6;
/* TODO: Add all ciphers supported by wiphy */
ap->ciphers = wiphy_select_cipher(wiphy, 0xffff);
@@ -1507,7 +1519,7 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
ap->beacon_interval = 100;
/* TODO: Pick from actual supported rates */
- if (no_cck_rates) {
+ if (config->no_cck_rates) {
l_uintset_put(ap->rates, 12); /* 6 Mbps*/
l_uintset_put(ap->rates, 18); /* 9 Mbps*/
l_uintset_put(ap->rates, 24); /* 12 Mbps*/
@@ -1523,8 +1535,8 @@ struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
l_uintset_put(ap->rates, 22); /* 11 Mbps*/
}
- if (crypto_psk_from_passphrase(psk, (uint8_t *) ssid, strlen(ssid),
- ap->pmk) < 0)
+ if (crypto_psk_from_passphrase(config->psk, (uint8_t *) config->ssid,
+ strlen(config->ssid), ap->pmk) < 0)
goto error;
if (!frame_watch_add(wdev_id, 0, 0x0000 |
@@ -1757,6 +1769,7 @@ static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
{
struct ap_if_data *ap_if = user_data;
const char *ssid, *wpa2_psk;
+ struct ap_config *config;
if (ap_if->ap && ap_if->ap->started)
return dbus_error_already_exists(message);
@@ -1767,10 +1780,15 @@ static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
if (!l_dbus_message_get_arguments(message, "ss", &ssid, &wpa2_psk))
return dbus_error_invalid_args(message);
- ap_if->ap = ap_start(ap_if->netdev, ssid, wpa2_psk, 0, false, NULL,
- ap_if_event_func, ap_if);
- if (!ap_if->ap)
+ config = l_new(struct ap_config, 1);
+ config->ssid = l_strdup(ssid);
+ config->psk = l_strdup(wpa2_psk);
+
+ ap_if->ap = ap_start(ap_if->netdev, config, ap_if_event_func, ap_if);
+ if (!ap_if->ap) {
+ ap_config_free(config);
return dbus_error_invalid_args(message);
+ }
ap_if->pending = l_dbus_message_ref(message);
return NULL;
diff --git a/src/ap.h b/src/ap.h
index b007b657..3ca9467f 100644
--- a/src/ap.h
+++ b/src/ap.h
@@ -41,13 +41,30 @@ struct ap_event_station_removed_data {
enum mmpdu_reason_code reason;
};
+struct ap_event_registration_started_data {
+ const uint8_t *mac;
+ const struct iovec *assoc_ies;
+};
+
+struct ap_event_registration_success_data {
+ const uint8_t *mac;
+};
+
typedef void (*ap_event_func_t)(enum ap_event_type type, const void *event_data,
void *user_data);
typedef void (*ap_stopped_func_t)(void *user_data);
-struct ap_state *ap_start(struct netdev *netdev, const char *ssid,
- const char *psk, int channel, bool no_cck_rates,
- const uint8_t **authorized_macs,
+struct ap_config {
+ char *ssid;
+ char *psk;
+ uint8_t channel;
+ uint8_t **authorized_macs;
+ bool no_cck_rates : 1;
+};
+
+void ap_config_free(struct ap_config *config);
+
+struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
ap_event_func_t event_func, void *user_data);
void ap_shutdown(struct ap_state *ap, ap_stopped_func_t stopped_func,
void *user_data);
--
2.25.1
1 year, 8 months
Re: Issue with iwd + Linux 5.8.3 + WPA Enterprise
by Ard Biesheuvel
On Thu, 27 Aug 2020 at 06:56, Caleb Jorden <caljorden(a)hotmail.com> wrote:
>
> I can tell you all assumed this, but just by way as a quick update on the original issue:
>
> I have confirmed that Herbert's patch (crypto: af_alg - Work around empty control messages without MSG_MORE) does indeed fix the original iwd 1.8 + WPA Enterprise issue.
>
> Thank you!
>
> Caleb Jorden
>
Thanks for confirming.
> ________________________________________
> From: Herbert Xu <herbert(a)gondor.apana.org.au>
> Sent: Thursday, August 27, 2020 3:49 AM
> To: Ard Biesheuvel
> Cc: Denis Kenzior; Andrew Zaborowski; Paul Menzel; Caleb Jorden; Sasha Levin; iwd(a)lists.01.org; # 3.4.x; Greg KH; LKML; David S. Miller; Linux Crypto Mailing List
> Subject: Re: Issue with iwd + Linux 5.8.3 + WPA Enterprise
>
> On Wed, Aug 26, 2020 at 05:42:27PM +0200, Ard Biesheuvel wrote:
> >
> > I still get a failure in aes_siv_encrypt(), which does not occur with
> > the kernel side fix applied.
>
> Where is this test from? I can't find it in the ell git tree.
>
> Thanks,
> --
> Email: Herbert Xu <herbert(a)gondor.apana.org.au>
> Home Page: http://gondor.apana.org.au/~herbert/
> PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
1 year, 8 months
Re: [v2 PATCH] crypto: af_alg - Work around empty control messages
without MSG_MORE
by Ard Biesheuvel
On Thu, 27 Aug 2020 at 09:15, Herbert Xu <herbert(a)gondor.apana.org.au> wrote:
>
> On Thu, Aug 27, 2020 at 08:40:01AM +0200, Ard Biesheuvel wrote:
> >
> > It is part of iwd - just build that and run 'make check'
> >
> > With your patch applied, the occurrence of sendmsg() in
> > operate_cipher() triggers the warn_once(), but if I add MSG_MORE
> > there, the test hangs.
>
> I see. This is a different issue. The original kernel change
> was a bit too strict here and it is barfing at the fact that two
> successive sendmsg's of the same request both contain a control
> message.
>
> Here's an updated patch to allow this.
>
> ---8<---
> The iwd daemon uses libell which sets up the skcipher operation with
> two separate control messages. As the first control message is sent
> without MSG_MORE, it is interpreted as an empty request.
>
> While libell should be fixed to use MSG_MORE where appropriate, this
> patch works around the bug in the kernel so that existing binaries
> continue to work.
>
> We will print a warning however.
>
> A separate issue is that the new kernel code no longer allows the
> control message to be sent twice within the same request. This
> restriction is obviously incompatible with what iwd was doing (first
> setting an IV and then sending the real control message). This
> patch changes the kernel so that this is explicitly allowed.
>
> Reported-by: Caleb Jorden <caljorden(a)hotmail.com>
> Fixes: f3c802a1f300 ("crypto: algif_aead - Only wake up when...")
> Cc: <stable(a)vger.kernel.org>
> Signed-off-by: Herbert Xu <herbert(a)gondor.apana.org.au>
>
> diff --git a/crypto/af_alg.c b/crypto/af_alg.c
> index a6f581ab200c..8be8bec07cdd 100644
> --- a/crypto/af_alg.c
> +++ b/crypto/af_alg.c
> @@ -16,6 +16,7 @@
> #include <linux/module.h>
> #include <linux/net.h>
> #include <linux/rwsem.h>
> +#include <linux/sched.h>
> #include <linux/sched/signal.h>
> #include <linux/security.h>
>
> @@ -845,9 +846,15 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
> }
>
> lock_sock(sk);
> - if (ctx->init && (init || !ctx->more)) {
> - err = -EINVAL;
> - goto unlock;
> + if (ctx->init && !ctx->more) {
> + if (ctx->used) {
> + err = -EINVAL;
> + goto unlock;
> + }
> +
> + pr_info_once(
> + "%s sent an empty control message without MSG_MORE.\n",
> + current->comm);
> }
> ctx->init = true;
>
Yep, that works.
1 year, 8 months