[grsec] 'charp' module parameter, 2.1.14-2.6.31.5-200910312135

hooanon05 at yahoo.co.jp hooanon05 at yahoo.co.jp
Sun Nov 8 19:11:22 EST 2009


pageexec at freemail.hu:
> thanks for your report but i'll need more info about which exact modules
> you observed the problem with. the fundamental problem is that under PaX
> (and even vanilla linux, see 65afac7d80ab3bc9f81e75eafb71eeb92a3ebdef)
> these kernel_param structs are read-only so setting the flags field in
> them will cause an oops. in vanilla linux the solution is the same except
> they opted for leaking memory, i'd like to avoid that but for that i'll
> need to know which modules can reach this code with non-kmalloc'ed strings.

The module is develping by myself and it is not included into mainline.
So I don't think 'which module' is important for you.
I want to point out that there are many modules which use charp
parameter, and some of them has a problem possibly in grsecurity. If you
try grep -w charp to your kernel source tree, you will find about 280
lines.

For instance,
./kernel/rcutorture.c:82:module_param(torture_type, charp, 0444);

To reproduce the problem by using ./kernel/rcutorture.c,
- set CONFIG_RCU_TORTURE_TEST=m, "torture tests for RCU"
- build and reboot
- load the module named 'rcutorture'
- and then unload it

Then you will see,
$ sudo modprobe -r rcutorture
rcu-torture: rtc: (null) ver: 2862 tfle: 0 rta: 2862 rtaf: 0 rtf: 2861 rtmbe: 0 nt: 15476
rcu-torture: Reader Pipe:  4197716 206 0 0 0 0 0 0 0 0 0
rcu-torture: Reader Batch:  4197620 302 0 0 0 0 0 0 0 0 0
rcu-torture: Free-Block Circulation:  2861 2861 2861 2861 2861 2861 2861 2861 2861 2861 0
rcu-torture:--- End of test: SUCCESS: nreaders=4 nfakewriters=4 stat_interval=0 verbose=0 test_no_idle_hz=0 shuffle_interval=3 stutter=5 irqreader=1
kfree_debugcheck: out of range ptr ffffffffa00f9406h.
------------[ cut here ]------------
kernel BUG at mm/slab.c:2819!
invalid opcode: 0000 [#1] PREEMPT SMP 
last sysfs file: /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-7/2-7:1.0/host4/target4:0:0/4:0:0:0/type
CPU 1 
Modules linked in: nfsd exportfs nls_iso8859_1 nls_cp437 [last unloaded: rcutorture]
Pid: 1946, comm: modprobe Not tainted 2.6.31.5-grsec #293 Pegatron
RIP: 0010:[<ffffffff810f0f6b>]  [<ffffffff810f0f6b>] kfree_debugcheck+0x2b/0x30
RSP: 0018:ffff88000e9bbe28  EFLAGS: 00010092
RAX: 000000000000003c RBX: ffffffffa00f9406 RCX: 0000000000000000
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff816d99b0
RBP: ffff88000e9bbe38 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000001 R12: ffffffff810679fd
R13: ffffffffa00f94a8 R14: ffffffffa00f9406 R15: 0000000000000206
FS:  00007f55755466e0(0000) GS:ffff8800056bc000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 00007fffdeb54ad0 CR3: 000000000f9f4000 CR4: 00000000000406e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process modprobe (pid: 1946, threadinfo ffff88000e9ba000, task ffff88000f9ed0c0)
Stack:
 ffff88000e9bbe38 0000000000000000 ffff88000e9bbe78 ffffffff810f2e70
<0> ffff88000e9bbe88 0000000000000000 0000000000000168 ffffffffa00f94a8
<0> 0000000000000009 000000000000002d ffff88000e9bbec8 ffffffff810679fd
Call Trace:
 [<ffffffff810f2e70>] kfree+0x110/0x280
 [<ffffffff810679fd>] destroy_params+0x8d/0x90
 [<ffffffff81089b10>] free_module+0xb0/0x150
 [<ffffffff81089d8f>] sys_delete_module+0x1df/0x250
 [<ffffffff8107dc6d>] ? trace_hardirqs_on_caller+0x14d/0x1a0
 [<ffffffff8144d2ee>] ? trace_hardirqs_on_thunk+0x3a/0x3f
 [<ffffffff8100a842>] system_call_fastpath+0x16/0x1b
Code: 55 48 89 e5 53 48 89 fb 48 83 ec 08 e8 8f d6 f3 ff 84 c0 74 07 48 83 c4 08 5b c9 c3 48 89 de 48 c7 c7 98 42 5d 81 e8 75 8e 35 00 <0f> 0b eb fe 90 55 48 b8 ff ff ff ff ff 87 ff ff 48 89 e5 48 83 
RIP  [<ffffffff810f0f6b>] kfree_debugcheck+0x2b/0x30
 RSP <ffff88000e9bbe28>
---[ end trace 24086a64a3d733d7 ]---


I don't think it is necessary to test all modules which have 'charp'
parameter and show you the result. But they may be categorized by
several groups.

A. Harmless
- the charp parameter is initialized by NULL
- the charp parameter is set the separatly allocated memory

We can kfree() the prameter safely.


B. Problem will happen when the parameter is specfied
- initialized by NULL
B-1.
- set the static string
B-2.
- set the separatly allocated memory, but the memory block is maintained
  by another place.
  when "int_param=0 charp_param=foo" is given, the module parser may set
  the address middle of this string to the charp parameter ("foo").

I don't know exactly what will happen at freeing the specified
parameter.


C. Problem will happen regardless the paramter
- initialized by a static string.

The previous sample of rcutorture is the case.


I've just checked Rusty Russell's commit
(65afac7d80ab3bc9f81e75eafb71eeb92a3ebdef) which you pointed out too.
I can guess that
- he (and everybody) does not want the memory-leak actually.
- but he had to, because there are many modules which use charp.
- generally the module parameter is not so large, which means the memory
  leak is not so large.
- if he (or we) fix every charp parameters with big effort, some memory
  fragmentation may happen.
- is it really worth to do?
- it may be worth to limit the length of the parameter in order to
  minimize the memory leak.

I can modify my module to set the kfree-able memory to the module
parameter, but it never fix the generic problem in grsecurity patch.
I am afraid that the grsecurity patch has to choose Rusty Russell's
memory-leak way until all modules fix their charp parameter.


J. R. Okajima


More information about the grsecurity mailing list