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 87998e3f61cb46ed49f1d911d5c8bd9fafedb4d7
Author: Royyan Zahir <[email protected]>
AuthorDate: Wed Sep 30 22:04:23 2026 +0400

    sched/signal: validate a sigevent where it is registered
    
    A SIGEV_SIGNAL | SIGEV_THREAD_ID timer skipped timer_create's signal
    check, and nxsig_notification honoured any thread ID. Add
    nxsig_event_valid(): the signal must exist and a SIGEV_THREAD_ID target
    must be one of the caller's own threads, as on Linux. timer_create,
    gpio, button and phy_notify call it before storing an event, so the
    caller gets EINVAL and an expiring timer never fails its DEBUGVERIFY.
    
    Signed-off-by: Royyan Zahir <[email protected]>
---
 drivers/input/button_upper.c    |  2 +-
 drivers/ioexpander/gpio.c       |  7 +++++++
 drivers/net/phy_notify.c        |  6 ++++++
 include/nuttx/signal.h          | 18 +++++++++++++++++
 sched/signal/sig_notification.c | 44 +++++++++++++++++++++++++++++++++++++++++
 sched/timer/timer_create.c      |  3 +--
 6 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/drivers/input/button_upper.c b/drivers/input/button_upper.c
index ed9f239ba50..40cca92c40d 100644
--- a/drivers/input/button_upper.c
+++ b/drivers/input/button_upper.c
@@ -638,7 +638,7 @@ static int btn_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
           FAR struct btn_notify_s *notify =
             (FAR struct btn_notify_s *)((uintptr_t)arg);
 
-          if (notify)
+          if (notify && nxsig_event_valid(&notify->bn_event) == OK)
             {
               /* Save the notification events */
 
diff --git a/drivers/ioexpander/gpio.c b/drivers/ioexpander/gpio.c
index f4bb08468eb..3fbcb0e0db6 100644
--- a/drivers/ioexpander/gpio.c
+++ b/drivers/ioexpander/gpio.c
@@ -829,6 +829,13 @@ static int gpio_ioctl(FAR struct file *filep, int cmd, 
unsigned long arg)
 #if CONFIG_DEV_GPIO_NSIGNALS > 0
             if (arg)
               {
+                ret = nxsig_event_valid((FAR struct sigevent *)arg);
+                if (ret < 0)
+                  {
+                    leave_critical_section(flags);
+                    break;
+                  }
+
                 pid = nxsched_getpid();
                 for (i = 0; i < CONFIG_DEV_GPIO_NSIGNALS; i++)
                   {
diff --git a/drivers/net/phy_notify.c b/drivers/net/phy_notify.c
index 57d086fdaa3..88a6beec642 100644
--- a/drivers/net/phy_notify.c
+++ b/drivers/net/phy_notify.c
@@ -290,6 +290,12 @@ int phy_notify_subscribe(FAR const char *intf, pid_t pid,
       return phy_notify_unsubscribe(intf, pid);
     }
 
+  ret = nxsig_event_valid(event);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
   /* Check if this client already exists */
 
   client = phy_find_assigned(intf, pid);
diff --git a/include/nuttx/signal.h b/include/nuttx/signal.h
index f58dc6f901f..7c334517be5 100644
--- a/include/nuttx/signal.h
+++ b/include/nuttx/signal.h
@@ -691,6 +691,24 @@ unsigned int nxsig_sleep(unsigned int seconds);
 
 int nxsig_usleep(useconds_t usec);
 
+/****************************************************************************
+ * Name: nxsig_event_valid
+ *
+ * Description:
+ *   Check a sigevent handed in by the calling task before it is stored:
+ *   its signal must exist and a SIGEV_THREAD_ID target must be one of the
+ *   caller's own threads.
+ *
+ * Input Parameters:
+ *   event - The instance of struct sigevent to check.
+ *
+ * Returned Value:
+ *   Zero (OK) if the event may be stored; -EINVAL if not.
+ *
+ ****************************************************************************/
+
+int nxsig_event_valid(FAR const struct sigevent *event);
+
 /****************************************************************************
  * Name: nxsig_notification
  *
diff --git a/sched/signal/sig_notification.c b/sched/signal/sig_notification.c
index a7948c33974..2a3778f2ef6 100644
--- a/sched/signal/sig_notification.c
+++ b/sched/signal/sig_notification.c
@@ -92,6 +92,50 @@ static void nxsig_notification_worker(FAR void *arg)
  * Public Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: nxsig_event_valid
+ *
+ * Description:
+ *   Check a sigevent handed in by the calling task before it is stored:
+ *   its signal must exist and a SIGEV_THREAD_ID target must be one of the
+ *   caller's own threads.
+ *
+ * Input Parameters:
+ *   event - The instance of struct sigevent to check.
+ *
+ * Returned Value:
+ *   Zero (OK) if the event may be stored; -EINVAL if not.
+ *
+ ****************************************************************************/
+
+int nxsig_event_valid(FAR const struct sigevent *event)
+{
+  FAR struct tcb_s *target;
+
+  if ((event->sigev_notify & SIGEV_SIGNAL) == 0)
+    {
+      return OK;
+    }
+
+  if (!GOOD_SIGNO(event->sigev_signo))
+    {
+      return -EINVAL;
+    }
+
+  if ((event->sigev_notify & SIGEV_THREAD_ID) == 0)
+    {
+      return OK;
+    }
+
+  target = nxsched_get_tcb(event->sigev_notify_thread_id);
+  if (target == NULL || target->group != nxsched_self()->group)
+    {
+      return -EINVAL;
+    }
+
+  return OK;
+}
+
 /****************************************************************************
  * Name: nxsig_notification
  *
diff --git a/sched/timer/timer_create.c b/sched/timer/timer_create.c
index c756ed2c66e..42c39b84f87 100644
--- a/sched/timer/timer_create.c
+++ b/sched/timer/timer_create.c
@@ -169,8 +169,7 @@ int timer_create(clockid_t clockid, FAR struct sigevent 
*evp,
 
   if (timerid == NULL || (clockid != CLOCK_REALTIME &&
       clockid != CLOCK_MONOTONIC && clockid != CLOCK_BOOTTIME) ||
-      (evp != NULL && evp->sigev_notify == SIGEV_SIGNAL &&
-       !GOOD_SIGNO(evp->sigev_signo)))
+      (evp != NULL && nxsig_event_valid(evp) < 0))
     {
       set_errno(EINVAL);
     }

Reply via email to