2.6 build / keyboard hooking

0 views
Skip to first unread message

rezn

unread,
Dec 19, 2004, 10:03:04 AM12/19/04
to lin...@googlegroups.com
I'm somewhat new to the linux kernel, but am learning fast.

Anyway, just a small note on the 2.6 build process. I had trouble
getting compile_2.6 to work, and came up with a (somewhat simplified)
script that works much better for me.

$ cat bin-2.6/c26.sh
mv linice_kernel.o linice_kernel.o_shipped
make -C /lib/modules/`uname -r`/build M=$PWD
cp linice.ko linice_`uname -r`/linice.o

The Makefile in bin-2.6 remains unchanged. The '_shipped' is the key
to getting the kernels makefile to recognize that linice_kernel.o is
already compiled. the M=$PWD is just a shorter way of saying
'SUBDIRS=...' Its weird, but well documented in the 2.6 tree at
'Documentation/kbuild/modules.txt'

On an unrelated note, I looked briefly at the keyboard code and it
looks like maybe the functions kbd_keycode() and kbd_event()
(drivers/char/keyboard.c) are the right places to hook for 2.6. The
only real difference is the names of the functions and some extra
parameters, the actual function KeyboardHook looks like it will work
without modification, as long as the function pointer declarations are
changed to reflect the new parameters. I did this, and got linice to
load up on 2.6, (it displayed on the console), and went away (restored
my console) when I hit F5, but then the machine was then hung. It was
neat to see it up at least.

anyway, I really dont know what I'm doing quite yet, so maybe none of
this makes sense.

I'm sure there are some other issues beyond the keyboard code that need
to be fixed to make it run on 2.6. It would be great if there was a
small list of things that need to get fixed to get it up and running at
least.

Carlos Manuel Duclos Vergara

unread,
Dec 19, 2004, 11:11:19 AM12/19/04
to lin...@googlegroups.com
Hi,

> I'm somewhat new to the linux kernel, but am learning fast.
>

nice to see more people here!

> Anyway, just a small note on the 2.6 build process. I had trouble
> getting compile_2.6 to work, and came up with a (somewhat simplified)
> script that works much better for me.
>
> $ cat bin-2.6/c26.sh
> mv linice_kernel.o linice_kernel.o_shipped
> make -C /lib/modules/`uname -r`/build M=$PWD
> cp linice.ko linice_`uname -r`/linice.o
>
> The Makefile in bin-2.6 remains unchanged. The '_shipped' is the key
> to getting the kernels makefile to recognize that linice_kernel.o is
> already compiled. the M=$PWD is just a shorter way of saying
> 'SUBDIRS=...' Its weird, but well documented in the 2.6 tree at
> 'Documentation/kbuild/modules.txt'
>

good, having it compiled and loaded into 2.6 without much modifications is a
real milestone. However, much of the module initialisation code was rewritten
in 2.6, so we will need to update that code sooner or later. And my position
is (well Goran is the one that decides what needs to be done), if we need to
change the initialisation routines to work in 2.6 why not to make other parts
of linice to make it working the 2.6 way (for example the symbol address
loading)

> On an unrelated note, I looked briefly at the keyboard code and it
> looks like maybe the functions kbd_keycode() and kbd_event()
> (drivers/char/keyboard.c) are the right places to hook for 2.6. The
> only real difference is the names of the functions and some extra
> parameters, the actual function KeyboardHook looks like it will work
> without modification, as long as the function pointer declarations are
> changed to reflect the new parameters. I did this, and got linice to
> load up on 2.6, (it displayed on the console), and went away (restored
> my console) when I hit F5, but then the machine was then hung. It was
> neat to see it up at least.
>

there is something really weird here, I just checked that keyboard.o and
atkbd.o are enabled by default at 2.6 kernels -><-
Well, it requires some more research but I think the calling sequence should
be:
atkbd routines-> keyboard routines-> (console routines || input routines) or
whatever other thing needs to access to the keyboard
this may explain why hooking directly into keyboard.o causes the computer to
hang, I'm not quite sure how this happens. Can you recompile your kernel and
put some printks at $(KERNEL_SOURCE)/drivers/input/keyboard/atkbd.c and
$(KERNEL_SOURCE)/drivers/char/keyboard.c to see what is really happening?

> anyway, I really dont know what I'm doing quite yet, so maybe none of
> this makes sense.
>

