3

I'm writing a kernel module and I need to hijack/wrap some sys calls. I'm brute-forcing the sys_call_table address and I'm using cr0 to disable/enable page protection. So far so good (I'll make public the entire code once it's done, so I can update this question if somebody wants).

Anyways, I have noticed that if I hijack __NR_sys_read I get a kernel oops when I unload the kernel module, and also all konsoles (KDE) crash. Note that this doesn't happen with __NR_sys_open or __NR_sys_write.

I'm wondering why is this happening. Any ideas?

PS: Please don't go the KProbes way, I already know about it and it's not possible for me to use it as the final product should be usable without having to recompile the entire kernel.

EDIT: (add information)

I restore the original function before unloading. Also, I have created two test-cases, one with _write only and one with _read. The one with _write unloads fine, but the one with _read unloads and then crashes the kernel).

EDIT: (source code)

I'm currently at home so I can't post the source code right now, but if somebody wants, I can post an example code as soon as I get to work. (~5 hours)

Quonux
  • 2,975
  • 1
  • 24
  • 32
alexandernst
  • 14,352
  • 22
  • 97
  • 197

1 Answers1

5

This may be because a kernel thread is currently inside read - if calling your read-hook doesn't lock the module, it can't be unloaded safely.

This would explain the "konsoles" (?) crashing as they are probably currently performing the read syscall, waiting for data. When they return from the actual syscall, they'll be jumping into the place where your function used to be, causing the problem.

Unloading will be messy, but you need to first remove the hook, then wait for all callers exit the hook function, then unload the module.

I've been playing with linux syscall hooking recently, but I'm by no means a kernel guru, so I appologise if this is off-base.

PS: This technique might prove more reliable than brute-forcing the sys_call_table. The brute-force techniques I've seen tend to kernel panic if sys_close is already hooked.

Dougall
  • 281
  • 1
  • 6
  • The github link seems really interesting! I need to read it better, but I think I'm going to switch to it over the brute-force method. About the other issue, how can I wait for all callers to exit? I mean, I could write some crappy method that counts read/close, but maybe there is something better that you're aware of? Regards – alexandernst Apr 08 '13 at 15:44
  • 1
    I wish I had a better answer. You can see an [example of really dodgy looking locking here](http://www.tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN890) and a [discussion of try_module_get/module_put here](http://stackoverflow.com/questions/1741415/linux-kernel-modules-when-to-use-try-module-get-module-put) The general idea is either to unhook, then wait in the unload function until the lock is released, then return. I'm not sure what the correct locking structure is, but I imagine there are good concurrency people on SO. It also may make unloading take ages. – Dougall Apr 08 '13 at 22:24
  • Those links look interesting too (btw, I tried the code from the link in your first answer and I already switched to it). Maybe I should create another question about how to unload safely the module? – alexandernst Apr 09 '13 at 08:15
  • +1 for safely unloading and refcounts as while in read system process may be blocked for the long time. – Ilya Matveychikov Jul 17 '13 at 07:47