Control: tags -1 + upstream patch
Dear Maintainer, I tried to have a look into this issue and guess I found something. It looks like the application is exhausting its stack by allocation an integer array with maxpid elements. At least in my test VM this leads to 16 MB array size, while stack has just a size of 8 MB. Attached patch allocates two such arrays from the heap. With this "unhide brute" could finish without crash. Another workaround would be to increase stacksize by "ulimit -s 40960" before running unhide. Kind regards, Bernhard
dmesg by submitter: Nov 30 01:39:48 heisenberg kernel: unhide[208429]: segfault at 7ffd06cfec58 ip 000055c15aa077d3 sp 00007ffd06cfec60 error 6 in unhide-linux[55c15aa07000+6000] Nov 30 01:39:48 heisenberg kernel: Code: 00 48 89 45 c8 31 c0 48 63 05 5d 98 00 00 48 8d 04 85 0f 00 00 00 48 83 e0 f0 48 29 c4 48 89 65 98 48 29 c4 31 c0 48 89 65 90 <e8> d8 3e 00 00 31 c0 66 0f 1f 44 00 00 48 8b 4d 98 48 8b 55 90 c7 /* * Page fault error code bits: * * bit 0 == 0: no page found 1: protection fault * bit 1 == 0: read access 1: write access * bit 2 == 0: kernel-mode access 1: user-mode access * bit 3 == 1: use of reserved bit detected * bit 4 == 1: fault was an instruction fetch * bit 5 == 1: protection keys block access */ enum x86_pf_error_code { PF_PROT = 1 << 0, PF_WRITE = 1 << 1, PF_USER = 1 << 2, PF_RSVD = 1 << 3, PF_INSTR = 1 << 4, PF_PK = 1 << 5, }; arch/x86/mm/fault.c: printk("%s%s[%d]: segfault at %lx ip %px sp %px error %lx", "error 6" == 0x6 == 0b110 bit 0 == 0: no page found bit 1 == 1: write access bit 2 == 1: user-mode access bit 3 == 0: bit 4 == 0: bit 5 == 0: # Bullseye/testing amd64 qemu VM 2019-12-03 apt update apt dist-upgrade apt install systemd-coredump mc devscripts dpkg-dev gdb unhide unhide-dbgsym mkdir /home/benutzer/source/unhide/orig -p cd /home/benutzer/source/unhide/orig apt source unhide cd gdb -q --args unhide set width 0 set pagination off directory /home/benutzer/source/unhide/orig/unhide-20130526 b main run dele 1 info target find /b 0x00005555555563e0, 0x000055555555b001, 0x00, 0x48, 0x89, 0x45, 0xc8, 0x31, 0xc0, 0x48, 0x63, 0x05, 0x5d, 0x98, 0x00, 0x00, 0x48, 0x8d, 0x04, 0x85, 0x0f, 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0xf0, 0x48, 0x29, 0xc4, 0x48, 0x89, 0x65, 0x98, 0x48, 0x29, 0xc4, 0x31, 0xc0, 0x48, 0x89, 0x65, 0x90, 0xe8, 0xd8, 0x3e, 0x00, 0x00, 0x31, 0xc0, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x98, 0x48, 0x8b, 0x55, 0x90, 0xc7 root@debian:~# gdb -q --args unhide Reading symbols from unhide... Reading symbols from /usr/lib/debug/.build-id/41/d7d39535f738606ad3acf0611a8397925762b3.debug... (gdb) set width 0 (gdb) set pagination off (gdb) directory /home/benutzer/source/unhide/orig/unhide-20130526 Source directories searched: /home/benutzer/source/unhide/orig/unhide-20130526:$cdir:$cwd (gdb) b main Breakpoint 1 at 0x23e0: file /usr/include/x86_64-linux-gnu/bits/stdio2.h, line 107. (gdb) run Starting program: /usr/sbin/unhide [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Breakpoint 1, main (argc=1, argv=0x7fffffffed18) at /usr/include/x86_64-linux-gnu/bits/stdio2.h:107 warning: Source file is more recent than executable. 107 return __printf_chk (__USE_FORTIFY_LEVEL - 1, __fmt, __va_arg_pack ()); (gdb) dele 1 (gdb) info target Symbols from "/usr/sbin/unhide-linux". Native process: Using the running image of child Thread 0x7ffff7de5740 (LWP 13520). While running this, GDB does not access memory from... Local exec file: `/usr/sbin/unhide-linux', file type elf64-x86-64. Entry point: 0x555555556660 ... 0x00005555555563e0 - 0x000055555555b001 is .text ... (gdb) find /b 0x00005555555563e0, 0x000055555555b001, 0x00, 0x48, 0x89, 0x45, 0xc8, 0x31, 0xc0, 0x48, 0x63, 0x05, 0x5d, 0x98, 0x00, 0x00, 0x48, 0x8d, 0x04, 0x85, 0x0f, 0x00, 0x00, 0x00, 0x48, 0x83, 0xe0, 0xf0, 0x48, 0x29, 0xc4, 0x48, 0x89, 0x65, 0x98, 0x48, 0x29, 0xc4, 0x31, 0xc0, 0x48, 0x89, 0x65, 0x90, 0xe8, 0xd8, 0x3e, 0x00, 0x00, 0x31, 0xc0, 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00, 0x48, 0x8b, 0x4d, 0x98, 0x48, 0x8b, 0x55, 0x90, 0xc7 0x5555555567a9 <brute+41> 1 pattern found. (gdb) b *(0x5555555567a9 + 42) Breakpoint 3 at 0x5555555567d3: file unhide-linux-bruteforce.c, line 73. (gdb) x/10xb 0x5555555567d3 0x5555555567d3 <brute+83>: 0xe8 0xd8 0x3e 0x00 0x00 0x31 0xc0 0x66 0x5555555567db <brute+91>: 0x0f 0x1f (gdb) info b Num Type Disp Enb Address What 3 breakpoint keep y 0x00005555555567d3 in brute at unhide-linux-bruteforce.c:73 (gdb) list unhide-linux-bruteforce.c:73 68 int allpids2[maxpid] ; 69 int x; 70 int y; 71 int z; 72 73 msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS with fork()\n") ; 74 75 // PID under 301 are reserved for kernel 76 for(x=0; x < 301; x++) 77 { (gdb) disassemble brute Dump of assembler code for function brute: 0x0000555555556780 <+0>: push %rbp 0x0000555555556781 <+1>: lea 0x5880(%rip),%rdx # 0x55555555c008 0x0000555555556788 <+8>: xor %esi,%esi 0x000055555555678a <+10>: mov %rsp,%rbp 0x000055555555678d <+13>: push %r15 0x000055555555678f <+15>: push %r14 0x0000555555556791 <+17>: push %r13 0x0000555555556793 <+19>: push %r12 0x0000555555556795 <+21>: push %rbx 0x0000555555556796 <+22>: sub $0x68,%rsp 0x000055555555679a <+26>: mov 0x3a38f(%rip),%rdi # 0x555555590b30 <unlog> 0x00005555555567a1 <+33>: mov %fs:0x28,%rax 0x00005555555567aa <+42>: mov %rax,-0x38(%rbp) 0x00005555555567ae <+46>: xor %eax,%eax 0x00005555555567b0 <+48>: movslq 0x985d(%rip),%rax # 0x555555560014 <maxpid> 0x00005555555567b7 <+55>: lea 0xf(,%rax,4),%rax 0x00005555555567bf <+63>: and $0xfffffffffffffff0,%rax 0x00005555555567c3 <+67>: sub %rax,%rsp 0x00005555555567c6 <+70>: mov %rsp,-0x68(%rbp) 0x00005555555567ca <+74>: sub %rax,%rsp 0x00005555555567cd <+77>: xor %eax,%eax 0x00005555555567cf <+79>: mov %rsp,-0x70(%rbp) 0x00005555555567d3 <+83>: callq 0x55555555a6b0 <msgln> <<<<<<<<<<<<<<< 0x00005555555567d8 <+88>: xor %eax,%eax 0x00005555555567da <+90>: nopw 0x0(%rax,%rax,1) 0x00005555555567e0 <+96>: mov -0x68(%rbp),%rcx 0x00005555555567e4 <+100>: mov -0x70(%rbp),%rdx ... ########## gdb -q --args unhide brute set width 0 set pagination off set backtrace past-main directory /home/benutzer/source/unhide/orig/unhide-20130526 b *(brute +83) run root@debian:~# gdb -q --args unhide brute Reading symbols from unhide... Reading symbols from /usr/lib/debug/.build-id/41/d7d39535f738606ad3acf0611a8397925762b3.debug... (gdb) set width 0 (gdb) set pagination off (gdb) directory /home/benutzer/source/unhide/orig/unhide-20130526 Source directories searched: /home/benutzer/source/unhide/orig/unhide-20130526:$cdir:$cwd (gdb) b brute Breakpoint 1 at 0x2780: file unhide-linux-bruteforce.c, line 65. (gdb) run Starting program: /usr/sbin/unhide brute [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Unhide 20130526 Copyright © 2013 Yago Jesus & Patrick Gouin License GPLv3+ : GNU GPL version 3 or later http://www.unhide-forensics.info NOTE : This version of unhide is for systems using Linux >= 2.6 Used options: Breakpoint 1, brute () at unhide-linux-bruteforce.c:65 65 { (gdb) b *(brute +83) Breakpoint 2 at 0x5555555567d3: file unhide-linux-bruteforce.c, line 73. (gdb) dele 1 (gdb) cont Continuing. Breakpoint 2, brute () at unhide-linux-bruteforce.c:73 73 msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS with fork()\n") ; (gdb) stepi Program received signal SIGSEGV, Segmentation fault. brute () at unhide-linux-bruteforce.c:73 73 msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS with fork()\n") ; (gdb) bt #0 brute () at unhide-linux-bruteforce.c:73 #1 0x00005555555565c9 in main (argc=argc@entry=2, argv=argv@entry=0x7fffffffecf8) at unhide-linux.c:787 #2 0x00007ffff7e0ebbb in __libc_start_main (main=0x5555555563e0 <main>, argc=2, argv=0x7fffffffecf8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffece8) at ../csu/libc-start.c:308 #3 0x000055555555668a in _start () (gdb) display/i $pc 1: x/i $pc => 0x5555555567d3 <brute+83>: callq 0x55555555a6b0 <msgln> (gdb) info frame 0 Stack frame at 0x7fffffffebf0: rip = 0x5555555567d3 in brute (unhide-linux-bruteforce.c:73); saved rip = 0x5555555565c9 called by frame at 0x7fffffffec20 source language c. Arglist at 0x7ffffdffeb50, args: Locals at 0x7ffffdffeb50, Previous frame's sp is 0x7fffffffebf0 Saved registers: rbx at 0x7fffffffebb8, rbp at 0x7fffffffebe0, r12 at 0x7fffffffebc0, r13 at 0x7fffffffebc8, r14 at 0x7fffffffebd0, r15 at 0x7fffffffebd8, rip at 0x7fffffffebe8 (gdb) info frame 1 Stack frame at 0x7fffffffec20: rip = 0x5555555565c9 in main (unhide-linux.c:787); saved rip = 0x7ffff7e0ebbb called by frame at 0x7fffffffece0, caller of frame at 0x7fffffffebf0 source language c. Arglist at 0x7fffffffebe8, args: argc=argc@entry=2, argv=argv@entry=0x7fffffffecf8 Locals at 0x7fffffffebe8, Previous frame's sp is 0x7fffffffec20 Saved registers: rbx at 0x7fffffffebf8, rbp at 0x7fffffffec00, r12 at 0x7fffffffec08, r13 at 0x7fffffffec10, rip at 0x7fffffffec18 (gdb) info frame 2 Stack frame at 0x7fffffffece0: rip = 0x7ffff7e0ebbb in __libc_start_main (../csu/libc-start.c:308); saved rip = 0x55555555668a called by frame at 0x0, caller of frame at 0x7fffffffec20 source language c. Arglist at 0x7fffffffec18, args: main=0x5555555563e0 <main>, argc=2, argv=0x7fffffffecf8, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffece8 Locals at 0x7fffffffec18, Previous frame's sp is 0x7fffffffece0 Saved registers: rbx at 0x7fffffffecb0, rbp at 0x7fffffffecb8, r12 at 0x7fffffffecc0, r13 at 0x7fffffffecc8, r14 at 0x7fffffffecd0, rip at 0x7fffffffecd8 (gdb) info frame 3 Stack frame at 0x0: rip = 0x55555555668a in _start; saved rip = <not saved> Outermost frame: outermost caller of frame at 0x7fffffffece0 Arglist at 0x7fffffffecd8, args: Locals at 0x7fffffffecd8, Previous frame's sp is 0x7fffffffece8 https://stackoverflow.com/questions/37321252/check-used-stack-size-using-core-file/37327019 (gdb) print (char *)_environ - (char *)$sp $1 = 33554880 (gdb) print/x (char *)_environ - (char *)$sp $2 = 0x20001c0 (gdb) print/x maxpid $4 = 0x400000 (gdb) print/x sizeof(allpids2[0]) $5 = 0x4 (gdb) print/x sizeof(allpids2[0]) * maxpid $6 = 0x1000000 (gdb) print sizeof(allpids2[0]) * maxpid $7 = 16777216 (gdb) print (sizeof(allpids2[0]) * maxpid)/1024 $8 = 16384 (gdb) print (sizeof(allpids2[0]) * maxpid)/1024/1024 $9 = 16 root@debian:~# ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 11863 max locked memory (kbytes, -l) 65536 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 <<<<<<<<<<< Just 8 MB stack size, but array allpids2 has 16 MB of size cpu time (seconds, -t) unlimited max user processes (-u) 11863 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
Description: Allocate pid arrays from the stack Author: Bernhard Ãbelacker <bernha...@mailbox.org> Bug-Debian: https://bugs.debian.org/945864 Forwarded: no Last-Update: 2019-12-03 --- unhide-20130526.orig/unhide-linux-bruteforce.c +++ unhide-20130526/unhide-linux-bruteforce.c @@ -64,14 +64,20 @@ void *funcionThread (void *parametro) void brute(void) { int i=0; - int allpids[maxpid] ; - int allpids2[maxpid] ; + int* allpids; + int* allpids2; int x; int y; int z; msgln(unlog, 0, "[*]Starting scanning using brute force against PIDS with fork()\n") ; + allpids = malloc(sizeof(int)*maxpid) ; + allpids2 = malloc(sizeof(int)*maxpid) ; + if (!allpids || !allpids2) { + die(unlog, "Error: Cannot allocate pid arrays ! Exiting."); + } + // PID under 301 are reserved for kernel for(x=0; x < 301; x++) { @@ -214,4 +220,7 @@ void brute(void) } } } + + free(allpids); + free(allpids2); }