newlib: copy args for atexit()'ed function before unlock the mutex

Message ID 20251203085803.579-1-takashi.yano@nifty.ne.jp
State New
Headers
Series newlib: copy args for atexit()'ed function before unlock the mutex |

Commit Message

Takashi Yano Dec. 3, 2025, 8:57 a.m. UTC
  The commit a2a8bc771f2f has a problem that __atexit which includes
args for atexit()'ed function may be touched by another thread
since the mutex is unlocked while calling the function.
With this path, the args, etc. are copyed to local variable to
prevent this problem.

Fixes: a2a8bc771f2f ("newlib: Unlock the mutex while calling atexit()'ed functions")
Suggested-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>, Sebastian Huber <sebastian.huber@embedded-brains.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
---
 newlib/libc/stdlib/__call_atexit.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
  

Comments

Corinna Vinschen Dec. 4, 2025, 9:39 a.m. UTC | #1
On Dec  3 17:57, Takashi Yano wrote:
> The commit a2a8bc771f2f has a problem that __atexit which includes
> args for atexit()'ed function may be touched by another thread
> since the mutex is unlocked while calling the function.
> With this path, the args, etc. are copyed to local variable to
> prevent this problem.
> 
> Fixes: a2a8bc771f2f ("newlib: Unlock the mutex while calling atexit()'ed functions")
> Suggested-by: Sebastian Huber <sebastian.huber@embedded-brains.de>
> Reviewed-by: Corinna Vinschen <corinna@vinschen.de>, Sebastian Huber <sebastian.huber@embedded-brains.de>
> Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
> ---
>  newlib/libc/stdlib/__call_atexit.c | 14 ++++++++++----
>  1 file changed, 10 insertions(+), 4 deletions(-)

Thanks, please push.

Corinna
  

Patch

diff --git a/newlib/libc/stdlib/__call_atexit.c b/newlib/libc/stdlib/__call_atexit.c
index 44f1f6acc..15ecda343 100644
--- a/newlib/libc/stdlib/__call_atexit.c
+++ b/newlib/libc/stdlib/__call_atexit.c
@@ -93,6 +93,8 @@  __call_exitprocs (int code, void *d)
       for (n = p->_ind - 1; n >= 0; n--)
 	{
 	  int ind;
+	  __ULong fntypes, is_cxa;
+	  void *fnarg;
 
 	  i = 1 << n;
 
@@ -114,18 +116,22 @@  __call_exitprocs (int code, void *d)
 
 	  ind = p->_ind;
 
+	  fntypes = args->_fntypes;
+	  is_cxa = args->_is_cxa;
+	  fnarg = args->_fnargs[n];
+
 #ifndef __SINGLE_THREAD__
 	  /* Unlock __atexit_recursive_mutex; otherwise, the function fn() may
 	     deadlock if it waits for another thread which calls atexit(). */
 	  __lock_release_recursive(__atexit_recursive_mutex);
 #endif
 	  /* Call the function.  */
-	  if (!args || (args->_fntypes & i) == 0)
+	  if (!args || (fntypes & i) == 0)
 	    fn ();
-	  else if ((args->_is_cxa & i) == 0)
-	    (*((void (*)(int, void *)) fn))(code, args->_fnargs[n]);
+	  else if ((is_cxa & i) == 0)
+	    (*((void (*)(int, void *)) fn))(code, fnarg);
 	  else
-	    (*((void (*)(void *)) fn))(args->_fnargs[n]);
+	    (*((void (*)(void *)) fn))(fnarg);
 #ifndef __SINGLE_THREAD__
 	  __lock_acquire_recursive(__atexit_recursive_mutex);
 #endif