btw, I don't understand it also. I was completely sure that the input layer
was in charge of handling the keyboard.

> I'm sure there are some other issues beyond the keyboard code that need
> to be fixed to make it run on 2.6. It would be great if there was a
> small list of things that need to get fixed to get it up and running at
> least.

well, there are at least two "main" things to be done:

1.- find out how is exactly the keyboard handling in 2.6
1.1.- put some printks at the keyboard.c and atkbd.c to see what is
happening
1.2.- build the calling sequence
1.3.- find where to put some hooks for linice

2.- find out how to load the System.map
2.1.- finish my approach and see how it behaves
2.2.- propose another one if it not behaves the way we need

Cheers!

--
Carlos Manuel Duclos Vergara
car...@embedded.cl
http://www.elbazaar.cl/

Peter K.

unread,
Dec 19, 2004, 12:01:20 PM12/19/04
to lin...@googlegroups.com
On Sun, 19 Dec 2004 07:03:04 -0800
"rezn" <offb...@gmail.com> wrote:

> looks like maybe the functions kbd_keycode() and kbd_event()

I think, that it is right place if we want to do things like in 2.4 version ( But why not use official interface to hook on sysrq? May be it will be more universal?)

> my console) when I hit F5, but then the machine was then hung. It was
> neat to see it up at least.

May be it will goot ide to send .diff's here? It will save time. (I think) I 'm afraid that kbd hooking and modules list is not _only_ problems to port linice on 2.6 :(

P.S. Sorry for my english. =)


Peter K.

unread,
Dec 19, 2004, 12:03:20 PM12/19/04
to lin...@googlegroups.com
Ehh.. Using Sysreq is bad idea, sorry... I forgot that it sometimes not compiled in kernel. ;)

Peter K.

unread,
Dec 19, 2004, 1:19:06 PM12/19/04
to lin...@googlegroups.com
On Sun, 19 Dec 2004 07:03:04 -0800
"rezn" <offb...@gmail.com> wrote:

Ok, i have just do hook of those functions (see rezn message)
and it works fine ;). No hangup. No panic. Handling works just fine.

But there are some other issues:
I cant load/unload modules
I cant see any exports (due modules_list problem)
But trace work fine. (F8, F10 and so on)

The main thing i want to say: the core stuff work fine in 2.6 and it's just cool!

Code of install.c in linsym
===========================
while( !feof(fpSystemMap) && (!handle_kbd_event || !handle_scancode || !
{
items = fscanf(fpSystemMap, "%X %c %s\n", &address, &code, sSymbol);
if( items==3 && strcmp("kbd_event", sSymbol)==0 )
{
VERBOSE2 printf(" handle_kbd_event = %08X\n", address);
handle_kbd_event = address;
}
else
if( items==3 && strcmp("kbd_keycode", sSymbol)==0 )
{
VERBOSE2 printf(" handle_scancode = %08X\n", address);
handle_scancode = address;
}
else
if( items==3 && strcmp("modules", sSymbol)==0 )
{
VERBOSE2 printf(" module_list = %08X\n", address);
module_list = address;


Prototype of new LiniceHandleScancode
=====================================

void LiniceHandleScancode(unsigned int scancode, int fPressed, struct pt_regs *regs)

Kernel is 2.6.8.1. Works fine under X server. :)

Carlos Manuel Duclos Vergara

unread,
Dec 19, 2004, 1:32:18 PM12/19/04
to lin...@googlegroups.com
Hi,

>
> Ok, i have just do hook of those functions (see rezn message)
> and it works fine ;). No hangup. No panic. Handling works just fine.
>

can you do some test to make sure that the kbd handling routines to hook are
those ones? I think it is very important to get everything before the input
layer to avoid any kind of information loss. If this is true, then half of
the problem of porting linice to 2.6 would be ready. I'm implementing the
"external" symbol address lookup (i.e. by means of a user helper program), as
soon as I get it working we can merge everything and see what happens :-)

daniel reznick

unread,
Dec 19, 2004, 3:14:05 PM12/19/04
to lin...@googlegroups.com
I tried again and it does indeed work. Linice does seem to work pretty
well (5 minutes of testing, heh) under 2.6!

One issue with this technique is differing kernel versions; I am
using 2.6.9 and kbd_scancode takes 4 parameters, not 3 (like in
2.6.8). I do think that maybe the best end solution is to have a
small userspace program which watches for the 'hotkey' keystroke and
causes an int3 to happen to trigger linice...could be done by anything
like your window manager etc. This solution appears to work for now,
though.

As for modules, I did notice in bin-2.6/iceface.c the body of the
function *ice_get_module is:
#if 0 //2.6

I didn't try changing it yet, but thats probably a good place to start
to get modules working.

In addition to the small changes in linsym documented above by peter,
and the function pointer prototype declaration, you have to make sure
to also change the call to the function pointer to pass along the
extra arguments.. I attached a small diff to linice/input/keyboard.c
which works for me (2.6.9)

daniel reznick

unread,
Dec 19, 2004, 3:59:38 PM12/19/04
to lin...@googlegroups.com
oops, heres the diff
26_kbd_patch

Goran

unread,
Dec 20, 2004, 1:16:41 AM12/20/04
to lin...@googlegroups.com
This is fantastic! That little trick with "_shipped" works great :)

I tried on Fedora Core2 with the kernel 2.6.5-1.358 but the default
Symbol.map file that is in /boot does not contain neither of the
symbols that we'd need. I did not recompile that kernel since I'd like
to have a pristine (out-of-the-box) platform. Is the reason you see
symbols "kbd_event" and "modules" because you recompiled your kernels,
or because you run newer versions? For example, in the sources for
2.6.9 "kbd_event" is static, so it's not exported.

What do you test on? I will try to get the same versions installed.

So right now we seem to hit at least one difference with kernel
mid-versions, and that is the prototype of handle scancode in the
keyboard. However, that one is easy to fix - we just use the newer
prototype since the parameters are pushed on the stack from left to
right, they are backward compatible the way they happen to grow.

Since this appers to be a major milestone, I will add these few changes
and do a minor release.

Thanks!
- Goran

Peter K.

unread,
Dec 20, 2004, 1:38:04 AM12/20/04
to lin...@googlegroups.com
On Sun, 19 Dec 2004 15:59:38 -0500
daniel reznick <offb...@gmail.com> wrote:

And gathering all stuff togather :)
In fact, it will be better to move hooking to platform (version) depending code, but i think we will do it later, after linice will work.. ;)


--- keyboard.c 2004-12-20 09:33:06.000000000 +0300
+++ keyboard.c.new 2004-12-20 09:31:35.000000000 +0300
@@ -49,6 +49,7 @@
#include "intel.h" // Include processor specific stuff
#include "debug.h" // Include our dprintk()

+#include <linux/version.h>

/******************************************************************************
* *
@@ -100,8 +101,13 @@
static BOOL fCapsLock = FALSE;

// Keyboard hook variables
-
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
typedef void (*TLinuxHandleScancode)(unsigned char, unsigned int);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
+typedef void (*TLinuxHandleScancode)(unsigned int, int, struct pt_regs *xxx);
+#else
+typedef void (*TLinuxHandleScancode)(unsigned int, int, int xx, truct pt_regs *xxx);
+#endif
static TLinuxHandleScancode LinuxHandleScancode;
static DWORD *pKbdHook = NULL; // Original kbd hook address
static DWORD KbdHook; // Original kbd hook value
@@ -323,7 +329,13 @@
* Hook function for the standard Linux handle_scancode() which it chains.
*
******************************************************************************/
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
void LiniceHandleScancode(BYTE scancode, BOOL fPressed)
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
+void LiniceHandleScancode(unsigned int scancode, int fPressed, struct pt_regs *xxx)
+#else
+void LiniceHandleScancode(unsigned int scancode, int fPressed, int xx, struct pt_regs *xxx)
+#endif
{
static WCHAR Key = 0;
BYTE code = scancode & 0x7F;
@@ -348,10 +360,23 @@
// and put host into a known state

// Depress control or alt key
- if( Key & CHAR_CTRL )
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+ if( Key & CHAR_CTRL )
(LinuxHandleScancode)(SC_CONTROL, !fPressed);
else
(LinuxHandleScancode)(SC_ALT, !fPressed);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
+ if( Key & CHAR_CTRL )
+ (LinuxHandleScancode)(SC_CONTROL, !fPressed, xxx);
+ else
+ (LinuxHandleScancode)(SC_ALT, !fPressed, xxx);
+#else
+ if( Key & CHAR_CTRL )
+ (LinuxHandleScancode)(SC_CONTROL, !fPressed, xx, xxx);
+ else
+ (LinuxHandleScancode)(SC_ALT, !fPressed, xx, xxx);
+#endif

Key &= ~(CHAR_CTRL | CHAR_ALT);

@@ -367,7 +392,13 @@
else
{
// Chain the call to the original handle_scancode
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
(LinuxHandleScancode)(scancode, fPressed);
+#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)
+ (LinuxHandleScancode)(scancode, fPressed, xxx);
+#else
+ (LinuxHandleScancode)(scancode, fPressed. xx, xxx);
+#endif
}
}

