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;