This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/5190] New: syslog() may interact between threads.


1. Summary:

  syslog() uses global variable LogTag, LogFacility, and LogStat
  between threads. It may cause interraction between threads
  such as overriding global variables.

2. hardware dependency:

  none.

3. Description of Problem:

  syslog() uses global variable LogTag, LogFacility, and LogStat
  between threads. It may cause interraction between threads
  such as overriding global variables. It is really problem
  when using different ident, logopt, facility in multi-thread
  applications.

  Problem No.1:
    LogTag may be override.

  Problem No.2:
    LogFacility may be override.

  Problem No.3:
    LogStat may be override.


4. How reproducible:

  Always

5. Step to Reproduce:
  The following test program can reproduce the problems.
    tst-syslog.tar.gz
  To make reproduction easy, this program executes openlog(),
 syslog(), closelog()  at the same time by a lot of threads.

  1) Extract the archive file.
     The following files are extracted.
        Makefile
        tst-syslog.c
  2) Compile the test program.
        # make
  3) Run the test program.
        # ./tst-syslog

     - If Problem  No.1 happens, the test program will
       display the following messages.

       Example:
         A00009: This is test message from thread A00006-105

       In this thread, openlog("A00006",LOG_NDELAY,LOG_DEFAULT) is
       executed. And syslog() is excuted, expecting LogTag is "A00006",
       but LogTag is really "A00009", which is set by other thread.
       is overrided by other thread(in "A00009").


6. Actual Results:
/var/log/messages:
-----------------------------------------------------------------------------
Oct  9 17:28:58 localhost A00006: This is test message from thread A00006-103
Oct  9 17:28:58 localhost A00006: This is test message from thread A00006-104
Oct  9 17:28:58 localhost A00009: This is test message from thread A00006-105
----------------------------------------------------------------------------- 
In Usual, ident and Thread-ID is same, as line 1,and 2.
but Problem No.1 occurs, ident and Thread-ID is different, as line 3.

7. Expected Resulst:

   Each thread use different values of LogType, LogFacility,
   and LogStat.

8. Cause
  Problem No.1:
    LogTag may be override.


        Thread1                 Thread 2
                                openlog()
                                syslog()
        openlog(?gMy ID?h,...)
                                closelog()
        syslog()
        closelog()

  1) openlog() is called in thread 1 with argument "My ID" as ident.
     LogTag is set by "My ID".
          ----------------------
        internal_function
        openlog_internal(const char *ident, int logstat, int logfac)
        {
                if (ident != NULL)
                        LogTag = ident;
          -----------------------

  2) closelog()is called in thread 2.
     LogTag is unset.
          -----------------------
        closelog ()
        {
          /* Protect against multiple users and cancellation.  */
          __libc_cleanup_push (cancel_handler, NULL);
          __libc_lock_lock (syslog_lock);

          closelog_internal ();
          LogTag = NULL;
          -----------------------

  3) syslog() is called in thread1.
     LogTag is set by its program name,
     but expected value is "My ID".
         -------------------------
            if (LogTag == NULL)
              LogTag = __progname;
            if (LogTag != NULL)
              fputs_unlocked (LogTag, f);

?@?@?@?@(snip)

            /* We have the header.  Print the user's format into the
               buffer.  */
            if (flag == -1)
              vfprintf (f, fmt, ap);
            else
              __vfprintf_chk (f, flag, fmt, ap);
          --------------------------

  The cause of of Problem No.2, and No.3 are same.


9. Solutions
  I propose a following patch.
------------------------------------------------------------------------------
$ diff -ruN glibc-2.6.1/misc/syslog.c.orig glibc-2.6.1/misc/syslog.c
--- glibc-2.6.1/misc/syslog.c.orig      2006-01-14 21:09:36.000000000 +0900
+++ glibc-2.6.1/misc/syslog.c   2007-10-16 17:06:53.000000000 +0900
@@ -62,6 +62,21 @@

 #define ftell(s) INTUSE(_IO_ftell) (s)

