Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance dmht tcache command #4355

Merged
merged 12 commits into from
Mar 22, 2024
Merged

Enhance dmht tcache command #4355

merged 12 commits into from
Mar 22, 2024

Conversation

giridharprasath
Copy link
Contributor

@giridharprasath giridharprasath commented Mar 13, 2024

  • Add tcache heap heuristics
  • Fetch glibc version from libc.so
  • Add unit testcases for glibc version

Your checklist for this pull request

  • I've read the guidelines for contributing to this repository
  • I made sure to follow the project's coding style
  • I've documented or updated the documentation of every function and struct this PR changes. If not so I've explained why.
  • I've added tests that prove my fix is effective or that my feature works (if possible)
  • I've updated the rizin book with the relevant information (if needed)

Detailed description

  • Refactored dmht command to find tcache bins based on tls data
  • Added support for 32 and 64 bit tls parsing
  • Fetch glibc version if not available in file maps.
  • Added unit testcases for glibc version fetch.

For the program mentioned in this comment, below is the output:

[0x608f183f1244]> dmht
WARNING: unimplemented ELF/X86_64 reloc type 18
WARNING: unimplemented ELF/X86_64 reloc type 18
...
---------- Tcachebins for thread 1 ----------
---------- Tcachebins for thread 2 ----------
Tcache_bin[01]: Items: 3
 -> Chunk(addr=0x7610dc000bc0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610dc000b90, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610dc000b60, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
---------- Tcachebins for thread 3 ----------
Tcache_bin[01]: Items: 3
 -> Chunk(addr=0x7610d4000bc0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610d4000b90, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610d4000b60, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
---------- Tcachebins for thread 4 ----------
Tcache_bin[01]: Items: 3
 -> Chunk(addr=0x7610d0000bc0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610d0000b90, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x7610d0000b60, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
...
---------- Tcachebins for thread 100 ----------
Tcache_bin[01]: Items: 3
 -> Chunk(addr=0x761034000ee0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x761034000eb0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x761034000e80, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
---------- Tcachebins for thread 101 ----------
Tcache_bin[01]: Items: 3
 -> Chunk(addr=0x761038000ee0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x761038000eb0, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)
 -> Chunk(addr=0x761038000e80, size=0x30, flags=NON_MAIN_ARENA,PREV_INUSE)

Example code:

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

void *thread1(void *vargp)
{
	char* a = (char*) malloc(40);
	char* b = (char*) malloc(40);
	char* c = (char*) malloc(40);
	char* d = (char*) malloc(40);
	free(a);
	free(b);
	free(c);
	free(d);
	a = (char*) malloc(40);
	b = (char*) malloc(40);
	c = (char*) malloc(40);
	d = (char*) malloc(40);
	sleep(100);
	return NULL;
}

int main()
{
	pthread_t thread[100];
	for (int i = 0; i < 100; i++){
		pthread_create(&thread[i], NULL, thread1, NULL);
	}
	sleep(1);
	__builtin_trap();
	exit(0);
}

Output:

[0x5fe7d6869296]> dmht
WARNING: unimplemented ELF/X86_64 reloc type 18
....
---------- Tcachebins for thread 1 ----------
---------- Tcachebins for thread 2 ----------
---------- Tcachebins for thread 3 ----------
---------- Tcachebins for thread 4 ----------
---------- Tcachebins for thread 5 ----------
---------- Tcachebins for thread 6 ----------
---------- Tcachebins for thread 7 ----------
...
---------- Tcachebins for thread 98 ----------
---------- Tcachebins for thread 99 ----------
---------- Tcachebins for thread 100 ----------
---------- Tcachebins for thread 101 ----------

Test plan

Wrote testcases for glibc version parsing.
...

Closing issues

Fixes #1259

PS: Main idea is from pwndbg heap heuristics module

@giridharprasath
Copy link
Contributor Author

Regression is failing for dmht command.

WARNING: unimplemented ELF/X86_64 reloc type 18: this is not addressed yet.
This is being hit from reloc_convert function where rel->type == RZ_X86_64_TPOFF64.

librz/include/rz_debug.h Outdated Show resolved Hide resolved
Copy link
Member

@wargio wargio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well done. i have added some comments which should improve slightly the code, but overall looks very good.

XVilka

This comment was marked as resolved.

@XVilka

This comment was marked as resolved.

@XVilka

This comment was marked as resolved.

librz/debug/p/native/linux/linux_debug.c Outdated Show resolved Hide resolved
librz/debug/p/native/linux/linux_debug.c Outdated Show resolved Hide resolved
@giridharprasath
Copy link
Contributor Author

Indirect leak of 153 byte(s) in 9 object(s) allocated from:
    #0 0x7f69b746c32a in __interceptor_strdup /usr/src/debug/gcc/gcc/libsanitizer/asan/asan_interceptors.cpp:454
    #1 0x7f69aad23c6c in convert_import (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xb23c6c) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #2 0x7f69aad36d06 in relocs (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xb36d06) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #3 0x7f69aac9ec34 in rz_bin_set_and_process_relocs (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa9ec34) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #4 0x7f69aac94fee in rz_bin_object_process_plugin_data (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa94fee) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #5 0x7f69aac926a0 in rz_bin_object_new (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa926a0) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #6 0x7f69aac691ee in rz_bin_file_new_from_buffer (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa691ee) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #7 0x7f69aac77185 in rz_bin_open_buf (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa77185) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #8 0x7f69aac789d5 in rz_bin_open_io (/home/z3phyr/personal/rizin/build/librz/bin/librz_bin.so.0.8+0xa789d5) (BuildId: 8f5210242ac946677b0c2b190bacfb113b4edae5)
    #9 0x7f69b625271d in rz_get_glibc_version_64 (/home/z3phyr/personal/rizin/build/librz/core/librz_core.so.0.8+0xe5271d) (BuildId: 6b18397fd428f12501a33ccd4ec493111691a05e)
    #10 0x55c08c7737e8 in test_get_glibc_version (/home/z3phyr/personal/rizin/build/test/unit/test_glibc_version+0x27e8) (BuildId: adc47f0e0b2eb76b84091785dcd4f2d34ce66ff8)
    #11 0x55c08c773b9e in all_tests (/home/z3phyr/personal/rizin/build/test/unit/test_glibc_version+0x2b9e) (BuildId: adc47f0e0b2eb76b84091785dcd4f2d34ce66ff8)
    #12 0x55c08c77329a in main (/home/z3phyr/personal/rizin/build/test/unit/test_glibc_version+0x229a) (BuildId: adc47f0e0b2eb76b84091785dcd4f2d34ce66ff8)
    #13 0x7f69b5243ccf  (/usr/lib/libc.so.6+0x25ccf) (BuildId: c0caa0b7709d3369ee575fcd7d7d0b0fc48733af)



Looking into this issue, the same code block is invoked from get_va_symbol too

@XVilka

This comment was marked as resolved.

librz/debug/p/debug_native.c Show resolved Hide resolved
librz/debug/p/native/linux/linux_debug.c Show resolved Hide resolved
Copy link
Member

@XVilka XVilka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Various small things but apart from those - LGTM.

librz/core/linux_heap_glibc.c Outdated Show resolved Hide resolved
librz/core/linux_heap_glibc.c Outdated Show resolved Hide resolved
librz/core/linux_heap_glibc.c Outdated Show resolved Hide resolved
librz/core/linux_heap_glibc.c Outdated Show resolved Hide resolved
librz/include/rz_debug.h Outdated Show resolved Hide resolved
librz/debug/p/native/linux/linux_debug.c Outdated Show resolved Hide resolved
@XVilka XVilka requested a review from wargio March 21, 2024 14:07
@wargio wargio merged commit de4a3c7 into rizinorg:dev Mar 22, 2024
44 checks passed
@wargio
Copy link
Member

wargio commented Mar 22, 2024

@giridharprasath this broke PowerPC builds:

../librz/debug/p/native/linux/linux_debug.c: In function ‘get_linux_tls_val’:

../librz/debug/p/native/linux/linux_debug.c:898:14: error: ‘struct powerpc_regs_t’ has no member named ‘gs_base’

  898 |    tls = regs.gs_base;

      |              ^

../librz/debug/p/native/linux/linux_debug.c: In function ‘linux_thread_list’:

../librz/debug/p/native/linux/linux_debug.c:969:16: error: ‘struct powerpc_regs_t’ has no member named ‘gs_base’

  969 |      tls = regs.gs_base;

      |                ^

and ARM:

../librz/debug/p/native/linux/linux_debug.c: In function ‘get_linux_tls_val’:

../librz/debug/p/native/linux/linux_debug.c:897:28: error: ‘PTRACE_GETREGS’ undeclared (first use in this function); did you mean ‘PTRACE_GETREGSET’?

  897 |   if (rz_debug_ptrace(dbg, PTRACE_GETREGS, dbg->tid, NULL, &regs) != -1) {

      |                            ^~~~~~~~~~~~~~

      |                            PTRACE_GETREGSET

and SystemZ:

../librz/debug/p/native/linux/linux_debug.c: In function ‘get_linux_tls_val’:

../librz/debug/p/native/linux/linux_debug.c:897:28: error: ‘PTRACE_GETREGS’ undeclared (first use in this function); did you mean ‘PTRACE_GETREGSET’?

  897 |   if (rz_debug_ptrace(dbg, PTRACE_GETREGS, dbg->tid, NULL, &regs) != -1) {

      |                            ^~~~~~~~~~~~~~

      |                            PTRACE_GETREGSET

../librz/debug/p/native/linux/linux_debug.c:897:28: note: each undeclared identifier is reported only once for each function it appears in

../librz/debug/p/native/linux/linux_debug.c:898:14: error: ‘struct _user_regs_struct’ has no member named ‘gs_base’

  898 |    tls = regs.gs_base;

      |              ^

../librz/debug/p/native/linux/linux_debug.c: In function ‘linux_thread_list’:

../librz/debug/p/native/linux/linux_debug.c:968:30: error: ‘PTRACE_GETREGS’ undeclared (first use in this function); did you mean ‘PTRACE_GETREGSET’?

  968 |     if (rz_debug_ptrace(dbg, PTRACE_GETREGS, dbg->tid, NULL, &regs) != -1) {

      |                              ^~~~~~~~~~~~~~

      |                              PTRACE_GETREGSET

../librz/debug/p/native/linux/linux_debug.c:969:16: error: ‘struct _user_regs_struct’ has no member named ‘gs_base’

  969 |      tls = regs.gs_base;

      |                ^

Please check the following link: https://github.com/rizinorg/rizin/runs/22962762398

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants