Reading user-space address address when debugging kext - macos

I'd like to read user space address from lldb when debugging remote machine driver (kext) via kdp. I know that in code I could use copyin in order to move the code to kernel space and read it easily, so as expected when I've tried to read user memory directly it failed :
(lldb) memory read 0x000070000d15a024
error: kdp read memory failed (error 4)
is there some alternative to copyin during runtime debugging session to convert my data somewhere I could read it from the debugger ?
thanks

Assuming you load the debug scripts for the specific kernel you use (should be in the appropriate KDK), you have the printuserdata command.
This is its description:
printuserdata:
Read userspace data for given task and print based on format provided.
Syntax: (lldb) printuserdata <task_t> <uspace_address> <format_specifier>
params:
<task_t> : pointer to task
<uspace_address> : address to user space memory
<format_specifier> : String representation for processing the data and printing it.
e.g Q -> unsigned long long, q -> long long, I -> unsigned int, i -> int
10i -> 10 ints, 20s -> 20 character string, s -> null terminated string
See: https://docs.python.org/2/library/struct.html#format-characters
options:
-X : print all values in hex.
-O <file path>: Save data to file
Example invocation:
(lldb) printuserdata 0xffffff8013257d80 0x00007fff941f5000 10c

Related

Perf cannot use symbol from kernel module

