Bug 1519182

Summary: Error messages generated by glibc will not be redirected in Shell
Product: Red Hat Enterprise Linux 7 Reporter: Steffen Froemer <sfroemer>
Component: glibcAssignee: glibc team <glibc-bugzilla>
Status: CLOSED NOTABUG QA Contact: qe-baseos-tools-bugs
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 7.4CC: ashankar, fweimer, mnewsome, pfrankli
Target Milestone: rc   
Target Release: ---   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2017-11-30 11:01:41 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Steffen Froemer 2017-11-30 10:57:18 UTC
Description of problem:
If an application triggers some strange behavior in  glibc, and latter will generate error messages, these messages will not be redirected when using error redirection.


Version-Release number of selected component (if applicable):
glibc-2.17-157.el7.x86_64

How reproducible:
bash-4.2.46-20.el7_2.x86_64


Steps to Reproduce:
1. create a simple c-application

   <<<
   #include<stdio.h>
   #include<stdlib.h>

   int main()
   {
       char* ptr = (char*)malloc(sizeof("test"));
       char array[]= "test";
       ptr = array;
       free(ptr);
       return 0;
   }

2. compile it with `gcc -o foo`
3. run `./foo 2>&1 >std.out`

Actual results:

$ ./foo 2>&1 >std.out                                                                                                                                                                                               
*** Error in `./foo': munmap_chunk(): invalid pointer: 0x00007ffc44577180 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7ada4)[0x7f72c6bc2da4]
./foo[0x4005b2]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f72c6b69b35]
./foo[0x4004b9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:00 16797798                           /home/vagrant/foo
00600000-00601000 r--p 00000000 fd:00 16797798                           /home/vagrant/foo
00601000-00602000 rw-p 00001000 fd:00 16797798                           /home/vagrant/foo
02376000-02397000 rw-p 00000000 00:00 0                                  [heap]
7f72c6932000-7f72c6947000 r-xp 00000000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6947000-7f72c6b46000 ---p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b46000-7f72c6b47000 r--p 00014000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b47000-7f72c6b48000 rw-p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b48000-7f72c6cfe000 r-xp 00000000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6cfe000-7f72c6efe000 ---p 001b6000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6efe000-7f72c6f02000 r--p 001b6000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6f02000-7f72c6f04000 rw-p 001ba000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6f04000-7f72c6f09000 rw-p 00000000 00:00 0
7f72c6f09000-7f72c6f29000 r-xp 00000000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c711c000-7f72c711f000 rw-p 00000000 00:00 0
7f72c7126000-7f72c7128000 rw-p 00000000 00:00 0
7f72c7128000-7f72c7129000 r--p 0001f000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c7129000-7f72c712a000 rw-p 00020000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c712a000-7f72c712b000 rw-p 00000000 00:00 0
7ffc44558000-7ffc44579000 rw-p 00000000 00:00 0                          [stack]
7ffc44587000-7ffc44589000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

$ cat std.out
<empty>



Expected results:
When using error redirection, it's expected by users, that any kind of error message will be included in the target.

$ ./foo 2>&1 >std.out                                                                                                                                                                                               
$ cat std.out
*** Error in `./foo': munmap_chunk(): invalid pointer: 0x00007ffc44577180 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7ada4)[0x7f72c6bc2da4]
./foo[0x4005b2]
/lib64/libc.so.6(__libc_start_main+0xf5)[0x7f72c6b69b35]
./foo[0x4004b9]
======= Memory map: ========
00400000-00401000 r-xp 00000000 fd:00 16797798                           /home/vagrant/foo
00600000-00601000 r--p 00000000 fd:00 16797798                           /home/vagrant/foo
00601000-00602000 rw-p 00001000 fd:00 16797798                           /home/vagrant/foo
02376000-02397000 rw-p 00000000 00:00 0                                  [heap]
7f72c6932000-7f72c6947000 r-xp 00000000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6947000-7f72c6b46000 ---p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b46000-7f72c6b47000 r--p 00014000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b47000-7f72c6b48000 rw-p 00015000 fd:00 84                         /usr/lib64/libgcc_s-4.8.5-20150702.so.1
7f72c6b48000-7f72c6cfe000 r-xp 00000000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6cfe000-7f72c6efe000 ---p 001b6000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6efe000-7f72c6f02000 r--p 001b6000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6f02000-7f72c6f04000 rw-p 001ba000 fd:00 64394                      /usr/lib64/libc-2.17.so
7f72c6f04000-7f72c6f09000 rw-p 00000000 00:00 0
7f72c6f09000-7f72c6f29000 r-xp 00000000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c711c000-7f72c711f000 rw-p 00000000 00:00 0
7f72c7126000-7f72c7128000 rw-p 00000000 00:00 0
7f72c7128000-7f72c7129000 r--p 0001f000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c7129000-7f72c712a000 rw-p 00020000 fd:00 64387                      /usr/lib64/ld-2.17.so
7f72c712a000-7f72c712b000 rw-p 00000000 00:00 0
7ffc44558000-7ffc44579000 rw-p 00000000 00:00 0                          [stack]
7ffc44587000-7ffc44589000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


Additional info:

Some insight can be found here: https://stackoverflow.com/questions/7085360/squelching-glibc-memory-corruption-stack-trace-output


glibc errors gets written specifically to /dev/tty, unless you have set the environment variable LIBC_FATAL_STDERR_. I'm not sure this is documented anywhere, but the relevant code can be found here.


https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/libc_fatal.c;h=e1b4c8d314dcc80dd227721062c43f7564b31ade;hb=356f8bc660a154a07b03da7c536831da5c8f74fe#l51

  51 /* Abort with an error message.  */
  52 void
  53 __libc_message (int do_abort, const char *fmt, ...)
  54 {
  55   va_list ap;
  56   va_list ap_copy;
  57   int fd = -1;
  58 
  59   va_start (ap, fmt);
  60   va_copy (ap_copy, ap);
  61 
  62 #ifdef FATAL_PREPARE
  63   FATAL_PREPARE;
  64 #endif
  65 
  66   /* Open a descriptor for /dev/tty unless the user explicitly
  67      requests errors on standard error.  */
  68   const char *on_2 = __secure_getenv ("LIBC_FATAL_STDERR_");
  69   if (on_2 == NULL || *on_2 == '\0')
  70     fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
  71 
  72   if (fd == -1)
  73     fd = STDERR_FILENO;
  74

Comment 2 Florian Weimer 2017-11-30 11:01:41 UTC
This is deliberately done to prevent leaking potentially sensitive data into other processes along a shell pipeline.

Note that future versions of glibc will drastically reduce the amount of diagnostic data printed once corruption (stack corruption, heap corruption, buffer overflow attempt) is detected.  Please let us know if you have a use case which needs this output.

Our recommendation is to rely on coredump and automated coredump analysis tools (so that the full dump never has to be written to disk).

Comment 3 Florian Weimer 2017-11-30 11:06:46 UTC
I forgot to mention that there are various tools to capture terminal output, such as script.

Tracking commands with a non-zero exit status might also help.  This is also needed to capture segmentation faults, which do not trigger any output at all (and all these corruptions can easily result in segmentation faults instead of glibc error messages due to the heuristic nature of the detection mechanisms).