This is an automated email from the ASF dual-hosted git repository.

xiaoxiang 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 af53d7a178 libs/libc/aio/lio_listio: fix the heap use-after-free bug
af53d7a178 is described below

commit af53d7a178da3bf398fddb2ae3fffca63ed701bc
Author: guoshichao <[email protected]>
AuthorDate: Mon Jun 19 17:52:39 2023 +0800

    libs/libc/aio/lio_listio: fix the heap use-after-free bug
    
    1. the lio_sigsetup() method use a universal sighand instance across all
    aiocb instances, but inside the lio_sighandler() method, if one aiocb is
    handle finished, then this method will free the sighand instance that
    come along with current aiocb instance. thus when handle next aiocb
    instance, use-after-free crash will happen. in order to solve this
    problem, we make each aiocb instance have their own sighand instance
    2. make the lio_listio implementation can pass the
    ltp/open_posix_testsuite/lio_listio testcases
    3. the modification are referred to 
https://pubs.opengroup.org/onlinepubs/9699919799/functions/lio_listio.html
    
    Signed-off-by: guoshichao <[email protected]>
---
 libs/libc/aio/lio_listio.c | 83 ++++++++++++++++++++++++----------------------
 1 file changed, 44 insertions(+), 39 deletions(-)

diff --git a/libs/libc/aio/lio_listio.c b/libs/libc/aio/lio_listio.c
index ae1b2f4d13..d54e5e2526 100644
--- a/libs/libc/aio/lio_listio.c
+++ b/libs/libc/aio/lio_listio.c
@@ -215,55 +215,25 @@ static int lio_sigsetup(FAR struct aiocb * const *list, 
int nent,
                         FAR struct sigevent *sig)
 {
   FAR struct aiocb *aiocbp;
-  FAR struct lio_sighand_s *sighand;
+  struct lio_sighand_s sighand;
   sigset_t set;
   struct sigaction act;
   int status;
   int i;
 
-  /* Allocate a structure to pass data to the signal handler */
-
-  sighand = lib_zalloc(sizeof(struct lio_sighand_s));
-  if (!sighand)
-    {
-      ferr("ERROR: lib_zalloc failed\n");
-      return -ENOMEM;
-    }
-
   /* Initialize the allocated structure */
 
-  sighand->list = list;
-  sighand->sig  = *sig;
-  sighand->nent = nent;
-  sighand->pid  = _SCHED_GETPID();
-
-  /* Save this structure as the private data attached to each aiocb */
-
-  for (i = 0; i < nent; i++)
-    {
-      /* Skip over NULL entries in the list */
-
-      aiocbp = list[i];
-      if (aiocbp)
-        {
-          FAR void *priv = NULL;
-
-          /* Check if I/O is pending for  this entry */
-
-          if (aiocbp->aio_result == -EINPROGRESS)
-            {
-              priv = (FAR void *)sighand;
-            }
-
-          aiocbp->aio_priv = priv;
-        }
-    }
+  memset(&sighand, 0, sizeof(struct lio_sighand_s));
+  sighand.list = list;
+  sighand.sig  = *sig;
+  sighand.nent = nent;
+  sighand.pid  = _SCHED_GETPID();
 
   /* Make sure that SIGPOLL is not blocked */
 
   sigemptyset(&set);
   sigaddset(&set, SIGPOLL);
-  status = sigprocmask(SIG_UNBLOCK, &set, &sighand->oprocmask);
+  status = sigprocmask(SIG_UNBLOCK, &set, &sighand.oprocmask);
   if (status != OK)
     {
       int errcode = get_errno();
@@ -282,7 +252,7 @@ static int lio_sigsetup(FAR struct aiocb * const *list, int 
nent,
   sigfillset(&act.sa_mask);
   sigdelset(&act.sa_mask, SIGPOLL);
 
-  status = sigaction(SIGPOLL, &act, &sighand->oact);
+  status = sigaction(SIGPOLL, &act, &sighand.oact);
   if (status != OK)
     {
       int errcode = get_errno();
@@ -293,6 +263,36 @@ static int lio_sigsetup(FAR struct aiocb * const *list, 
int nent,
       return -errcode;
     }
 
+  /* Save this structure as the private data attached to each aiocb */
+
+  for (i = 0; i < nent; i++)
+    {
+      /* Skip over NULL entries in the list */
+
+      aiocbp = list[i];
+      if (aiocbp)
+        {
+          FAR void *priv = NULL;
+
+          /* Check if I/O is pending for  this entry */
+
+          if (aiocbp->aio_result == -EINPROGRESS)
+            {
+              priv = lib_zalloc(sizeof(struct lio_sighand_s));
+              if (!priv)
+                {
+                  ferr("ERROR: lib_zalloc failed\n");
+                  return -ENOMEM;
+                }
+
+              memcpy(priv, (FAR void *)&sighand,
+                      sizeof(struct lio_sighand_s));
+            }
+
+          aiocbp->aio_priv = priv;
+        }
+    }
+
   return OK;
 }
 
@@ -517,7 +517,12 @@ int lio_listio(int mode, FAR struct aiocb * const list[], 
int nent,
   int ret;
   int i;
 
-  DEBUGASSERT(mode == LIO_WAIT || mode == LIO_NOWAIT);
+  if (mode != LIO_WAIT && mode != LIO_NOWAIT)
+    {
+      set_errno(EINVAL);
+      return ERROR;
+    }
+
   DEBUGASSERT(list);
 
   nqueued = 0;    /* No I/O operations yet queued */

Reply via email to