mirror of
https://github.com/apache/nuttx.git
synced 2026-10-10 07:40:27 +00:00
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 <royzah@gmail.com>
This commit is contained in:
parent
bcff4ae00d
commit
87998e3f61
6 changed files with 77 additions and 3 deletions
|
|
@ -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(¬ify->bn_event) == OK)
|
||||
{
|
||||
/* Save the notification events */
|
||||
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue