This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 3a0ea0f41716b1316b22dd108e4aa5d60b1c7901 Author: raiden00pl <[email protected]> AuthorDate: Thu Oct 22 13:02:53 2026 +0200 wireless/ieee802154: drop received frames the MAC cannot parse The header parser read past a frame shorter than its MAC header, and a reserved frame type leaked the indication and its IOB. The header length is computed by mac802154_mhrlen(), shared with mac802154_get_mhrlen(). Assisted-by: Claude Code Signed-off-by: raiden00pl <[email protected]> --- wireless/ieee802154/mac802154.c | 70 ++++++++++++++++++++++++++ wireless/ieee802154/mac802154_get_mhrlen.c | 80 +++++++++++++++--------------- wireless/ieee802154/mac802154_internal.h | 3 ++ 3 files changed, 113 insertions(+), 40 deletions(-) diff --git a/wireless/ieee802154/mac802154.c b/wireless/ieee802154/mac802154.c index d9aa3d5c0c1..56c6f328d8d 100644 --- a/wireless/ieee802154/mac802154.c +++ b/wireless/ieee802154/mac802154.c @@ -109,6 +109,7 @@ static void mac802154_sfevent(FAR const struct ieee802154_radiocb_s *radiocb, enum ieee802154_sfevent_e sfevent); static void mac802154_purge_worker(FAR void *arg); +static int mac802154_fcmhrlen(uint16_t fc); static void mac802154_rxdatareq(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_data_ind_s *ind); @@ -1061,6 +1062,57 @@ static void mac802154_rxframe(FAR const struct ieee802154_radiocb_s *radiocb, } } +/**************************************************************************** + * Name: mac802154_fcmhrlen + * + * Description: + * MAC header length described by a frame control field. + * + ****************************************************************************/ + +static int mac802154_fcmhrlen(uint16_t fc) +{ + return mac802154_mhrlen((fc & IEEE802154_FRAMECTRL_DADDR) >> + IEEE802154_FRAMECTRL_SHIFT_DADDR, + (fc & IEEE802154_FRAMECTRL_SADDR) >> + IEEE802154_FRAMECTRL_SHIFT_SADDR, + (fc & IEEE802154_FRAMECTRL_PANIDCOMP) != 0); +} + +/**************************************************************************** + * Name: mac802154_mhrvalid + * + * Description: + * Check that a received frame holds the whole MAC header described by its + * frame control field, and the command identifier of a command frame. + * + ****************************************************************************/ + +static bool mac802154_mhrvalid(FAR struct iob_s *iob) +{ + uint16_t fc; + int len; + int mhrlen; + + len = iob->io_len - iob->io_offset; + if (len < 3) + { + return false; + } + + fc = iob->io_data[iob->io_offset] | + (iob->io_data[iob->io_offset + 1] << 8); + mhrlen = mac802154_fcmhrlen(fc); + + if (((fc & IEEE802154_FRAMECTRL_FTYPE) >> + IEEE802154_FRAMECTRL_SHIFT_FTYPE) == IEEE802154_FRAME_COMMAND) + { + mhrlen++; + } + + return len >= mhrlen; +} + /**************************************************************************** * Name: mac802154_rxframe_worker * @@ -1112,6 +1164,16 @@ static void mac802154_rxframe_worker(FAR void *arg) iob = ind->frame; + /* Drop a frame shorter than its MAC header */ + + if (!mac802154_mhrvalid(iob)) + { + wlwarn("WARNING: dropping malformed frame\n"); + ieee802154_primitive_free((FAR struct ieee802154_primitive_s *) + ind); + continue; + } + /* Set a local pointer to the frame control then move the offset past * the frame control field */ @@ -1280,6 +1342,14 @@ static void mac802154_rxframe_worker(FAR void *arg) ind); } break; + + default: + { + wlinfo("Reserved frame type %u dropped\n", ftype); + ieee802154_primitive_free((FAR struct ieee802154_primitive_s *) + ind); + } + break; } } } diff --git a/wireless/ieee802154/mac802154_get_mhrlen.c b/wireless/ieee802154/mac802154_get_mhrlen.c index d6ef3d9d103..fbb34f97b56 100644 --- a/wireless/ieee802154/mac802154_get_mhrlen.c +++ b/wireless/ieee802154/mac802154_get_mhrlen.c @@ -52,6 +52,38 @@ static const uint8_t mac802154_addr_length[4] = * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: mac802154_mhrlen + * + * Description: + * Calculate the MAC header length given the addressing modes and the PAN + * ID compression field. + * + ****************************************************************************/ + +int mac802154_mhrlen(enum ieee802154_addrmode_e dmode, + enum ieee802154_addrmode_e smode, bool panidcomp) +{ + int ret = 3; /* Always frame control (2 bytes) and seq. num (1 byte) */ + + ret += mac802154_addr_length[dmode]; + ret += mac802154_addr_length[smode]; + + if (dmode != IEEE802154_ADDRMODE_NONE) + { + ret += 2; /* 2 bytes for destination PAN ID */ + } + + /* The source PAN ID is omitted when PAN ID compression is set */ + + if (smode != IEEE802154_ADDRMODE_NONE && !panidcomp) + { + ret += 2; /* 2 bytes for source PAN ID */ + } + + return ret; +} + /**************************************************************************** * Name: mac802154_get_mhrlen * @@ -65,7 +97,6 @@ int mac802154_get_mhrlen(MACHANDLE mac, { FAR struct ieee802154_privmac_s *priv = (FAR struct ieee802154_privmac_s *)mac; - int ret = 3; /* Always frame control (2 bytes) and seq. num (1 byte) */ /* Check to make sure both the dest address and the source address are not * set to NONE @@ -87,47 +118,16 @@ int mac802154_get_mhrlen(MACHANDLE mac, return -EINVAL; } - /* Add the destination address length */ - - ret += mac802154_addr_length[meta->destaddr.mode]; - - /* Add the source address length */ - - ret += mac802154_addr_length[meta->srcmode]; - /* If both destination and source addressing information is present, the * MAC sublayer shall compare the destination and source PAN identifiers. - * [1] pg. 41. - */ - - if (meta->srcmode != IEEE802154_ADDRMODE_NONE && - meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) - { - /* If the PAN identifiers are identical, the PAN ID Compression field - * shall be set to one, and the source PAN identifier shall be omitted - * from the transmitted frame. [1] pg. 41. - */ - - if (IEEE802154_PANIDCMP(meta->destaddr.panid, priv->addr.panid)) - { - ret += 2; /* 2 bytes for destination PAN ID */ - return ret; - } - } - - /* If we are here, PAN ID compression is off, so include the dest and - * source PAN ID if the respective address is included + * If the PAN identifiers are identical, the PAN ID Compression field + * shall be set to one, and the source PAN identifier shall be omitted + * from the transmitted frame. [1] pg. 41. */ - if (meta->srcmode != IEEE802154_ADDRMODE_NONE) - { - ret += 2; /* 2 bytes for source PAN ID */ - } - - if (meta->destaddr.mode != IEEE802154_ADDRMODE_NONE) - { - ret += 2; /* 2 bytes for destination PAN ID */ - } - - return ret; + return mac802154_mhrlen(meta->destaddr.mode, meta->srcmode, + meta->srcmode != IEEE802154_ADDRMODE_NONE && + meta->destaddr.mode != IEEE802154_ADDRMODE_NONE && + IEEE802154_PANIDCMP(meta->destaddr.panid, + priv->addr.panid)); } diff --git a/wireless/ieee802154/mac802154_internal.h b/wireless/ieee802154/mac802154_internal.h index 0656a4775e4..b463f0d0541 100644 --- a/wireless/ieee802154/mac802154_internal.h +++ b/wireless/ieee802154/mac802154_internal.h @@ -321,6 +321,9 @@ void mac802154_createdatareq(FAR struct ieee802154_privmac_s *priv, void mac802154_updatebeacon(FAR struct ieee802154_privmac_s *priv); +int mac802154_mhrlen(enum ieee802154_addrmode_e dmode, + enum ieee802154_addrmode_e smode, bool panidcomp); + void mac802154_notify(FAR struct ieee802154_privmac_s *priv, FAR struct ieee802154_primitive_s *primitive);