Goran

unread,
Dec 20, 2004, 1:44:54 AM12/20/04
to lin...@googlegroups.com
Peter, could you email me all the files that you changed? I think that
will be easier and make this thread more readable. Please use
feat...@linice.com (I got to test this email address :)
Then I will verify the changes on a 2.4 build and release.
Thanks!

Goran

unread,
Dec 20, 2004, 1:48:32 AM12/20/04
to lin...@googlegroups.com
Oh, cool - this google groups server is mangling the email address to
prevent spam. I like that. The email address is "features" at... :)

Goran

unread,
Dec 20, 2004, 1:59:34 AM12/20/04
to lin...@googlegroups.com
Hi,
Looking back at the changes, what I was trying to say is that we don't
need to bracket keyboard hook function with
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
because the 2 new parameters are added to the right; it's like the
variable number of parameters thing: you can add as many as you want to
the right, and the "C" function will still work using just those that
it expects from the left, if you know what I mean. So the new prototyps
is fully backward compatible with the old 2.4 and will simply work in
both environments. That's nice thing with hook functions that dont use
kernel headers :)
What distro do you have?
Thanks

daniel reznick

unread,
Dec 20, 2004, 7:04:10 AM12/20/04
to lin...@googlegroups.com
Hi Goran.

I used 2.6.9 from kernel.org and compiled it myself. I'm not sure
about this, but I think that System.map should have all kernel
symbols, even ones that are not exported. Perhaps those functions
don't exist in 2.6.5 or maybe redhat ships a modified System.map for
some reason. There also might be some configuration options in the
kernel that control this, but, again, I'm not sure.

Peter K.

unread,
Dec 20, 2004, 1:42:33 PM12/20/04
to lin...@googlegroups.com
On Sun, 19 Dec 2004 22:59:34 -0800
"Goran" <gde...@gmail.com> wrote:

I thought about parameters and C stack calling conventions too, but we call original one functions from hook, and i'm not sure that it will work. For example...

int original(int a. int b, int c);
int hook(int a, int b)
{
original call // how we do that without right prototype???...
original(a, b);// what will be in stack on "c" place??
}

hook(a, b); // all ok, caller must update esp... not called function

I speak english very bad, but i hope you know what i want to say...
May be i forgot something?? If so, just forgot above text. :)

About distro: i am using debian testing/unstable, kernel 2.6.8.1 from kernel.org. :) I see, we must look on other kernel versions to check if this hook is safe to use.

Peter K.

unread,
Dec 20, 2004, 1:49:14 PM12/20/04
to lin...@googlegroups.com
On Mon, 20 Dec 2004 07:04:10 -0500
daniel reznick <offb...@gmail.com> wrote:

>
> Hi Goran.
>
> I used 2.6.9 from kernel.org and compiled it myself. I'm not sure
> about this, but I think that System.map should have all kernel
> symbols, even ones that are not exported.

You are right. "T" and "t" symbols means global/static IMHO :)
In fact, may be it is the good idea ALWAYS LOAD System.map to linice? And linice can use this information for hooking and as symbol map to debug kernel? In fact, it's looks more simply than calling userspace or doing things like this...

