Bug 923827 - coredump_filter incorrect for RELRO binaries
Summary: coredump_filter incorrect for RELRO binaries
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: kernel
Version: 18
Hardware: x86_64
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Oleg Nesterov
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2013-03-20 14:34 UTC by Jan Kratochvil
Modified: 2013-03-20 19:07 UTC (History)
6 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2013-03-20 19:07:22 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)

Description Jan Kratochvil 2013-03-20 14:34:57 UTC
Description of problem:
Either this description in kernel-doc is wrong
  - (bit 4) ELF header pages in file-backed private memory areas (it is
            effective only if the bit 2 is cleared)
or its implementation has a bug (I guess the latter).

If this bit 4 is disabled even modified readonly pages are no longer dumped.
This seems unrelated to the what bit 4 should do.

Default Fedora/RHEL settings work but if user modifies /proc/self/coredump_filter it may have unexpected results.

Version-Release number of selected component (if applicable):
FAIL: kernel-3.8.3-203.fc18.x86_64
FAIL: kernel-3.3.5-2.fc16.x86_64
FAIL: kernel-2.6.32-279.el6.x86_64

How reproducible:
Always.

Steps to Reproduce:
set +H
(set -ex;echo -e '#include<unistd.h>\nconst char a[0x2000]={0};int main(void){return pause();}' >relro.c;gcc -o relro relro.c -Wall -Wl,-z,relro;ulimit -c unlimited;echo 0x32 >/proc/self/coredump_filter;cat /proc/self/coredump_filter;./relro&p=$!;sleep 1;cat /proc/$p/smaps >relro.smaps;kill -SEGV $p)
gdb ./relro ./relro.core 
(gdb) info sharedlibrary 

Actual results:
No shared libraries loaded at this time.

Expected results:
(gdb) info sharedlibrary 
From                To                  Syms Read   Shared Object Library
0x00000037efc1f1a0  0x00000037efd60940  Yes         /lib64/libc.so.6
0x00000037ef400b20  0x00000037ef41a3d9  Yes         /lib64/ld-linux-x86-64.so.2

Additional info:

readelf -l relro
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  DYNAMIC        0x0000000000002e50 0x0000000000602e50 0x0000000000602e50
                                    ^^^^^^^^^^^^^^^^^^
                 0x0000000000000190 0x0000000000000190  RW     8
  GNU_RELRO      0x0000000000002e28 0x0000000000602e28 0x0000000000602e28
                 0x00000000000001d8 0x00000000000001d8  R      1

readelf -l core.*
Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000002000 0x0000000000602000 0x0000000000000000
                                    ^^^^^^^^^^^^^^^^^^
                 0x0000000000000000 0x0000000000001000  R      1000
                 ^^^^^^^^^^^^^^^^^^
                 Here is missing dumped the DYNAMIC segment.

relro.smaps
00602000-00603000 r--p 00002000 fc:01 323271                             /tmp/relro
Size:                  4 kB
Rss:                   4 kB
Pss:                   4 kB
Shared_Clean:          0 kB
Shared_Dirty:          0 kB
Private_Clean:         0 kB
Private_Dirty:         4 kB
Referenced:            4 kB
Anonymous:             4 kB
AnonHugePages:         0 kB
Swap:                  0 kB
KernelPageSize:        4 kB
MMUPageSize:           4 kB

GDB "gcore" implementation which dumps it correctly:
              if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0
                                  || strcmp (keyword, "Private_Dirty:") == 0
                                  || strcmp (keyword, "Swap:") == 0
                                  || strcmp (keyword, "Anonymous:") == 0))
                modified = 1;
Bug 716406 approved this is the correct behavior.

As both "Private_Dirty:"!=0 and "Anonymous:"!=0 then the page should be dumped.
But it is not, kernel should follow the Bug 716406 rules.

Comment 1 Oleg Nesterov 2013-03-20 17:58:53 UTC
Sorry Jan, I can't really help. I know absolutely nothing about elf/relro/etc.

(In reply to comment #0)
>
> Description of problem:
> Either this description in kernel-doc is wrong
>   - (bit 4) ELF header pages in file-backed private memory areas (it is
>             effective only if the bit 2 is cleared)
> or its implementation has a bug (I guess the latter).
>
> If this bit 4 is disabled even modified readonly pages are no longer dumped.

Which readonly pages? anon/mapped? shared/private?

As for bit 4, this is MMF_DUMP_ELF_HEADERS. I only know that if it is set
fs/binfmt_elf.c:vma_dump_size() can return PAGE_SIZE (rather than vma-length)
if the first word marches ELFMAG. IOW, in this case we only dump the first
page or dump nothing, unless the previous checks trigger the "whole" case.

> Steps to Reproduce:
> set +H
> (set -ex;echo -e '#include<unistd.h>\nconst char a[0x2000]={0};int
> main(void){return pause();}' >relro.c;gcc -o relro relro.c -Wall
> -Wl,-z,relro;ulimit -c unlimited;echo 0x32 >/proc/self/coredump_filter;cat
> /proc/self/coredump_filter;./relro&p=$!;sleep 1;cat /proc/$p/smaps
> >relro.smaps;kill -SEGV $p)
> gdb ./relro ./relro.core
> (gdb) info sharedlibrary
>
> Actual results:
> No shared libraries loaded at this time.

OK, 0x32 sets bits:

        1 - anonymous shared memory. Irrelevant, I guess

        4 - ELF header pages (MMF_DUMP_ELF_HEADERS above)

        5 - hugetlb private memory. Irrelevant.

So I am even more confused, you said "this bit 4 is disabled" above?    

I did

        $ echo 1 >>/proc/self/coredump_filter
        $ ./relro
        ^\Quit (core dumped)
        $ gdb ./relro ./core
        (gdb) info sharedlibrary
        From                To                  Syms Read   Shared Object Library
        0x00007ffdf7252080  0x00007ffdf733901c  Yes         /lib/libc.so.6
        0x00007ffdf7588a50  0x00007ffdf759e334  Yes         /lib64/ld-linux-x86-64.so.2

and everything looks fine with the 4th bit disabled?

In short: I am all confused.

Comment 2 Jan Kratochvil 2013-03-20 19:07:22 UTC
Sorry, I am idiot, the default coredump_filter is 0x33 so stripping bit 4 should have been 0x23 (and not 0x32).


Note You need to log in before you can comment on or make changes to this bug.