Bug 26100 - Race in syslog(3) with regards to tag printing.
Summary: Race in syslog(3) with regards to tag printing.
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: 2.22
: P2 normal
Target Milestone: 2.33
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-06-09 16:32 UTC by Jaroslav Jindrak
Modified: 2024-09-09 09:21 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jaroslav Jindrak 2020-06-09 16:32:11 UTC
Hello, when syslog(3) prints a message, it goes through the following piece of code to determine whether the different parts of the message should be printed:

misc/syslog.c (comments mine):
>   if (LogTag == NULL)
>     LogTag = __progname;
>   if (LogTag != NULL) // This evaluates to true.
>     __fputs_unlocked (LogTag, f); 
>   if (LogStat & LOG_PID)
>     fprintf (f, "[%d]", (int) __getpid ());
> 
>   // Imagine LogTag gets set to NULL by closelog()
>   // called in another thread.
> 
>   if (LogTag != NULL) // This evaluates to false.
>     {   
>       putc_unlocked (':', f); 
>       putc_unlocked (' ', f); 
>     }

As the comments in the snippet say, it is possible for LogTag to be reset to NULL after a tag (either user supplied value or __progname) was printed into the membuffer. However, this means that the last condition evaluates to false and the ': ' separator between the tag and the message is not printed, resulting in a mangled output to the system log (which may e.g. confuse processes grepping the log).

This happens in our glibc-2.22, but as the code does not differ in the mainline version of glibc I think it is also affected.

An example proposed patch from me would be:

Index: glibc-2.22/misc/syslog.c
===================================================================
--- glibc-2.22.orig/misc/syslog.c
+++ glibc-2.22/misc/syslog.c
@@ -201,11 +201,15 @@ __vsyslog_chk(int pri, int flag, const c
 	    msgoff = ftell (f);
 	    if (LogTag == NULL)
 	      LogTag = __progname;
+	    int used_tag = 0;
 	    if (LogTag != NULL)
-	      __fputs_unlocked (LogTag, f);
+	      {
+	        __fputs_unlocked (LogTag, f);
+	        used_tag = 1;
+	      }
 	    if (LogStat & LOG_PID)
 	      fprintf (f, "[%d]", (int) __getpid ());
-	    if (LogTag != NULL)
+	    if (used_tag)
 	      {
 		putc_unlocked (':', f);
 		putc_unlocked (' ', f);



A third party that reported the bug to us has verified that this patch fixed the issue for them. Whenever syslog outputs a tag (be it a custom value or __progname), this patch makes sure that the ': ' separator is also printed.
Comment 1 Andreas Schwab 2020-08-18 09:30:01 UTC
Fixed in 2.33.
Comment 2 Florian Weimer 2024-09-09 09:21:17 UTC
Fixed via:

commit c4e4b2e149705559d28b16a9b47ba2f6142d6a6c
Author: Andreas Schwab <schwab@suse.de>
Date:   Tue Jun 23 12:55:49 2020 +0200

    Correct locking and cancellation cleanup in syslog functions (bug 26100)
    
    Properly serialize the access to the global state shared between the
    syslog functions, to avoid races in multithreaded processes.  Protect a
    local allocation in the __vsyslog_internal function from leaking during
    cancellation.