Hello All -
Subject: PPC Assembly Language - Linux Loadble Kernel Module
Detail: How access local TOC area (r2) when called from kernel in syscall table hook?
I have written a loadable kernel module for Linux that uses syscall table hooking to intercept system calls and log information about them before passing the call on to the original handler. This is part of a security product. My module runs well and is in production code running on a large variety of Linux kernel versions and distributions with both 32 and 64 bit kernels all running on x86 hardware.
I am trying to port this code to run on Linux for PPC processors and ran into a few problems. Using the Linux kernel source, it is easy enough to see how the system call table is implemented differently on PPC. I can replace entries in the table with function addresses from my own compiled handlers, no problem.
But, here's the issue I'm having trouble with. The PPC ABI uses this thing called a Table Of Contents (TOC) address which is stored in the CPU's R2 register and expects to address a module's global and local data by using an offset from the address (TOC address) contained in that register. This works fine in normal cases where a function call is made because the compiler knows to load the module's TOC address into the register before making the call (or its already there becasue normally your functions are called by your own code).
However, when I place the address of my own function (from my loaded kernel module at runtime) into the system call table, the kernel calls my handler with an R2 value that is not the one my compiled C code expects, so my code gets control without being able to access its data.
Does anybody know of any example code out there showing how to handle this situation? I cannot recompile the kernel. This should be a straightforward case of runtime syscall table hooking, but I have yet to figure it out, or find any examples specific to PPC.
Ideas include:
Hand coding an assembly language stub that saves the R2 value, loads the register with my local TOC address, executes my code, then restores the old value before calling the original handler. I don't have the depth of PPC assembly experience to do this, nor am I sure it would work.
Some magic gcc option that will generate my code without using TOC. There is a documented gcc option "-mno-toc"
that doesn't work on my PPC6 Linux. It looks like it may only be an option for system V.4 and embedded PowerPC.
Any help is greatly appreciated !
Thanks!