I want to trace a kernel module I've written using Intel PT but I can not get perf to recognize symbols from my kernel modules. For the sake of simplicity, I tried tracing a module that periodically prints a string to the log, using perf record -e intel_pt// -a --filter 'filter print_hello' sleep 1. This results in the following error:
Kernel symbol lookup: Symbol 'print_hello' not found.
Note that symbols must be functions.
Failed to parse address filter: 'filter print_hello'
Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [#<file name>]
Where multiple filters are separated by space or comma.
Recording without a filter using perf record -a -e intel_pt//k sleep 1 and then grep'ing the perf script output for print_hello does not return anything either.
However, perf kallsyms print_hello returns
print_hello: [hello_periodic] /lib/modules/5.4.161/extra/hello-periodic.ko 0xffffffffc07af07c-0xffffffffc07af0b6 (0x7c-0xb6)
so I assume perf can find the symbol after all.
Why could this happen?
A workaround is possible:
perf record -e intel_pt// -a "$(printf 'filter print_hello\t[hello_periodic]')" sleep 1
Or just use numbers:
perf record -e intel_pt// -a --filter 'filter 0xffffffffc07af07c/0x3a' sleep 1
However, at least kernel v5.18 is probably needed because it has commit c243cecb58e3 ("perf/x86/intel/pt: Relax address filter validation")
For perf help, also try the linux perf users mailing list:
linux-perf-users#vger.kernel.org
and mail archive at:
https://lore.kernel.org/linux-perf-users/
For general information, the kernel perf wiki:
https://perf.wiki.kernel.org
And for Intel PT, the Intel PT wiki page:
https://perf.wiki.kernel.org/index.php/Perf_tools_support_for_Intel%C2%AE_Processor_Trace

Code not running in Hackerrank though it is running in onlinegdb

The main topic is to write a code in C++ for Hash with Chaining (using single link list).here, data has been provided in terms of array of long datatype and we have to store them in hash(table size 13) in a sorted manner.
Here is my code for the same.
https://onlinegdb.com/B1pbgjxAI
There is no compiler error in the code but while running the code the following error arises.
*** buffer overflow detected ***: ./Solution terminated
Reading symbols from Solution...done.
[New LWP 86657]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./Solution'.
Program terminated with signal SIGABRT, Aborted.
#0 __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
To enable execution of this file add
add-auto-load-safe-path /usr/local/lib64/libstdc++.so.6.0.25-gdb.py
line to your configuration file "//.gdbinit".
To completely disable this security protection add
set auto-load safe-path /
line to your configuration file "//.gdbinit".
For more information about this security protection see the
"Auto-loading safe path" section in the GDB manual. E.g., run from the shell:
info "(gdb)Auto-loading safe path"
Here, for the testcase, input is
201911169
and the output should be
93
In line 36 you're calling strcpy(p->name,Name), but Name is passed from x in main, and char x[4] isn't null-terminated as you only assign to x[j] for j from 2 downto 0. Add a statement x[3] = '\0';.

Is it possible to log the output of a uboot command into a file from u-boot prompt?

I am working with an embedded board which supports u-boot.
I am trying to write and read the emmc device connected to the board,
After read, i need to have a look at the contents and compare it with the data that I have written to it.
Is there a way I can log the output of the a u-boot command, when I read a block from eMMC and store it in an address and try to view the contents of
it using:
mmc read 0x10700000 133120 1
mm.l 0x10700000
into a file and then can store the file in an emmc partition or a tftp server ?
Thank you for your time,
Nishad
The save command can be used to write memory to a file.
save file to a filesystem
save <interface> <dev[:part]> <addr> <filename> bytes [pos]
- Save binary file 'filename' to partition 'part' on device
type 'interface' instance 'dev' from addr 'addr' in memory.
'bytes' gives the size to save in bytes and is mandatory.
'pos' gives the file byte position to start writing to.
If 'pos' is 0 or omitted, the file is written from the start.
Of cause this requires the file system to be writable. For FAT this implies building with CONFIG_FAT_WRITE=y.

Make valgrind stop immediately after first error

my program processes large errors and during development in produces large amount of output on the console. It suffers from memory corruption and I try to use valgrind to locate the error.
Unfortunately, i can't find the error messages among the output lines, and they flushing by too fast to cancel execution when they pop up. They have to be there in order to locate the error ( which element does cause the error and so on ). Redirecting then within my program doesn't work, just like piping the output does only redirect the program output, not the valgrind output.
Can you give me a hint how to solve this.
In addition to redirecting both program and Valgrind output to a file (as already suggested), you can use --db-attach=yes flag, which will cause your program to stop in the debugger right at the error.
This has the advantage that in addition to looking at the log your program produced, you can also look at other program state (that you are not logging).
If you want it to stop in the console (not in a file), here is a way to do it :
Use the parameter : --gen-suppressions=yes
When you debug it will stops like this :
==949== Thread 2:
==949== Invalid read of size 4
==949== at 0x7B62DC0: wcslen (wcslen.S:24)
==949== by 0x7B62D7D: wcsdup (wcsdup.c:29)
==949== by 0x52D0476: de_strdup(wchar_t*) (de_string.cpp:1442)
==949== by 0x437629: void de_format<>(c_de_string&, wchar_t*) (de_string.h:368)
==949== by 0x45F4FB: int db_select_group<>(s_db*, s_pqexec_param*, wchar_t*, wchar_t*, wchar_t*, wchar_t*, int, wchar_t*) (in /corto/goinfre/code2/cortod.repo/bin/x64/Debug/cortod)
==949== by 0x45EA96: check_oldgeom(c_cartod*) (cartod_funcs.cpp:114)
==949== by 0x45EBF8: armserv_update_geom(c_cartod*) (cartod_funcs.cpp:149)
==949== by 0x455EF9: c_cortosrv_thread::on_timeout() (cartod.cpp:163)
==949== by 0x52FE500: c_de_thread::loop() (de_thread.cpp:35)
==949== by 0x52FEE97: thread_loop(void*) (de_thread_priv_linux.cpp:85)
==949== by 0x506E181: start_thread (pthread_create.c:312)
==949== by 0x7BBA47C: clone (clone.S:111)
==949== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==949==
==949==
==949== ---- Print suppression ? --- [Return/N/n/Y/y/C/c] ----
Then you can go to the next one continue all etc.
The normal purpose of this parameter is to remove the false positives, by printing suppression that you can add in a file and pass it to valgrind using the parameter : --suppressions=<filename>
Valgrind 3.14.0 has --exit-on-first-error option:
ERROR-RELATED OPTIONS top
These options are used by all tools that can report errors, e.g.
Memcheck, but not Cachegrind.
...
--exit-on-first-error=<yes|no> [default: no]
If this option is enabled, Valgrind exits on the first error. A
nonzero exit value must be defined using --error-exitcode option.
Useful if you are running regression tests or have some other
automated test machinery.
This option must be used together with --error-exitcode option, so possible Valgrind invocation can be:
valgrind --exit-on-first-error=yes --error-exitcode=1 ...
Valgrind outputs to stderr (fd 2) by default. You can capture stderr by redirecting file desctiptor 2:
# Output to log file.
valgrind [options] > valgrind.log 2>&1
# View output interactively.
valgrind [options] 2>&1 | less
Or you could use the --log-fd option to change where output is sent:
valgrind [options] --log-fd=1 > valgrind.log
valgrind [options] --log-fd=1 | less
You can ask valgrind to save its output into file:
valgrind --log-file=<filename>
where <filename> is the file name for output. Later you can view this file with less or text editor.

How to view the GDTR's value?

In the book "Rootkit Arsenal" page 84 (Chapter 3) mentions:
..., we can view the contents of the
target machine's descriptor registers
using the command with the 0x100 mask:
kd> rM 0x100
and a paragraph below:
Note that the same task can be
accomplished by specifying the GDTR
components explicitly: kd> r gdtr ....
I run Windbg on my Win XP (inside VMWare) and choose the Kernel Debug -> Local.
My problem is in case of first command, windbg errors with:
lkd> rM 0x100
^ Operation not supported in current debug session 'rM 0x100'
and in the second command:
lkd> r gdtr
^ Bad register error in 'r gdtr'
Can anyone guide me ?
Right, you can't look at registers in a local kernel debug session. LiveKD works and you can also get the address indirectly through the PCR (!pcr).
-scott
I think I've found the solution:
Use two computers for kernel debugging instead of Local Kernel Debug.
(I used VMWare and am debugging through the COM port/named pipe)
I am thinking why this facility/feature (Local Kernel Debugging) is there if it's not complete ?

Resources