/* ** Purpose: SCSLogger logs the use of the connect(), accept() and shutdown() system call ** Last Update: 1999/03/09 ** Author: Thomas Biege (thomas@suse.de) ** Plattform: Linux 2.0.36 ** Install: gcc -O -c scslog.c ** insmod scslog.o */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*#include */ /*#include */ #define UC(b) ( ((int)b) & 0xff ) #define VERIFY_READ 0 #define GFP_KERNEL 0x03 struct task_struct { /* these are hardcoded - don't touch */ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ long counter; long priority; unsigned long signal; unsigned long blocked; /* bitmap of masked signals */ unsigned long flags; /* per process flags, defined below */ int errno; long debugreg[8]; /* Hardware debugging registers */ struct exec_domain *exec_domain; /* various fields */ struct linux_binfmt *binfmt; struct task_struct *next_task, *prev_task; struct task_struct *next_run, *prev_run; unsigned long saved_kernel_stack; unsigned long kernel_stack_page; int exit_code, exit_signal; /* ??? */ unsigned long personality; int dumpable:1; int did_exec:1; /* shouldn't this be pid_t? */ int pid; int pgrp; int tty_old_pgrp; int session; /* boolean value for session group leader */ int leader; int groups[NGROUPS]; /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with * p->p_pptr->pid) */ struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; struct wait_queue *wait_chldexit; /* for wait4() */ unsigned short uid,euid,suid,fsuid; unsigned short gid,egid,sgid,fsgid; unsigned long timeout, policy, rt_priority; unsigned long it_real_value, it_prof_value, it_virt_value; unsigned long it_real_incr, it_prof_incr, it_virt_incr; struct timer_list real_timer; long utime, stime, cutime, cstime, start_time; /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; int swappable:1; unsigned long swap_address; unsigned long old_maj_flt; /* old value of maj_flt */ unsigned long dec_flt; /* page fault count of the last time */ unsigned long swap_cnt; /* number of pages to swap on next pass */ /* limits */ struct rlimit rlim[RLIM_NLIMITS]; unsigned short used_math; char comm[16]; /* file system info */ int link_count; struct tty_struct *tty; /* NULL if no tty */ /* ipc stuff */ struct sem_undo *semundo; struct sem_queue *semsleeping; /* ldt for this task - used by Wine. If NULL, default_ldt is used */ struct desc_struct *ldt; /* tss for this task */ struct thread_struct tss; /* filesystem information */ struct fs_struct *fs; /* open file information */ struct files_struct *files; /* memory management info */ struct mm_struct *mm; /* signal handlers */ struct signal_struct *sig; #ifdef __SMP__ int processor; int last_processor; int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ #endif }; extern struct task_struct *current_set[NR_CPUS]; #define current (0+current_set[smp_processor_id()]) int errno; extern void *sys_call_table[]; int (*origsockcall) (int, unsigned long *); struct in_addr { unsigned int s_addr; }; struct sockaddr_in { __SOCKADDR_COMMON (sin_); unsigned short int sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof(struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof(unsigned short int) - sizeof(struct in_addr)]; }; /*****************************************************************************/ char *inet_ntoa(struct in_addr in) { static char b[28] = {0}; char *p; p = (char *) &in.s_addr; /* b[0] = p[0]; b[1] = '.'; b[2] = (char) UC(p[1]); b[3] = '.'; b[4] = (char) UC(p[2]); b[5] = '.'; b[6] = (char) UC(p[3]); b[7] = 0; */ sprintf(b, "%d.%d.%d.%d", UC(p[3]), UC(p[2]), UC(p[1]), UC(p[0])); return(b); } char *in_ntoa(unsigned long in) { static char buff[18]; char *p; p = (char *) ∈ sprintf(buff, "%d.%d.%d.%d", (p[0] & 255), (p[1] & 255), (p[2] & 255), (p[3] & 255)); return(buff); } extern int scslog(int call, u_long *args) { u_long arg_sin, arg_len; struct sockaddr_in *sin_in; void *k_buf; u_char nargs[18]={0,3,3,3,2,3,3,3,4,4,4,6,6,2,5,5,3,3}; if(verify_area(VERIFY_READ, args, nargs[call] * sizeof(u_long))) { printk("<1>SCSLog - ERROR: verify_area()\n"); return(-1); } arg_sin = get_user(args+1); arg_len = get_user(args+2); if((size_t)arg_len = sizeof(struct sockaddr_in)) { k_buf = kmalloc((u_int)sizeof(struct sockaddr_in), GFP_KERNEL); if(k_buf == NULL) { printk("<1>SCSLog - ERROR: kmalloc()\n"); return((*origsockcall)(call, args)); } memcpy_fromfs(k_buf, (void *) args+1, sizeof(struct sockaddr_in)) ; sin_in = (struct sockaddr_in *) k_buf; switch(call) { case SYS_CONNECT: printk("<1>SCSLog: connect - Name: %s | UID: %lu | EUID: %lu | PID: %lu | IP: %s | Port: %hu\n", current->comm, current->uid, current->euid, current->pid, in_ntoa(ntohl(sin_in->sin_addr.s_addr)), ntohs(sin_in->sin_port)); break; case SYS_ACCEPT: printk("<1>SCSLog: accept - Name: %s | UID: %lu | EUID: %lu | PID: %lu\n", current->comm, current->uid, current->euid, current->pid); break; case SYS_SHUTDOWN: printk("<1>SCSLog: shutdown - Name: %s | UID: %lu | EUID: %lu | PID: %lu\n", current->comm, current->uid, current->euid, current->pid); break; } } kfree(k_buf); return((*origsockcall)(call, args)); } int init_module(void) { origsockcall = sys_call_table[SYS_socketcall]; sys_call_table[SYS_socketcall] = (void *) scslog; printk("<1>SCSLog loaded - Thomas Biege (dod@muenster.net)\n"); return(0); } void cleanup_module(void) { sys_call_table[SYS_socketcall] = origsockcall; printk("<1>SCSLog released\n"); } /* eof */