* FW: trapping syscall problem - kernel module
@ 2001-09-24 4:55 Tony.Young
0 siblings, 0 replies; only message in thread
From: Tony.Young @ 2001-09-24 4:55 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 2658 bytes --]
If anyone here can help with the attached problem I'd appreciate it.
Please CC any responses to me as I'm not on the list.
TIA
Tony...
> -----Original Message-----
> From: Tony Young
> Sent: Friday, 21 September 2001 17:24
> To: 'slug@slug.org.au'
> Subject: trapping syscall problem - kernel module
>
>
> This is a question for those kernel hackers on the list that
> know about developing modules to trap/intercept system calls.
>
> I'm trying to develop a module that detects calls to
> fork/vfork, execve and exit to track processes on the system.
> I've implemented a module that will do this on Solaris - it
> was relatively simple. However I'm having trouble
> implementing a similar module on Linux.
>
> I've attached my source code and makefile - it should be safe
> to compile and load. But I make no guarantees. I've been
> testing and developing it on a 2.4.8 kernel - single
> cpu(Mandrake 8.1 beta).
> <<syscall.c>> <<makefile>>
> The module is fairly basic. It replaces each system call with
> my own that just displays some information using printk and
> calls the original.
> The fork, vfork and exit replacements work fine. But I'm
> having trouble with execve.
>
> With the implementation in the code that's currently enabled
> (inside #if 1 in newexecve()) any execve results in the
> calling process core dumping. The printk's before and after
> the call to oldexecve work which implies that the execve
> actually worked. But something appears to be going wrong
> returning from the function.
>
> This implementation is similar to the implementation of my
> Solaris module. After failure on linux though I went looking
> for alternatives and found another way of doing it which
> basically just bypasses the sys_execve(oldexecve) syscall
> entirely, calling do_execve itself. This method, as expected,
> works. However, if the implementation of sys_execve ever
> changes I'll need to change my implementation to match - I'd
> rather leverage of sys_execve if at all possible.
>
> So I guess what I'm asking is why my implementation doesn't
> work? I'm guessing that something's going on with
> sys_execve's use of the registers that's somehow trashing the
> stack or return pointer when used my way but I'm not sure.
>
> I haven't yet tried the kernel debugger to see what's going
> on - simply because I've never used it before.
>
> Any help anyone could provide would be great.
>
> Thanks.
> Tony...
>
> --
> Tony Young
> Senior Software Engineer
> Integrated Research Limited
> Level 10, 168 Walker St
> North Sydney, NSW 2060, Australia
> Ph: +61 2 9966 1066
> Fax: +61 2 9966 1042
>
[-- Attachment #2: syscall.c --]
[-- Type: application/octet-stream, Size: 4550 bytes --]
/*
* syscall.c
*
* gcc -D__KERNEL__ -DMODULE -c syscall.o syscall.c
*/
#include <linux/module.h>
#include <linux/kernel.h> /* printk */
#include <sys/syscall.h> /* SYS_... */
#include <linux/sched.h> /* task_struct */
#include <asm/current.h> /* current */
#include <asm/errno.h>
#include <asm/smplock.h>
#include <linux/slab.h>
int errno;
/*
* SYS_exit 1
* SYS_fork 2
* SYS_vfork 190
* SYS_execve 11
*/
extern void* sys_call_table[];
asmlinkage int (*oldfork)(struct pt_regs regs);
asmlinkage int (*oldvfork)(struct pt_regs regs);
asmlinkage int (*oldexecve)(struct pt_regs regs);
asmlinkage void (*oldexit)(int rc);
asmlinkage int newfork(struct pt_regs regs)
{
int childpid;
printk(KERN_DEBUG "newfork: fork called by PID %ld (%s)\n", current->pid, current->comm);
childpid = oldfork(regs);
if (childpid != -1)
printk(KERN_DEBUG "newfork: process PID %ld (%s) created child %ld\n", current->pid, current->comm, childpid);
else
printk(KERN_DEBUG "newfork: process PID %ld (%s) failed to create child\n", current->pid, current->comm);
return childpid;
}
asmlinkage int newvfork(struct pt_regs regs)
{
int childpid;
printk(KERN_DEBUG "newvfork: vfork called by PID %ld (%s)\n", current->pid, current->comm);
childpid = oldvfork(regs);
if (childpid != -1)
printk(KERN_DEBUG "newvfork: process PID %ld (%s) created child %ld\n", current->pid, current->comm, childpid);
else
printk(KERN_DEBUG "newvfork: process PID %ld (%s) failed to create child\n", current->pid, current->comm);
return childpid;
}
asmlinkage int newexecve(struct pt_regs regs)
{
int rc;
/* From modexecvehash */
char *filename;
printk(KERN_DEBUG "newexecve: execve called by PID %ld (%s) - %lp\n", current->pid, current->comm, oldexecve);
#if 0
lock_kernel();
filename = getname((char*)regs.ebx);
rc = PTR_ERR(filename);
if (!IS_ERR(filename))
{
rc = do_execve(filename, (char **)regs.ecx, (char **)regs.edx, ®s);
if (rc == 0)
{
current->ptrace &= ~PT_DTRACE;
printk(KERN_DEBUG "newexecve: process PID %ld execve'd (%s)\n", current->pid, current->comm);
}
else
printk(KERN_DEBUG "newexecve: process PID %ld failed to execve (%s) - rc = %d\n", current->pid, filename, rc);
unlock_kernel();
putname(filename);
}
#endif
#if 1
rc = oldexecve(regs);
if (rc == 0)
printk(KERN_DEBUG "newexecve: process PID %ld execve'd (%s)\n", current->pid, current->comm);
else
printk(KERN_DEBUG "newexecve: process PID %ld failed to execve - rc = %d\n", current->pid, rc);
#endif
/* restore the original execve so that if ours breaks down
* we can still create processes and not make the system unusable
*/
sys_call_table[SYS_execve] = oldexecve;
printk(KERN_DEBUG "cleanup_module: old execve syscall restored\n");
return rc;
}
asmlinkage void newexit(int rc)
{
printk(KERN_DEBUG "newexit: exit called by PID %ld (%s) with rc %d\n", current->pid, current->comm, rc);
oldexit(rc);
}
int init_module()
{
printk(KERN_DEBUG "init_module: syscall mod loaded\n");
//sys_call_table_addr = (func_ptr**)sys_call_table;
oldfork = (int(*)())sys_call_table[SYS_fork];
sys_call_table[SYS_fork] = newfork;
printk(KERN_DEBUG "init_module: fork syscall replaced\n");
oldvfork = (int(*)())sys_call_table[SYS_vfork];
sys_call_table[SYS_vfork] = newvfork;
printk(KERN_DEBUG "init_module: vfork syscall replaced\n");
oldexecve = (int(*)())sys_call_table[SYS_execve];
sys_call_table[SYS_execve] = newexecve;
printk(KERN_DEBUG "init_module: execve syscall replaced\n");
oldexit = (void(*)())sys_call_table[SYS_exit];
sys_call_table[SYS_exit] = newexit;
printk(KERN_DEBUG "init_module: exit syscall replaced\n");
return 0;
}
void cleanup_module()
{
sys_call_table[SYS_fork] = oldfork;
printk(KERN_DEBUG "cleanup_module: old fork syscall restored\n");
sys_call_table[SYS_vfork] = oldvfork;
printk(KERN_DEBUG "cleanup_module: old vfork syscall restored\n");
sys_call_table[SYS_execve] = oldexecve;
printk(KERN_DEBUG "cleanup_module: old execve syscall restored\n");
sys_call_table[SYS_exit] = oldexit;
printk(KERN_DEBUG "cleanup_module: old exit syscall restored\n");
printk(KERN_DEBUG "cleanup_module: syscall mod removed\n");
}
[-- Attachment #3: makefile --]
[-- Type: application/octet-stream, Size: 160 bytes --]
CFLAGS=-D__KERNEL__ -DMODULE -O -g
CC=gcc
all: clean syscall.o
clean:
rm -f syscall.o
in:
sudo insmod ./syscall.o
out:
sudo rmmod syscall
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2001-09-24 4:55 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-09-24 4:55 FW: trapping syscall problem - kernel module Tony.Young
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®