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);
 

Reply via email to