From b95257b33ffd9c4995254e38695d125cfd1d1899 Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Tue, 18 Aug 2026 23:40:09 +1200 Subject: [PATCH] hostapd: Tweak Makefile and update minor patches Avoid linker error when building a hostapd variant with the "internal" TLS backend by not enabling CONFIG_EAP_TLS_PINNING for those builds. The internal backend doesn't support pinning. Update two minor patches with more complete fixes from internal review. --- overlay/hostapd/Makefile | 5 +- ...o000-hostapd-ht-operation-null-deref.patch | 120 +++++++++++++++--- ...o001-radius-server-accept-attr-fixes.patch | 21 +-- .../o103-eap-tls-server-cert-pinning.patch | 12 +- 4 files changed, 121 insertions(+), 37 deletions(-) diff --git a/overlay/hostapd/Makefile b/overlay/hostapd/Makefile index 0ffbea3..8340ed8 100644 --- a/overlay/hostapd/Makefile +++ b/overlay/hostapd/Makefile @@ -17,8 +17,11 @@ OVERLAY_RELEASE:=1 include ../../include/overlay.mk define Overlay/BuildConfig -# safe for all variants, no-op when CONFIG_EAP_TLS is not enabled +# Safe for all package variants except those using the 'internal' TLS backend. +# Only variants with CONFIG_EAP_TLS=y will actually build pinning support. +ifneq ($(SSL_VARIANT),internal) DRIVER_MAKEOPTS += CONFIG_EAP_TLS_PINNING=y +endif endef $(eval $(call BuildPackageOverlay,network/services/hostapd)) diff --git a/overlay/hostapd/patches/o000-hostapd-ht-operation-null-deref.patch b/overlay/hostapd/patches/o000-hostapd-ht-operation-null-deref.patch index 021c881..92dcb4c 100644 --- a/overlay/hostapd/patches/o000-hostapd-ht-operation-null-deref.patch +++ b/overlay/hostapd/patches/o000-hostapd-ht-operation-null-deref.patch @@ -1,46 +1,126 @@ -From 0e275f281a19e3175fd02335145600e338b378c5 Mon Sep 17 00:00:00 2001 +From 5ca1f6193cc45051bf3e698d501fc6d6e7c718e3 Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Wed, 29 Jul 2026 19:21:36 +1200 -Subject: [PATCH] hostapd: Fix NULL deref in hostapd_eid_ht_operation +Subject: [PATCH] hostapd: Fix NULL deref and endianness in Extended NSS BW + code -hapd->iface->current_mode is NULL whenever hostapd runs without hw -feature data, which is not an error: -hostapd_setup_interface_complete_sync() continues when -hostapd_get_hw_features() fails (commented "Not all drivers support this -yet, so continue without hw feature data"), skipping the +170-hostapd-update-cfs0-and-cfs1-for-160MHz.patch adds an Extended NSS +BW check to hostapd_eid_ht_operation() and hostapd_eid_vht_operation(); +both dereference hapd->iface->current_mode without a NULL check. + +current_mode is NULL whenever hostapd runs without hw feature data, +which is not an error: hostapd_setup_interface_complete_sync() continues +when hostapd_get_hw_features() fails (commented "Not all drivers support +this yet, so continue without hw feature data"), skipping the hostapd_select_hw_mode() block that would set current_mode. Interface setup then proceeds to hostapd_start_beacon() and builds the beacon IEs anyway. This is why hostapd_eid_erp_info(), hostapd_dfs_start_channel_switch() and many other call sites all check current_mode before dereferencing it. -Reaching it requires ieee80211n=1 (the function returns early otherwise) -together with no hw feature data, i.e. driver=none or any driver whose -get_hw_feature_data fails. +Reaching the HT case requires ieee80211n=1 (hostapd_eid_ht_operation() +returns early otherwise), the VHT case ieee80211ac=1 (all callers of +hostapd_eid_vht_operation() gate it on hostapd_is_vht_enabled()), +together with no hw feature data -- i.e. driver=none or any driver whose +get_hw_feature_data fails. The VHT case is particularly clearly +unintended: hostapd_eid_vht_capabilities(), called immediately before +hostapd_eid_vht_operation() at every call site, already returns early +when current_mode is absent, so hostapd correctly omits the VHT +Capabilities element and then crashes building VHT Operation. + +Treat an absent current_mode as advertising no Extended NSS BW support, +which leaves both elements identical to what upstream emitted before the +check was introduced. -Treat an absent current_mode as advertising no VHT capabilities, which -leaves the resulting HT Operation element identical to what upstream -emitted before the Extended NSS BW check was introduced. +Also fix misplaced host_to_le32() calls in the same patch: +iface->current_mode->vht_capab and the VHT_CAP_* constants are both host +byte order (u32), so can be compared / masked directly without the +detour through an le32 local. However in hostapd_eid_vht_capabilities() +the vht_capabilities_info being built is le32, so constants need +swapping before application. This endianness issue is not expected to +affect any OpenWrt target in practice, since the radios that support 160 +/ 80+80 channels are on little-endian platforms. Signed-off-by: Karsten Sperling --- - src/ap/ieee802_11_ht.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) + src/ap/ieee802_11_ht.c | 7 +++---- + src/ap/ieee802_11_vht.c | 11 +++++------ + 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c -index 77b7907e7..47e9ea390 100644 +index 77b7907e7..9661733fe 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c -@@ -145,7 +145,8 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) +@@ -127,7 +127,6 @@ no_update: + u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) + { + struct ieee80211_ht_operation *oper; +- le32 vht_capabilities_info; + u8 *pos = eid; + u8 chwidth; + +@@ -145,10 +144,10 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); set_ht_param(hapd, oper); - vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab); -+ vht_capabilities_info = host_to_le32(hapd->iface->current_mode ? -+ hapd->iface->current_mode->vht_capab : 0); chwidth = hostapd_get_oper_chwidth(hapd->iconf); - if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT +- if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT +- && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) { ++ if (hapd->iface->current_mode && ++ (hapd->iface->current_mode->vht_capab & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) && ++ ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) { + oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5); + } + +diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c +index f77cbdb7e..226c30319 100644 +--- a/src/ap/ieee802_11_vht.c ++++ b/src/ap/ieee802_11_vht.c +@@ -65,14 +65,14 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts) + } + + chwidth = hostapd_get_oper_chwidth(hapd->iconf); +- if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) ++ if ((mode->vht_capab & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) { +- cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT; ++ cap->vht_capabilities_info |= host_to_le32(VHT_CAP_EXTENDED_NSS_BW_SUPPORT); + cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)); + cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)); + cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK)); + } else { +- cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK; ++ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK)); + } + + /* Supported MCS set comes from hw */ +@@ -87,7 +87,6 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts) + u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) + { + struct ieee80211_vht_operation *oper; +- le32 vht_capabilities_info; + u8 *pos = eid; + enum oper_chan_width oper_chwidth = + hostapd_get_oper_chwidth(hapd->iconf); +@@ -126,7 +125,6 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) + oper->vht_op_info_chan_center_freq_seg1_idx = seg1; + + oper->vht_op_info_chwidth = oper_chwidth; +- vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab); + if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) { + /* + * Convert 160 MHz channel width to new style as interop +@@ -141,7 +139,8 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) + else + oper->vht_op_info_chan_center_freq_seg0_idx += 8; + +- if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT) ++ if (hapd->iface->current_mode && ++ (hapd->iface->current_mode->vht_capab & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)) + oper->vht_op_info_chan_center_freq_seg1_idx = 0; + } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) { + /* -- 2.50.1 (Apple Git-155) diff --git a/overlay/hostapd/patches/o001-radius-server-accept-attr-fixes.patch b/overlay/hostapd/patches/o001-radius-server-accept-attr-fixes.patch index 392ee52..a055f47 100644 --- a/overlay/hostapd/patches/o001-radius-server-accept-attr-fixes.patch +++ b/overlay/hostapd/patches/o001-radius-server-accept-attr-fixes.patch @@ -1,8 +1,7 @@ -From 8a3ff9d9f228a40de81d2b91ac77beef7265aea8 Mon Sep 17 00:00:00 2001 +From 4e351c1e65e0c1590d59bfbe6ef05d4555ffc7c3 Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Sun, 9 Aug 2026 02:25:05 +1200 -Subject: [PATCH] RADIUS server: Fix accept_attr leak, allocation size and NULL - handling +Subject: [PATCH] RADIUS server: accept_attr leak, alloc size, NULL handling radius_server_get_eap_user() is the get_eap_user callback, so it runs for every EAP user lookup and reassigns sess->accept_attr each time, @@ -21,11 +20,11 @@ session. Signed-off-by: Karsten Sperling --- - src/radius/radius_server.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) + src/radius/radius_server.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c -index 44b4312e3..23d9a9333 100644 +index 44b4312e3..c65c1bfa4 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -554,7 +554,7 @@ radius_server_copy_attr(const struct hostapd_radius_attr *data) @@ -48,14 +47,16 @@ index 44b4312e3..23d9a9333 100644 sess->username = os_malloc(user_len * 4 + 1); if (sess->username == NULL) { -@@ -2370,7 +2374,10 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity, +@@ -2370,7 +2374,11 @@ static int radius_server_get_eap_user(void *ctx, const u8 *identity, ret = data->get_eap_user(data->conf_ctx, identity, identity_len, phase2, user); if (ret == 0 && user) { -+ os_free(sess->accept_attr); - sess->accept_attr = radius_server_copy_attr(user->accept_attr); -+ if (sess->accept_attr == NULL) +- sess->accept_attr = radius_server_copy_attr(user->accept_attr); ++ struct radius_accept_attr *attr = radius_server_copy_attr(user->accept_attr); ++ if (attr == NULL) + return -1; ++ os_free(sess->accept_attr); ++ sess->accept_attr = attr; sess->macacl = user->macacl; sess->t_c_timestamp = user->t_c_timestamp; } diff --git a/overlay/hostapd/patches/o103-eap-tls-server-cert-pinning.patch b/overlay/hostapd/patches/o103-eap-tls-server-cert-pinning.patch index 7e00dd5..44ab8e7 100644 --- a/overlay/hostapd/patches/o103-eap-tls-server-cert-pinning.patch +++ b/overlay/hostapd/patches/o103-eap-tls-server-cert-pinning.patch @@ -1,4 +1,4 @@ -From e52755c05ab4d48f63bd9ae0b56fb10d0477e628 Mon Sep 17 00:00:00 2001 +From 13eaad49ffca32ee48ed6ec0303415f568bf55bb Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Fri, 3 Jul 2026 23:12:12 +1200 Subject: [PATCH] EAP-TLS server: Add support for client cert pinning @@ -59,10 +59,10 @@ Signed-off-by: Karsten Sperling create mode 100644 tests/hwsim/test_ap_eap_tls_cert_pin.py diff --git a/hostapd/Makefile b/hostapd/Makefile -index a7ebc534f..ee4e18079 100644 +index c277d070a..361e1a8ba 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile -@@ -434,6 +434,10 @@ ifdef CONFIG_EAP_TLS +@@ -438,6 +438,10 @@ ifdef CONFIG_EAP_TLS CFLAGS += -DEAP_SERVER_TLS OBJS += ../src/eap_server/eap_server_tls.o TLS_FUNCS=y @@ -211,10 +211,10 @@ index c0e903040..b58a65303 100644 } diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c -index 349e489c6..90bc43d70 100644 +index b0c386053..5f0b579a0 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c -@@ -2389,6 +2389,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, +@@ -2391,6 +2391,7 @@ static int ieee802_1x_get_eap_user(void *ctx, const u8 *identity, os_memset(user, 0, sizeof(*user)); user->phase2 = phase2; @@ -492,7 +492,7 @@ index 81d1eedd4..7174cfb7a 100644 session_ctx[7] = (u8) eap_type; if (tls_connection_set_verify(sm->cfg->ssl_ctx, data->conn, verify_peer, diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config -index 58b07513b..a2b526a27 100644 +index 383368bfd..20561a410 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -14,6 +14,7 @@ CONFIG_EAP=y