+#ifdef USE___THREAD
+static int     LogType = SOCK_DGRAM;   /* type of socket connection */
+static int     LogFile = -1;           /* fd for log */
+static __thread int    connected;              /* have done connect */
+static int     GLogStat;               /* status bits, set by openlog() */
+static __thread int    LogStat;                /* status bits, set by
openlog() */
+static const char *GLogTag;            /* string to tag the entry with */
+static __thread const char *LogTag;            /* string to tag the entry
with */
+static int     GLogFacility = LOG_USER;        /* default facility code */
+static __thread int    LogFacility = LOG_USER; /* default facility code */
+static int     LogMask = 0xff;         /* mask of priorities to be logged */
+static int     connected_count = 0;    /* open count in process */
+extern char    *__progname;            /* Program name, from crt0. */
+
+#else
 static int     LogType = SOCK_DGRAM;   /* type of socket connection */
 static int     LogFile = -1;           /* fd for log */
 static int     connected;              /* have done connect */
@@ -70,6 +85,7 @@
 static int     LogFacility = LOG_USER; /* default facility code */
 static int     LogMask = 0xff;         /* mask of priorities to be logged */
 extern char    *__progname;            /* Program name, from crt0. */
+#endif

 /* Define the lock.  */
 __libc_lock_define_initialized (static, syslog_lock)
@@ -201,6 +217,14 @@
                                              __localtime_r (&now, &now_tm),
                                              _nl_C_locobj_ptr);
            msgoff = ftell (f);
+#ifdef USE___THREAD
+           if ( !connected )
+             {
+               LogTag      = GLogTag;
+               LogStat     = GLogStat;
+               LogFacility = GLogFacility;
+             }
+#endif
            if (LogTag == NULL)
              LogTag = __progname;
            if (LogTag != NULL)
@@ -335,11 +359,19 @@
 internal_function
 openlog_internal(const char *ident, int logstat, int logfac)
 {
+#ifdef USE___THREAD
+       if (ident != NULL)
+               GLogTag = LogTag = ident;
+       GLogStat = LogStat = logstat;
+       if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+               GLogFacility = LogFacility = logfac;
+#else
        if (ident != NULL)
                LogTag = ident;
        LogStat = logstat;
        if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
                LogFacility = logfac;
+#endif

        int retry = 0;
        while (retry < 2) {
@@ -373,8 +405,14 @@
                                        ++retry;
                                        continue;
                                }
-                       } else
+                       }
+                       else
+                       {
                                connected = 1;
+#ifdef USE___THREAD
+                               connected_count++;
+#endif
+                       }
                }
                break;
        }
@@ -406,9 +444,19 @@
   if (!connected)
     return;

+#ifndef USE___THREAD
   __close (LogFile);
   LogFile = -1;
+#endif
   connected = 0;
+#ifdef USE___THREAD
+  connected_count--;
+  if ( connected_count )
+  {
+       __close (LogFile);
+       LogFile = -1;
+  }
+#endif
 }

 void
------------------------------------------------------------------------------
  This patch solves the problems that overriding gloval valiables
  LogTag, LogFacility, and LogStat. This fix do not effect for
  single-threaded applications, or multi-threaded applications which
  use same ident, logopt, or facilitiy between threads.

  Problem No.1:
  - This correction changes type of LogTag to thread-local storage.
  - Each thread may have different values of LogTag, and change
    local value, so able to avoid interactions to other thread.

  Problem No.2:
  - This correction changes type of LogFacility to thread-local storage.
  - Each thread may have different values of LogTag, and change
    local value, so able to avoid interactions to other thread.

  Problem No.3:
  - This correction changes type of LogStat to thread-local storage.
  - Each thread may have different values of LogTag, and change
    local value, so able to avoid interactions to other thread.

-- 
           Summary: syslog() may interact between threads.
           Product: glibc
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: k-makita at soft dot fujitsu dot com
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=5190

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]