================================================================
syscallmgr, 
A manager for embedding system calls
by means of loadable modules

(C) 1994,1995 under GPL, Hans Lermen <lermen@elserv.ffm.fgan.de>
================================================================

NOTE: This packet was originally develloped for the DOSEMU-team


The aim of this packet is to speed up developement of DOSEMU and
other projects, that require heavy kernel support.
With this packet you can avoid the anoying patching/recompiling/reboot
of the Linux kernel and can develop syscalls and other kernel changes
on the fly on a running system. Sure, you MUST be uid root !

It is NOT the aim of this packet to generally replace hardcoded kernel
support by loadable modules, because this would lead to insecure behavour
of the kernel ! So, if all works, the critical parts should be put back
to the kernel source tree.

The package mainly consists of

1. The syscall manager
2. A modified insmod (from modules package)


1. The syscall manager
   ==================

   The loadable module syscallmgr.o allows to put system calls into a loadable
   module (wasn't supported by the kernel) without confusing the kernel by 
   double __NR__ syscall numbers. This would allow dosemu to do many things 
   in kernel space, that actually are can only be done via kernel patches 
   and/or device drivers.
   Syscallmgr.o should be loaded via insmod as first of all loadable modules
   and must stay loaded as long as there is any application and/or loadable
   module using it.

   Syscalls must be registered by other loadable modules before use as follows:

     register_syscall(nr_syscall, routine, name);
        nr_syscall  The number of the syscall (greater 140)
                    or ZERO, if allocating a number dynamically
        routine     Pointer to the new user syscall routine, must be conform
                    to the kernel interface, see below resolve_syscall routine
                    as an example.
        name        The identification string for this syscall, e.g the name of
                    the routine.
     It returns the desired or the allocated syscall number on success or
     or < 0 on error. As the kernel syscall interface (int 0x80) refuses numbers
     out of range, this is a save way, even if usinging an unallocated number.
  
   Syscall must be unregistered by the module's cleanup routine via:
  
     unregister_syscall(nr_syscall)
     where nr_syscall is the number delivered by register_syscall.
  
   At userlevel a program first must include syscallmgr.h 
   and get the allocated nr_syscall via:
  
     resolve_syscall(char *name, struct syscall_sym_entry *buf);
        name         identification string for the syscall
        buf          =NULL for normal purpose,
                     else address of a buffer to get the list of all
                     allocated user syscalls.
     It returns the syscall number or <0 on error (see above).
     To get the required size of "buf" you may do:
         size = resolve_syscall(0,0);
     to get the number of entries you may do:
         count=resolve_syscall(0,buf)
  
   Example (user level):
  
     #include <linux/unistd.h>
     #include "syscallmgr.h"
     
     int __NR_my_private_syscall=-1;
     /* defines: 
      * static inline my_private_syscall(char *hellotext);
      */
     static inline _syscall1(int,my_private_syscall, char *,hellotext);
  
     main() {
       struct syscall_sym_entry *p;
       int size,count,i;
       __NR_my_private_syscall = resolve_syscall("my_private_syscall",0);
       my_private_syscall("Hello Linux kernel");
       my_private_syscall("I'm not invited, but I'm here");
       size=resolve_syscall(0,0);
       p=malloc(size);
       count=resolve_syscall(0,p);
       for (i=0; i <count; i++) printf("nr=%d %s\n",p[i].nr, p[i].name);
     }
  
  

   NOTE:
   1. Naming convention with <unistd.h> is    __NR_routine_name, 
      but naming convention in <syscall.h> is SYS_routine_name !
      You can use all standard macros/function along with your syscall number.
   2. Syscallmgr can NOT be used to replace existing kernel resident syscalls.
      (though you may do it manually).



2. A modified insmod
   =================


   This is a modified insmod for development purpose, which can load a module
   even if some syms are undefined in ksyms. The addresses then come out
   of /usr/src/(z)System.map. To avoid reading the wrong map I compare the 
   known addresses from get_kernel_sym() against the ones in (z)System.map.
   So there is *very* low propability of crashes.

   Again:
     Together with syscallmgr.o this allowes nearly all freedom (if suid)
     without kernel patches !

   This insmod can be used as a replacement for the ./insmod contained
   in the official modules-1.2.8.tar.gz from Bjorn Ekwall and Jacques Gelinas.
   It can replace the official one, because the special features are switched
   on by command line options. Usage is:


   insmod [-f] [-x] [-o name] [-msvwl] [-z | -Z mapfile] module [[sym=value]...]

     module     Filename of a loadable kernel module (*.o)
     -o name    Set internal modulname to name
     -x         do *not* export externs
     -m         generate loadmap (so crashes can be traced down)
     -v         verbose output
     -s         set insmod syslogging
     -w         print warnings
     -f         Force loading under wrong kernel version
                (together with -z also disables mapfile check)
     -z         At last use /usr/src/linux/zSystem.map to resolve
                (on Linux > 1.1.76:  System.map)
     -Z mapfile As -z, but use mapfile
     -l         Together with -z, -Z, also take local symbols from map
                (But note, local symbols can be multiple defined, last one is
                taken)


  NOTE:

  A.    This feature was added to insmod by the DOSEMU-team
        and released as part of the dosemu-distribution 
        much *earlier* then the release of modules-1.1.67.
        Unfortunately the meanings of the -m switch differs.
        Because of this I decided to take over the meaning from the official
        moduls release. This feature can be enabled via HACKER_TOOL.
        So, for old users of dosemu's insmod:  -m, -M  becomes -z, -Z ! Ok?
        Starting with Linux 1.1.76 the zSystem.map exists no longer,
        and is replaced by System.map (same file structure), but don't worry,
        if zSystem.map is not found, System.map is taken by default.
 
  B.    You may wonder why the dosemu team did not take effort to get
        this feature part of the official modutils release ?
        In fact, we did (at state of Linux 1.1.83)! 
        Bjorn Ekwall, because he saw that the dosemu team needs this,
        put the HACKER_TOOL stuff into modutils-1.1.85, but on protest
        of Linus he had to remove it later for modutils-1.1.87.
        So, we have the ugly state to always repatch the modules stuff
        whenever a a new release comes up, ... sorry.
        To make this as easy as possible, the HACKER_TOOL routines are
        programmed as isolated as possible (the integrated stuff from
        modutils-1.1.85 was faster).



3. You may test this stuff with:

     ./insmod syscallmgr.o
     ./insmod -lz testsys.o
     ./testmain
     rmmod testsys
     rmmod syscall

   You then get a klog like this

   Oct 19 00:43:09 el15 kernel: Syscall_Modul, init_module called, NR_resolve_syscall=255
   Oct 19 00:44:27 el15 kernel: Testsys, init_module called, NR_testsys=141
   Oct 19 00:44:59 el15 kernel: Testsys: >hello<
   Oct 19 00:44:59 el15 kernel: Testsys: code at fast_IRQ10_interrupt=501e06fc
   Oct 19 00:47:18 el15 kernel: Testsys: cleanup modul called
   Oct 19 00:54:32 el15 kernel: Syscall_Modul: cleanup modul called

   The testsys.c is also an example of how to even resolve local kernel symbols


Try it, and let me know how it works!
Hans <lermen@elserv.ffm.fgan.de>
