Because the process that crashes is not always the same and because the crash is produced while removing the module, I supposed that the problem was a race condition.
If I try to remove the module while a process is inside my_own_syscall then the function is unallocated and who knows what happens with file descriptors and other variables.
So I defined an atomic_t variable and used it as a counter. It is incremented when the function is reached and decremented when returning from it.
When I try to remove the module, first I stay blocked until there are not processes inside my functions. I wrote a shell script for continually insmod and rmmod the module and it appears to work fine.
Best regards
---------- Forwarded message ----------
From: Fernando Apesteguía <fernando.apesteguia@xxxxxxxxx>
Date: May 31, 2006 5:25 PM
Subject: Oops when working with syscalls
To: kernelnewbies@xxxxxxxxxxxx
Hi,
I'm writing a module to profile some syscalls parameters. I replace the original functions by my own ones, doing (for brk syscall):
old_brk = (void *) sct[__NR_brk];
sct[__NR_brk] = (unsigned long *) my_brk;
I get the syscall table address from System.map or by scanning the kernel address space (don't tell Linus.... :) )
This is my function:
asmlinkage int
my_brk(struct pt_regs regs)
{
struct pt_regs *tmp;
unsigned long brk_before, brk_after;
long long t1, t2;
long interval;
long long copy_mean;
int ret = -EINVAL;
printk(KERN_INFO "Bridging brk, calling original...\n");
/*Take some timestamps*/
ret = old_brk(regs); /* Call to the original routine */
/*more time stamps and statistics*/
__asm__("movl %%esp, %0": "=m"(tmp):);
regs = *tmp;
return (ret);
}
This works really fine. The system is stable and all the programs run without problems. This is what Intel Vtune does to profile syscalls.
My problem is with read syscall. I do exactly the same (here comes the code):
asmlinkage int
my_read(struct pt_regs regs)
{
struct pt_regs *tmp;
int ret = -EINVAL;
long long t1, t2, interval, copy_mean;
// printk(KERN_INFO "Bridging read, calling original...\n");
// rdtscll(t1);
ret = old_read(regs); /* ret has the bytes read */
// rdtscll(t2);
__asm__("movl %%esp, %0": "=m"(tmp):);
regs = *tmp;
return (ret);
}
I even removed the counters and statistics. The replacement goes fine, but when I try to rmmod the module I get an Oops like this (This is a partial output):
*pde=018ed067
*pte=00000000
Oops: 0000 [#1]
PREEMPT
Modules linked in: <here comes the list of modules>
CPU: 0
EIP: 0060: [<f8ad234a>] Tainted: P VLI
EFLAGS: 00010286 ( 2.6.15.6)
EIP is at 0xf8ad234a
eax: 00000033 ebx: 0000000 ecx: 00000033 edx: 0000000
esi: 0000001 edi: 0000000 ebp: f78d4000 esp: f78d5f78
ds: 007b es: 007b ss: 0068
Process klogd (pid: 2539, threadinfo=f78d4000 task=f78c0a50)
..
..
Call Trace:
[<c0102b79>] syscall_call + 0x7/0xb
Code: Bad EIP value
I don't know what I'm doing wrong... the other syscalls I catched (brk, fork and vfork) works fine.
Thanks in advance.
PS: Are there any tricks to get the complete output when getting an Oops from kernel?
I'm writing a module to profile some syscalls parameters. I replace the original functions by my own ones, doing (for brk syscall):
old_brk = (void *) sct[__NR_brk];
sct[__NR_brk] = (unsigned long *) my_brk;
I get the syscall table address from System.map or by scanning the kernel address space (don't tell Linus.... :) )
This is my function:
asmlinkage int
my_brk(struct pt_regs regs)
{
struct pt_regs *tmp;
unsigned long brk_before, brk_after;
long long t1, t2;
long interval;
long long copy_mean;
int ret = -EINVAL;
printk(KERN_INFO "Bridging brk, calling original...\n");
/*Take some timestamps*/
ret = old_brk(regs); /* Call to the original routine */
/*more time stamps and statistics*/
__asm__("movl %%esp, %0": "=m"(tmp):);
regs = *tmp;
return (ret);
}
This works really fine. The system is stable and all the programs run without problems. This is what Intel Vtune does to profile syscalls.
My problem is with read syscall. I do exactly the same (here comes the code):
asmlinkage int
my_read(struct pt_regs regs)
{
struct pt_regs *tmp;
int ret = -EINVAL;
long long t1, t2, interval, copy_mean;
// printk(KERN_INFO "Bridging read, calling original...\n");
// rdtscll(t1);
ret = old_read(regs); /* ret has the bytes read */
// rdtscll(t2);
__asm__("movl %%esp, %0": "=m"(tmp):);
regs = *tmp;
return (ret);
}
I even removed the counters and statistics. The replacement goes fine, but when I try to rmmod the module I get an Oops like this (This is a partial output):
*pde=018ed067
*pte=00000000
Oops: 0000 [#1]
PREEMPT
Modules linked in: <here comes the list of modules>
CPU: 0
EIP: 0060: [<f8ad234a>] Tainted: P VLI
EFLAGS: 00010286 ( 2.6.15.6)
EIP is at 0xf8ad234a
eax: 00000033 ebx: 0000000 ecx: 00000033 edx: 0000000
esi: 0000001 edi: 0000000 ebp: f78d4000 esp: f78d5f78
ds: 007b es: 007b ss: 0068
Process klogd (pid: 2539, threadinfo=f78d4000 task=f78c0a50)
..
..
Call Trace:
[<c0102b79>] syscall_call + 0x7/0xb
Code: Bad EIP value
I don't know what I'm doing wrong... the other syscalls I catched (brk, fork and vfork) works fine.
Thanks in advance.
PS: Are there any tricks to get the complete output when getting an Oops from kernel?