Failed to modify sys_call_table in 2.6.24-21 kernel

Submitted by Anonymous
on November 6, 2008 - 11:57am

Hello people!
I've got a trouble with my kernel module since I updated Ubuntu 8.04 last time. So, it's all about kernel 2.6.24-21 and higher... I think.
I detected that the string below, that worked perfectly until last update, doesn't work now:


sys_call_table[__NR_clone] = my_sys_clone;

sys_call_table - system call table, address taken from System.map file
my_sys_clone - my own sys_clone function, that I replace the original call with

Below is the error message (dmsg):

[ 1672.577687] ..................
[ 1672.577687] BUG: unable to handle kernel paging request at c0385a60
[ 1672.577797] IP: [] :proc_watcher_mod:proc_watcher_init+0xe9/0x10c
[ 1672.578784] *pde = 005c1067 *pte = 00385161
[ 1672.579543] Oops: 0003 [#1] SMP
[ 1672.579906] Modules linked in: proc_watcher_mod(+) isofs udf crc_itu_t binfmt_misc af_packet bridge stp bnep rfcomm sco l2cap bluetooth ppdev vmblock vmci vmmemctl speedstep_lib cpufreq_powersave cpufreq_userspace cpufreq_stats cpufreq_ondemand cpufreq_conservative freq_table video output sbs sbshc pci_slot wmi battery iptable_filter ip_tables x_tables vmhgfs lp loop ipv6 snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_oss snd_pcm snd_seq_dummy parport_pc parport snd_seq_oss evdev snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq container psmouse serio_raw snd_timer snd_seq_device ac button snd pcspkr i2c_piix4 soundcore snd_page_alloc intel_agp i2c_core shpchp agpgart pci_hotplug ext3 jbd mbcache sd_mod crc_t10dif sr_mod cdrom sg pcnet32 mptspi mptscsih mii uhci_hcd mptbase scsi_transport_spi ata_piix ata_generic pata_acpi usbcore libata scsi_mod dock thermal processor fan fbcon tileblit font bitblit softcursor fuse vmxnet
[ 1672.580036]
[ 1672.580036] Pid: 5950, comm: insmod Not tainted (2.6.27-7-generic #1)
[ 1672.580036] EIP: 0060:[] EFLAGS: 00010282 CPU: 0
[ 1672.580036] EIP is at proc_watcher_init+0xe9/0x10c [proc_watcher_mod]
[ 1672.580036] EAX: c01023c0 EBX: 00000000 ECX: e0c4c666 EDX: c0385880
[ 1672.580036] ESI: e0860000 EDI: 00000000 EBP: de7fff1c ESP: de7fff0c
[ 1672.580036] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
[ 1672.580036] Process insmod (pid: 5950, ti=de7fe000 task=dd4ebed0 task.ti=de7fe000)
[ 1672.580036] Stack: e0c4ce6c 00000001 e0c4fc04 00000000 de7fff8c c0101120 00000000 00000000
[ 1672.580036] 00000111 00000000 00000000 00000000 00000000 00000000 00000000 e0c5d064
[ 1672.580036] 0000001a e0c4da8c 00000000 00000000 c014c604 00000000 00000000 e0c4da80
[ 1672.580036] Call Trace:
[ 1672.580036] [] ? _stext+0x30/0x160
[ 1672.580036] [] ? __blocking_notifier_call_chain+0x14/0x70
[ 1672.580036] [] ? sys_init_module+0x88/0x1b0
[ 1672.580036] [] ? sys_close+0x7f/0xd0
[ 1672.580036] [] ? sysenter_do_call+0x12/0x2f
[ 1672.580036] =======================
[ 1672.580036] Code: 00 e8 dc c5 3e 00 a1 04 da c4 e0 e8 e2 c4 3e 00 8b 15 04 fc c4 e0 85 d2 89 15 08 fc c4 e0 74 15 8b 82 e0 01 00 00 a3 00 fc c4 e0 82 e0 01 00 00 10 c3 c4 e0 89 d8 83 c4 0c 5b 5d c3 c7 04 24
[ 1672.580036] EIP: [] proc_watcher_init+0xe9/0x10c [proc_watcher_mod] SS:ESP 0068:de7fff0c
[ 1672.580036] ---[ end trace 2b123145b19e26a4 ]---

Does anybody know if there are some changes in new kernel about system calls and sys_call_table?

PS. I tried the same on Ubuntu 8.10 - no changes, the same result :(

You Cannot Do It Anymore

on
November 7, 2008 - 9:58pm

Hi Ho!

This may help: http://kerneltrap.org/node/16668

Best regards,
Eus

Its impossible to do it

Anonymous (not verified)
on
November 9, 2008 - 8:08pm

Its impossible to do it anymore? why? Since kernel version?

Since 2.5.41

on
November 10, 2008 - 9:42pm

Hi Ho!

You can find the explanations to your first two questions in the link that I gave before.

I based my answers here on 2.6/lkmpg-examples/08-SystemCalls/README.txt that can be found in the docbook source of The Linux Kernel Module Programming Guide.

Best regards,
Eus

Of course you can still

gat3way (not verified)
on
November 11, 2008 - 3:00am

Of course you can still modify sys_call_table[] even though it's not exported. I recently did that on Linux 2.6.26-1-amd64 kernel.

All you have to do is get the address from System.map and find a way to pass it to your kernel module (I use procfs for that, which is a bad idea anyway).

After that it's simple, e.g:

static long *sct;
....
(in procfs read callback):

if(copy_from_user(buf, buffer, 20)) return -EFAULT;
sscanf(buf,"%lx",&sct);
original_clone = *(sct+__NR_clone);
*(sct+__NR_clone) = modified_clone;

You've got to define a modified_clone() function an keep the old address (in case you unload your module) in int *original_clone;

You don't need to define the sys_call_table[] array, my guess is that you probably overwrite the wrong memory location with the address of your clone() function.

But...what in fact are trying to implement? A rootkit? Cause there are a few legitimate uses of changing the sys_call_table[]...

Really?

on
November 11, 2008 - 10:02pm

Hi Ho!

I don't know whether or not this has been changed in Linux 2.6.26-1-amd64, but in Linux 2.6.21.5 as taken from http://kernel.org puts the sys_call_table in a read-only section of the memory. This means that you still cannot fiddle with it.

Could you please confirm whether or not this has been changed in Linux 2.6.26-1-amd64 by looking at file `arch/i386/kernel/entry.S' and see whether the following is listed there:

.section .rodata,"a"
#include "syscall_table.S"

If it still says .rodata,"a" and you can successfully fiddle with the sys_call_table that results from the compilation of the source code, I think it means that the read-only section is not enforced in the kernel realm unless you activate the feature of protecting read-only data structure through the kernel hacking menu of `menuconfig'.

Best regards,
Eus

Hello, that's

gat3way (not verified)
on
November 12, 2008 - 3:10am

Hello, that's arch/x86/kernel/entry_32.S:

.section .rodata,"a"
#include "syscall_table_32.S"

But there is nothing like that in entry_64.S though.

Well dunno...I use a debian-provided precompiled kernel image.

Try this code.

on
November 12, 2008 - 3:55am

http://kerneltrap.org/node/16739
You can try this! It works fine for me with 2.6.16, 2.6.26 and 2.6.27.
I noticed that you may have to sometimes slightly modify the code to make it works... In case of crash you can try to replace &memcmp by &unlock_kernel.
IMHO, I don't think this is the most reliable way to find the SCT address.
-----
http://lse.berlios.de

What the hack!

on
November 12, 2008 - 10:00pm

Hi Ho!

It's cool that the idea is to find the beginning of the system call table by finding it in between two exported symbols. But, that idea alone as you have mentioned it yourself is not reliable if it only compares the first entry of the sys_call_table. Comparing all of the content of the table will be a good one although it is not a bullet-proof technique. Who knows if in a particular system, the location of the table is moved to the middle-of-nowhere by a custom linker script?

Have you perused `Fiddling with sys_call_table in Linux Kernel 2.6.21.5'? Yes, it is my post. IMHO, it should be the best way to go if you have access to install a Linux kernel built from the source code.

Best regards,
Eus

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.