P.S. To sad, no free time... :( I want to write FEATURES to linice, but i can't do it... :( Ehhh.... Linice is my dream.. =)

Goran Devic

unread,
Dec 20, 2004, 2:22:59 PM12/20/04
to lin...@googlegroups.com
Howdy!
I think your english is good: you can clearly convey a technical
message; doing great, IMHO.

You see, the trick with the hook is that we define a prototype as a
pointer to a function; we dont use a static link so the compiler can't
complain about the mismatching prototypes.

Calling the original function using this way:
(LinuxHandleScancode)(SC_CONTROL, !fPressed);
makes it not care about the real parameters of the called code. The
stack will look like this:
+ 12 fPressed
+ 8 SC_CONTROL
+ 4 [Return address]
+ 0 stack frame [ebp]

If we add two new parameters, the stack frame will look like this:
(LinuxHandleScancode)(SC_CONTROL, !fPressed, new-param1, new-param2);
+ 20 new-param2
+ 16 new-param1
+ 12 fPressed
+ 8 SC_CONTROL
+ 4 [Return address]
+ 0 stack frame [ebp]
The called function will still use only up to +12, and ignore appended
new parameters.

The fact that we are calling it from a hook, where different number of
parameters are already being passed TO US, makes our function ONLY get
2 more parameters from the callee and push it when we call the hooked
function. In 2.4 kernels, those 2 parameters will be junk, but it does
not matter, since we dont use them, and neither the called function
does. They will be kind of copied around and finally discarded with
the stack left clean and balanced.

Perhaps we can just try it on a 2.4 kernel and see if it blows up :)
but I just sometimes like theoretical mind-games :)

Thanks!
- Goran

Peter K.

unread,
Dec 21, 2004, 2:13:13 AM12/21/04
to lin...@googlegroups.com
On Mon, 20 Dec 2004 13:22:59 -0600
Goran Devic <gde...@gmail.com> wrote:

Ehhh... I dont, undestand, i think i know what i am doing, but... Suddanly it happens =)

BTW I am now porting modules stuff (exp and module command works fine!!! bpx work fine =)) but i am using more symbols :( Is anybody doing the same work now? May be i must post ALL patches here?

And about hooking. =)

Call of hook from kernel:
+ 4 ret
+ 8 scancode
+ 12 fpressed
+ 16 xx
+ 20 xxx
+ locales of caller
+ ebp frame of caller

In hook we do at least:

push epb
mov ebp, esp
sub esp, ??? // to alloc stack for LOCALES.

so:
+ locales
+ ebp
+ ret
+ scancode
+ fpressed
+ xx
+ xxx

And then, we call original handler. Cases are:
1) Compiler just do pushes of parameters about we say, i.e
push fpressed
push scancode
call original

and stack of original handler is NOT right:
+ ret
+ scancode
+ fpressed
+ prev locales
+ prev ebp
+ prev ret and so on

2) Compiler do somewhat smart and correct esp to point it on right frame. All works fine.

3) Reality on my machine:
Here is the test:

typedef int (*test2)(int, int);
test2 z;
int test(int a, int b)
{
int i=2;
z(a, b);
}

250: 55 push %ebp
251: 89 e5 mov %esp,%ebp
253: 83 ec 08 sub $0x8,%esp // NEW frame (esp-=8)
256: 8b 45 0c mov 0xc(%ebp),%eax
259: 89 44 24 04 mov %eax,0x4(%esp) // move to [esp+4] second parameter
25d: 8b 45 08 mov 0x8(%ebp),%eax //
260: 89 04 24 mov %eax,(%esp) // move to [esp] first parameter
263: ff 15 00 00 00 00 call *0x0
269: 89 ec mov %ebp,%esp
26b: 5d pop %ebp
26c: c3 ret

You see: the frame before call *0x0 is
0)a
4)b
8)locale i
c)ebp
10)ret
14)caller parameters

So, suppose we push from kernel not a.b. but a,b,c? Will the z get those 3-d parameter? It seems that it will got locale or ebp, or something wrong.

So at least, this techique is compiler specific???? Where i do mistake?
My version, that may be it will work, but it's just ... mistake :)

So, it's safe to remove ifdef's from HOOK, but not from original handler prototype.

Plz, show me my mistake, in fact i really did not write on assembly from Win NT times, but all stuff above looks correct for me. =)

Peter K.

unread,
Dec 21, 2004, 3:18:53 AM12/21/04
to lin...@googlegroups.com
On Tue, 21 Dec 2004 10:13:13 +0300
"Peter K." <gloom...@mail.ru> wrote:

>
> On Mon, 20 Dec 2004 13:22:59 -0600
> Goran Devic <gde...@gmail.com> wrote:
>
> Ehhh... I dont, undestand, i think i know what i am doing, but... Suddanly it happens =)

Sorry! I am at work now, and i undestand Goran, we left NEW prototype in code :) No ifdef's, cool! Sorry once more for traffic.
Reply all
Reply to author
Forward
0 new messages