mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tony.Young@ir.com
To: linux-kernel@vger.kernel.org
Subject: FW: trapping syscall problem - kernel module
Date: Mon, 24 Sep 2001 14:55:51 +1000	[thread overview]
Message-ID: <C0D2F5944500D411AD8A00104B31930E8D409B@ir_nt_server2> (raw)

[-- 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, &regs);
      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


                 reply	other threads:[~2001-09-24  4:55 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=C0D2F5944500D411AD8A00104B31930E8D409B@ir_nt_server2 \
    --to=tony.young@ir.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®