emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r110328: Fix a malloc race condition


From: Paul Eggert
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r110328: Fix a malloc race condition involving strsignal.
Date: Mon, 01 Oct 2012 15:12:44 -0700
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 110328
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Mon 2012-10-01 15:12:44 -0700
message:
  Fix a malloc race condition involving strsignal.
  
  A signal can arrive in the middle of a malloc, and Emacs's signal
  handler can invoke strsignal, which can invoke malloc, which is
  not portable.  This race condition bug makes Emacs hang on GNU/Linux.
  Fix it by altering the signal handler so that it does not invoke
  strsignal.
  * emacs.c (shut_down_emacs): Use safe_strsignal, not strsignal.
  * process.c (status_message): Use const pointer, in case strsignal
  is #defined to safe_strsignal.
  * sysdep.c (sys_siglist, init_signals): Always define and
  initialize a substitute sys_siglist if the system does not define
  one, even if HAVE_STRSIGNAL.
  (safe_strsignal): Rename from strsignal.  Always define,
  using sys_siglist.  Return a const pointer.
  * syssignal.h (safe_strsignal): New decl.
  (strsignal) [!HAVE_STRSIGNAL]: Define in terms of safe_strsignal.
modified:
  src/ChangeLog
  src/emacs.c
  src/process.c
  src/sysdep.c
  src/syssignal.h
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-10-01 21:09:30 +0000
+++ b/src/ChangeLog     2012-10-01 22:12:44 +0000
@@ -1,3 +1,22 @@
+2012-10-01  Paul Eggert  <address@hidden>
+
+       Fix a malloc race condition involving strsignal.
+       A signal can arrive in the middle of a malloc, and Emacs's signal
+       handler can invoke strsignal, which can invoke malloc, which is
+       not portable.  This race condition bug makes Emacs hang on GNU/Linux.
+       Fix it by altering the signal handler so that it does not invoke
+       strsignal.
+       * emacs.c (shut_down_emacs): Use safe_strsignal, not strsignal.
+       * process.c (status_message): Use const pointer, in case strsignal
+       is #defined to safe_strsignal.
+       * sysdep.c (sys_siglist, init_signals): Always define and
+       initialize a substitute sys_siglist if the system does not define
+       one, even if HAVE_STRSIGNAL.
+       (safe_strsignal): Rename from strsignal.  Always define,
+       using sys_siglist.  Return a const pointer.
+       * syssignal.h (safe_strsignal): New decl.
+       (strsignal) [!HAVE_STRSIGNAL]: Define in terms of safe_strsignal.
+
 2012-10-01  Eli Zaretskii  <address@hidden>
 
        * w32proc.c (timer_loop): Fix code that waits for timer

=== modified file 'src/emacs.c'
--- a/src/emacs.c       2012-10-01 14:25:40 +0000
+++ b/src/emacs.c       2012-10-01 22:12:44 +0000
@@ -1886,7 +1886,7 @@
            static char const format[] = "Fatal error %d: ";
            char buf[sizeof format - 2 + INT_STRLEN_BOUND (int)];
            int buflen = sprintf (buf, format, sig);
-           char const *sig_desc = strsignal (sig);
+           char const *sig_desc = safe_strsignal (sig);
            ignore_value (write (STDERR_FILENO, buf, buflen));
            ignore_value (write (STDERR_FILENO, sig_desc, strlen (sig_desc)));
          }

=== modified file 'src/process.c'
--- a/src/process.c     2012-10-01 06:36:54 +0000
+++ b/src/process.c     2012-10-01 22:12:44 +0000
@@ -570,7 +570,7 @@
 
   if (EQ (symbol, Qsignal) || EQ (symbol, Qstop))
     {
-      char *signame;
+      char const *signame;
       synchronize_system_messages_locale ();
       signame = strsignal (code);
       if (signame == 0)

=== modified file 'src/sysdep.c'
--- a/src/sysdep.c      2012-10-01 02:07:14 +0000
+++ b/src/sysdep.c      2012-10-01 22:12:44 +0000
@@ -1543,12 +1543,10 @@
   errno = old_errno;
 }
 
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
-static char *my_sys_siglist[NSIG];
-# ifdef sys_siglist
-#  undef sys_siglist
-# endif
+#if !HAVE_DECL_SYS_SIGLIST
+# undef sys_siglist
 # define sys_siglist my_sys_siglist
+static char const *sys_siglist[NSIG];
 #endif
 
 /* Handle bus errors, invalid instruction, etc.  */
@@ -1611,7 +1609,7 @@
   main_thread = pthread_self ();
 #endif
 
-#if !defined HAVE_STRSIGNAL && !HAVE_DECL_SYS_SIGLIST
+#if !HAVE_DECL_SYS_SIGLIST
   if (! initialized)
     {
       sys_siglist[SIGABRT] = "Aborted";
@@ -1759,7 +1757,7 @@
       sys_siglist[SIGXFSZ] = "File size limit exceeded";
 # endif
     }
-#endif /* !defined HAVE_STRSIGNAL && !defined HAVE_DECL_SYS_SIGLIST */
+#endif /* !HAVE_DECL_SYS_SIGLIST */
 
   /* Don't alter signal handlers if dumping.  On some machines,
      changing signal handlers sets static data that would make signals
@@ -2280,21 +2278,20 @@
   return fdutimens (fd, filename, timespec);
 }
 
-#ifndef HAVE_STRSIGNAL
-char *
-strsignal (int code)
+/* Like strsignal, except async-signal-safe, and this function typically
+   returns a string in the C locale rather than the current locale.  */
+char const *
+safe_strsignal (int code)
 {
-  char *signame = 0;
+  char const *signame = 0;
 
   if (0 <= code && code < NSIG)
-    {
-      /* Cast to suppress warning if the table has const char *.  */
-      signame = (char *) sys_siglist[code];
-    }
+    signame = sys_siglist[code];
+  if (! signame)
+    signame = "Unknown signal";
 
   return signame;
 }
-#endif /* HAVE_STRSIGNAL */
 
 #ifndef DOS_NT
 /* For make-serial-process  */

=== modified file 'src/syssignal.h'
--- a/src/syssignal.h   2012-09-30 08:15:11 +0000
+++ b/src/syssignal.h   2012-10-01 22:12:44 +0000
@@ -39,6 +39,7 @@
 typedef void (*signal_handler_t) (int);
 
 extern void emacs_sigaction_init (struct sigaction *, signal_handler_t);
+char const *safe_strsignal (int);
 
 #if NSIG < NSIG_MINIMUM
 # undef NSIG
@@ -70,8 +71,7 @@
 #endif /* ! defined (SIGCLD) */
 
 #ifndef HAVE_STRSIGNAL
-/* strsignal is in sysdep.c */
-char *strsignal (int);
+# define strsignal(sig) safe_strsignal (sig)
 #endif
 
 void deliver_process_signal (int, signal_handler_t);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]