I use the simple sys_call_table rewrite to
log all execve calls in a system.
When moving to Ubuntu 16.10 with a 4.8 kernel this
mechanism suddenly stopped to work. In 16.04 with
a 4.6 kernel it was working.
1: write_cr0 (read_cr0 () & (~ 0x10000));
2: original_execve = (void *)syscall_table[__NR_execve];
3: syscall_table[__NR_execve] = (unsigned long)&new_execve;
4: write_cr0 (read_cr0 () | 0x10000);
The page fault already happens when reading the old entry, that is line 2.
To retrive the sys_call_table address I use:
sudo cat /boot/System.map-`uname -r` | grep -e '\ssys_call_table' | awk '{ print $1}' )"
Code is from: https://github.com/eiselekd/shinterposer/tree/master/mod
Does anyone know what happened? Maybe some
protection mechanism has been introduced?
There seem to be Address Space Layout Randomization (kASLR) on the syscall table taking
place by default in the 4.8 kernel. When declaring the sys_call_table symbol as exported and linking against it directly from a module the address for sys_call_table is changing for each boot.
The address from /boot/System.map-xxx is useless.
To disable kaslr in ubuntu 16.10 kernel 4.8 one can add
nokaslr
to the kernel command line.
What is the meaning of (OE+) in the following?
$ sudo cat /proc/modules | grep hello //hello_world is a kernel module created by me.
hello_world 20480 1 - Loading 0xffffffffc0221000 (OE+)
Here is my situation.
I have patched the Linux kernel function load_module(), which is called from finit_module(), the system call used by insmod to insert kernel modules.
The patch looks for a specific module, created by me (called hello_world) being installed, and when it does, it prevents the call to do_init_module(), and returns 0 instead. do_init_call() is responsible for calling a module's init function, and setting the module state to live (MODULE_STATE_LIVE).
When I read /proc/modules, the module state is Loading, which is expected. I do not understand however the meaning of (OE+) at the end of output. This is not displayed against any other module, as is verified by the following command.
$ sudo cat /proc/modules | grep OE
hello_world 20480 1 - Loading 0xffffffffc0221000 (OE+)
I am using Linux kernel v4.7.3.
Update
All this is happening in a Qemu virtual machine. On the host, which is running Linux 4.4.0-36-generic (Ubuntu), I get the following.
$ sudo cat /proc/modules | grep OE
vboxpci 24576 0 - Live 0xffffffffc082a000 (OE)
vboxnetadp 28672 0 - Live 0xffffffffc066e000 (OE)
vboxnetflt 28672 0 - Live 0xffffffffc0635000 (OE)
vboxdrv 454656 3 vboxpci,vboxnetadp,vboxnetflt, Live 0xffffffffc0783000 (OE)
sep4_0 671744 0 - Live 0xffffffffc06de000 (OE)
socperf2_0 36864 1 sep4_0, Live 0xffffffffc0660000 (OE)
pax 16384 0 - Live 0xffffffffc05f9000 (OE)
O means Out-of-tree module has been loaded.
E means Unsigned module has been loaded.
+ means that the module is being loaded.
- means that the module is being unloaded.
The source code for print_modules(), then module_flags(), and then print_tainted() functions may be helpful in figuring out the meaning of these and some other flags. Take a look at the comment just above print_tainted() function. Hope this helps.
On debugging linux kernel 3.6.11 with - "ddd vmlinux /proc/kcore" , the "file_systems" list present in fs/filesystems.c is shown empty, containing the address 0x0 .
It is supposed to contain file_system_type structures of all the registered file systems .
Why the list is empty or where else can I see the list of registered file systems ?
Debugging the kernel is not needed for that. There is a proc API that provides the information:
cat /proc/filesystems
Does anyone know of a way to get U-boot version installed from userspace? There is the fw_printenv command that provides access to U-boot's environment variables, but not the version.
If U-boot is located in mtd0, you can get version info as follows:
root#SUPERWIFI:/proc# strings /dev/mtd0 | grep U-Boot
U-Boot 1.1.4-g1c8343c8-dirty (Feb 28 2014 - 13:56:54)
U-Boot
Now running in RAM - U-Boot at: %08lx
Just an update for this.
In our version of U-Boot we changed the code for main_loop() in main.c to this:
#ifdef CONFIG_VERSION_VARIABLE
char *oldver=getenv("ver");
if(oldver==0 ||strcmp(oldver,version_string))
{
setenv("ver", version_string); /* set version variable */
saveenv();
}
#endif /* CONFIG_VERSION_VARIABLE */
So setenv/saveenv is only called, if needed by an update.
In our firmware we added
/sbin/fw_printenv -n ver > /var/config/u-boot.ver
to make the u-boot version public available.
There's no defined way to do this. Once Linux boots, u-boot is no longer running and it's RAM is reclaimed for Linux's use. Linux doesn't even know about u-boot. Nor does it have to have been booted by u-boot.
If you really want to do this, the only way to do it is to add the u-boot version to the kernel's command line, write code to scan the u-boot image in flash for it's version, or something even nastier.
An alternative solution is to read the version directly from the u-boot binary file (can be even embedded in an image file containing other binaries as well like e.g. the first stage bootloader) with e.g. mmcblk0boot0 as partition (of device mmcblk0) the bootloader resides in:
sudo grep -a --null-data U-Boot /dev/mmcblk0boot0
Site note: Does work not only for Arch Linux but e.g. Ubuntu as well.
In my devices UBoot automatically creates a "ver" environment variable containing its version:
U-Boot > printenv
baudrate=115200
ethact=FEC ETHERNET
ethaddr=24-db-ad-00-00-08
bootdelay=3
bootcmd=bootm fc080000 - fc060000
bootargs=console=ttyCPM0,115200n8 rdinit=/sbin/init
stdin=serial
stdout=serial
stderr=serial
ver=U-Boot 2009.03-svn9684 (Mar 08 2010 - 17:08:32)
Environment size: 253/131068 bytes
U-Boot >
I don't use fw_printenv, but I would imagine that this variable gets passed along as well. Maybe you already have something similar in your system?
UPDATE (5/23/2012):
I added fw_printenv to my linux image and can confirm that I do see the "ver" variable:
[root#ST600 /]# fw_printenv
baudrate=115200
ethact=FEC ETHERNET
ethaddr=24-db-ad-00-00-08
stdin=serial
stdout=serial
stderr=serial
ver=U-Boot 2009.03-svn9684 (Mar 11 2010 - 09:43:08)
bootcmd=bootm fc080000 - fc060000
bootdelay=3
bootargs=console=ttyCPM0,115200n8 rdinit=/sbin/init panic=10 mem=32m
[root#ST600 /]#
Try to read uboot version this way:
Find uboot partition, eg. for MTD device:
cat /proc/mtd
For /dev/mtd5:
cat /dev/mtd5 | hexdump -C -n 64
You can't rely on fw_printenv if you want to know u-boot version.
fw_printenv just looks for the printenv partition and dumps its data. So it's OK for normal variables, but it's not OK for the "ver" variable, which is dynamic, and whose value is initialized by u-boot when it boots. The value of this variable doesn't remain after u-boot exit, except if you manually save it to environment.
For example, on my board, if I print the "ver" variable from u-boot prompt:
U-Boot > printenv ver
ver=U-Boot 2009.11-00393-g5ca9497-dirty (Nov 26 2012 - 11:08:44)
This is the real version of u-boot, coming from u-boot itself.
Now, if I boot my board and use fw_printenv:
el#board # fw_printenv | grep ver=
ver=U-Boot 2009.11-00323-gbcc6e0e (Sep 21 2012 - 11:07:19)
As you can see, it's different. Because it happens that I have a "ver" variable defined in my environment. And it doesn't match the real u-boot version.
Of course, I could go back to u-boot, use "saveenv" to update the "ver" value in the environment. Then the two values would match. But then, I should always update the environment after changing u-boot.
So, my conclusion is that using fw_printenv to get u-boot version is definitely not a good idea.
If u-boot is residing in an MTD partition then this will work:
U_BOOT_VER=$(for part in `grep u-boot-[01] /proc/mtd | cut -f 1 -d ':'`; do strings /dev/${part} | grep "^U-Boot.*("; break; done)
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 ?