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


The following commit(s) were added to refs/heads/master by this push:
     new e6899872a51 sched/mqueue: always enforce POSIX checks in 
mq_send/mq_receive.
e6899872a51 is described below

commit e6899872a511c3b629182061b0625aa5205535a4
Author: Brijesh Thakkar <[email protected]>
AuthorDate: Thu Nov 5 15:10:35 2026 +0530

    sched/mqueue: always enforce POSIX checks in mq_send/mq_receive.
    
    nxmq_verify_send() and nxmq_verify_receive() have been compiled only
    when CONFIG_DEBUG_FEATURES is set since d09dc08eab ("sched/mqueue: do
    sanity check if DEBUG_FEATURES is enabled"); 1e7631e695 moved them into
    mq_send.c and mq_receive.c and kept the guard. As a result, without
    DEBUG_FEATURES mq_send() succeeds on a descriptor opened O_RDONLY,
    mq_receive() succeeds on one opened O_WRONLY, and oversized messages or
    a priority above the maximum are accepted. POSIX requires EBADF,
    EMSGSIZE and EINVAL for these, so conforming behavior depended on a
    debug option. This shows up in LTP mq_open_7_1 and 18 other mq_* cases
    on rv-virt:citest64, which does not set DEBUG_FEATURES.
    
    Always build the verify functions and always call them from
    file_mq_timedsend_internal() and file_mq_timedreceive_internal(), which
    every mq_*, nxmq_* and file_mq_* variant goes through. Only the pure
    sanity checks stay under CONFIG_DEBUG_FEATURES: NULL inode, NULL message
    pointer and NULL message queue. The order of the checks in debug builds
    is unchanged.
    
    Also return EBADF when the inode is not a message queue. Nothing
    checked the inode type, so mq_send() or mq_receive() on a pipe or the
    console used another driver's i_private as a struct mqueue_inode_s.
    
    The cost without DEBUG_FEATURES is +62 bytes of text on rv-virt:nsh64
    and +56 bytes on rv-virt:nsh (measured before the inode type check).
    
    Fixes #21248
    
    Assisted-by: Claude Code:claude-sonnet-5-5
    Signed-off-by: Brijesh Thakkar <[email protected]>
---
 sched/mqueue/mq_receive.c | 25 ++++++++++++++++++-------
 sched/mqueue/mq_send.c    | 30 +++++++++++++++++++++++-------
 2 files changed, 41 insertions(+), 14 deletions(-)

diff --git a/sched/mqueue/mq_receive.c b/sched/mqueue/mq_receive.c
index 15c389b08f5..4a2b9e1317f 100644
--- a/sched/mqueue/mq_receive.c
+++ b/sched/mqueue/mq_receive.c
@@ -62,33 +62,47 @@
  *   On success, zero (OK) is returned.  A negated errno value is returned
  *   on any failure:
  *
- *   EBADF    Message queue opened not opened for reading.
+ *   EBADF    Not a message queue, or opened not opened for reading.
  *   EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the message
  *            queue.
  *   EINVAL   Invalid 'msg' or 'msgq'
  *
  ****************************************************************************/
 
-#ifdef CONFIG_DEBUG_FEATURES
 static int nxmq_verify_receive(FAR struct file *mq,
                                FAR char *msg, size_t msglen)
 {
   FAR struct inode *inode = mq->f_inode;
   FAR struct mqueue_inode_s *msgq;
 
+#ifdef CONFIG_DEBUG_FEATURES
   if (inode == NULL)
     {
       return -EBADF;
     }
+#endif
+
+  /* The descriptor must refer to a message queue, otherwise i_private
+   * belongs to some other driver.
+   */
+
+  if (!INODE_IS_MQUEUE(inode))
+    {
+      return -EBADF;
+    }
 
   msgq = inode->i_private;
 
-  /* Verify the input parameters */
+#ifdef CONFIG_DEBUG_FEATURES
+  /* Verify the pointers (sanity check only) */
 
   if (!msg || !msgq)
     {
       return -EINVAL;
     }
+#endif
+
+  /* The checks below are required by POSIX and are always enforced */
 
   if ((mq->f_oflags & O_ACCMODE) == O_WRONLY)
     {
@@ -102,7 +116,6 @@ static int nxmq_verify_receive(FAR struct file *mq,
 
   return OK;
 }
-#endif
 
 /****************************************************************************
  * Name: file_mq_timedreceive_internal
@@ -157,7 +170,6 @@ ssize_t file_mq_timedreceive_internal(FAR struct file *mq, 
FAR char *msg,
       return -EINVAL;
     }
 
-#ifdef CONFIG_DEBUG_FEATURES
   /* Verify the input parameters and, in case of an error, set
    * errno appropriately.
    */
@@ -167,7 +179,6 @@ ssize_t file_mq_timedreceive_internal(FAR struct file *mq, 
FAR char *msg,
     {
       return ret;
     }
-#endif
 
   msgq = mq->f_inode->i_private;
 
@@ -568,7 +579,7 @@ ssize_t nxmq_receive(mqd_t mqdes, FAR char *msg, size_t 
msglen,
  *
  *   EAGAIN   The queue was empty, and the O_NONBLOCK flag was set
  *            for the message queue description referred to by 'mqdes'.
- *   EBADF    Message queue opened not opened for reading.
+ *   EBADF    Not a message queue, or opened not opened for reading.
  *   EMSGSIZE 'msglen' was less than the maxmsgsize attribute of the
  *            message queue.
  *   EINTR    The call was interrupted by a signal handler.
diff --git a/sched/mqueue/mq_send.c b/sched/mqueue/mq_send.c
index e3b5bd7a1b6..9cebc7a35e7 100644
--- a/sched/mqueue/mq_send.c
+++ b/sched/mqueue/mq_send.c
@@ -64,29 +64,48 @@
  *   returned.
  *
  *     EINVAL   Either msg or msgq is NULL or the value of prio is invalid.
- *     EBADF    Message queue opened not opened for writing.
+ *     EBADF    Not a message queue, or opened not opened for writing.
  *     EMSGSIZE 'msglen' was greater than the maxmsgsize attribute of the
  *               message queue.
  *
  ****************************************************************************/
 
-#ifdef CONFIG_DEBUG_FEATURES
 static int nxmq_verify_send(FAR FAR struct file *mq, FAR const char *msg,
                             size_t msglen, unsigned int prio)
 {
   FAR struct inode *inode = mq->f_inode;
   FAR struct mqueue_inode_s *msgq;
 
+#ifdef CONFIG_DEBUG_FEATURES
   if (inode == NULL)
     {
       return -EBADF;
     }
+#endif
+
+  /* The descriptor must refer to a message queue, otherwise i_private
+   * belongs to some other driver.
+   */
+
+  if (!INODE_IS_MQUEUE(inode))
+    {
+      return -EBADF;
+    }
 
   msgq = inode->i_private;
 
-  /* Verify the input parameters */
+#ifdef CONFIG_DEBUG_FEATURES
+  /* Verify the pointers (sanity check only) */
+
+  if (msg == NULL || msgq == NULL)
+    {
+      return -EINVAL;
+    }
+#endif
+
+  /* The checks below are required by POSIX and are always enforced */
 
-  if (msg == NULL || msgq == NULL || prio >= MQ_PRIO_MAX)
+  if (prio >= MQ_PRIO_MAX)
     {
       return -EINVAL;
     }
@@ -103,7 +122,6 @@ static int nxmq_verify_send(FAR FAR struct file *mq, FAR 
const char *msg,
 
   return OK;
 }
-#endif
 
 /****************************************************************************
  * Name: nxmq_alloc_msg
@@ -294,7 +312,6 @@ int file_mq_timedsend_internal(FAR struct file *mq, FAR 
const char *msg,
       return -EINVAL;
     }
 
-#ifdef CONFIG_DEBUG_FEATURES
   /* Verify the input parameters on any failures to verify. */
 
   ret = nxmq_verify_send(mq, msg, msglen, prio);
@@ -302,7 +319,6 @@ int file_mq_timedsend_internal(FAR struct file *mq, FAR 
const char *msg,
     {
       return ret;
     }
-#endif
 
   msgq = mq->f_inode->i_private;
 

Reply via email to