source: trunk/src/samhain_hide.c @ 443

Last change on this file since 443 was 443, checked in by katerina, 8 years ago

Fix for ticket #347 (the --enable-khide option does not work on Linux 3.x)

File size: 22.9 KB
Line 
1/***************************************************************************
2 *
3 * Purpose:
4 * -------
5 *   (1) Hide files with the string MAGIC_HIDE in filename,
6 *       where MAGIC_HIDE is defined below.
7 *       By default,  MAGIC_HIDE is defined as "samhain".
8 *
9 *   (2) Hide all processes, if the executable has the string MAGIC_HIDE
10 *       in its name.
11 *
12 *
13 * Configuration:
14 * -------------
15 *   If not building within the samhain system, you may remove the
16 *   line '#include "config.h"' and in the line
17 *   '#define MAGIC_HIDE SH_MAGIC_HIDE', replace SH_MAGIC_HIDE with
18 *   "someString" (in quotes !).
19 */
20
21/* #define _(string) string */
22#include "config.h"
23
24#undef _
25#define _(string) string
26
27/* define if this is a 2.6 kernel                 */
28/* #define LINUX26                                */
29
30#define MAGIC_HIDE SH_MAGIC_HIDE
31
32/*  #define MAGIC_HIDE "someString"               */
33
34/* define this if you have a modversioned kernel  */
35/*  #define MODVERSIONS                           */
36
37/* the address of the sys_call_table (not exported in 2.5 kernels) */
38#define MAGIC_ADDRESS SH_SYSCALLTABLE
39
40/*
41 * Install:
42 * -------
43 *   gcc -Wall -O2 -c samhain_hide.c
44 *   mv samhain_hide.o  /lib/modules/KERNEL_VERSION/misc/
45 *   
46 *   (Replace KERNEL_VERSION with your kernel's version.)
47 *
48 * Usage:
49 * -----
50 *   To load the module:
51 *    insmod samhain_hide (for improved safety: 'sync && insmod samhain_hide')
52 *
53 *   Self-hiding can be switched off by passing the option
54 *   'removeme=0' to the module:
55 *    insmod ./samhain_hide.ko removeme=0
56 *
57 *   To unload the module (only possible if not hidden):
58 *    rmmod samhain_hide  (for improved safety: 'sync && rmmod samhain_hide')
59 *
60 *
61 * Details:
62 * -------
63 *   The following kernel syscalls are replaced:
64 *     sys_getdents     [hide files/directories/processes (/proc/PID)]
65 *
66 * Tested on:
67 * ---------
68 *   Linux 2.2, 2.4, 2.6
69 *
70 * Copyright:
71 * ---------
72 *   Copyright (C) 2001, 2002 Rainer Wichmann (http://la-samhna.de)
73 *
74 * License:
75 * -------
76 *   This program is free software; you can redistribute it and/or modify
77 *   it under the terms of the GNU General Public License, version 2, as
78 *   published by the Free Software Foundation.
79 *                                                                         
80 *   This program is distributed in the hope that it will be useful,       
81 *   but WITHOUT ANY WARRANTY; without even the implied warranty of         
82 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
83 *   GNU General Public License for more details.                           
84 *                                                                         
85 *   You should have received a copy of the GNU General Public License     
86 *   along with this program; if not, write to the Free Software           
87 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             
88 *
89 ***************************************************************************/
90
91
92
93/*****************************************************
94 *
95 *  The defines:
96 *
97 *****************************************************/
98
99/* This is a Linux Loadable Kernel Module.
100 */
101
102#ifndef LINUX26
103#ifndef __KERNEL__
104#define __KERNEL__
105#endif
106#ifndef MODULE
107#define MODULE
108#endif
109#endif
110#define LINUX
111
112/* Define for debugging.   
113 */
114/* #define HIDE_DEBUG  */   /* query_module */
115/* #define FILE_DEBUG  */   /* getdents     */
116/* #define READ_DEBUG  */   /* read         */
117/* #define PROC_DEBUG  */   /* procfs       */
118/* #define INIT_DEBUG  */   /* module init  */
119
120/*****************************************************
121 *
122 *  The include files:
123 *
124 *****************************************************/
125
126
127/* The configure options (#defines) for the Kernel
128 */
129#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
130/* 2.6.19 (((2) << 16) + ((6) << 8) + (19)) */
131#define SH_KERNEL_MIN 132627
132
133#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,33)
134#include <generated/autoconf.h>
135#else
136#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,19)
137#include <linux/autoconf.h>
138#else
139#include <linux/config.h>
140#endif
141#endif
142
143#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,0)
144#ifdef CONFIG_MODVERSIONS
145#include <linux/modversions.h>
146#endif
147#else
148#ifndef LINUX26
149#define LINUX26
150#endif
151#endif
152
153#ifdef LINUX26
154#include <linux/init.h>
155#endif
156
157#include <linux/module.h>
158
159/* File tables structures. If directory caching is used,
160 * <linux/dcache.h> will be included here, and __LINUX_DCACHE_H
161 * will thus be defined.
162 */
163#include <linux/fs.h>
164#include <linux/proc_fs.h>
165
166/* Include the SYS_syscall defines.
167 */
168#ifndef LINUX26
169#include <sys/syscall.h>
170#else
171#define SYS_getdents 141
172#define SYS_getdents64 220
173#endif
174
175
176/* Includes for 'getdents' per the manpage.
177 */
178#include <linux/types.h>
179#include <linux/dirent.h>
180#include <linux/unistd.h>
181
182/* To access userspace memory.
183 */
184#include <asm/uaccess.h>
185
186/* Include for lock_kernel().
187 */
188#if SH_KERNEL_NUMERIC < KERNEL_VERSION(3,0,0)
189#include <linux/smp_lock.h>
190#else
191static inline void lock_kernel(void) { }
192static inline void unlock_kernel(void) { }
193#endif
194
195#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
196#include <linux/mutex.h>
197#endif
198
199/* Include for fget().
200 */
201#include <linux/file.h>
202#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,26)
203#include <linux/fdtable.h>
204#endif
205
206/*****************************************************
207 *
208 *  The global variables:
209 *
210 *****************************************************/
211
212/* The kernel syscall table. Not exported anymore in 2.5 ff., and also
213 * not in the RedHat 2.4 kernel.
214 */
215
216#if 0
217extern void * sys_call_table[];
218#define sh_sys_call_table sys_call_table
219#endif
220
221unsigned long * sh_sys_call_table = (unsigned long *) MAGIC_ADDRESS;
222
223/* The old address of the sys_getdents syscall.
224 */
225#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
226int (*old_getdents)(unsigned int, struct dirent *, unsigned int);
227#else
228
229struct linux_dirent {
230  unsigned long   d_ino;
231  unsigned long   d_off;
232  unsigned short  d_reclen;
233  char            d_name[1];
234};
235
236int (*old_getdents)(unsigned int, struct linux_dirent *, unsigned int);
237#endif
238
239#ifdef __NR_getdents64
240#if SH_KERNEL_NUMERIC >= 132628
241/*
242 * 'asmlinkage' is __required__ to get this to work.
243 */
244asmlinkage long (*old_getdents64)(unsigned int, struct linux_dirent64 __user *, unsigned int);
245#else
246long (*old_getdents64)(unsigned int, struct dirent64 *, unsigned int);
247#endif
248#endif
249
250char hidden[] = MAGIC_HIDE;
251 
252
253/*****************************************************
254 *
255 *  The functions:
256 *
257 *****************************************************/
258
259
260MODULE_AUTHOR("Rainer Wichmann");
261MODULE_DESCRIPTION("Hide files/processes/modules with MAGIC_HIDE in name.");
262#if defined(MODULE_LICENSE) || defined(LINUX26)
263MODULE_LICENSE("GPL"); 
264#endif
265
266#ifdef LINUX26
267/* Default is to hide ourselves.
268 */
269static int removeme = 1;
270
271#ifdef MODULE_PARM
272MODULE_PARM (removeme, "i");
273#else
274module_param(removeme, int, 0444);
275#endif
276
277#ifdef MODULE_PARM_DESC
278MODULE_PARM_DESC(removeme, "Choose zero for not hiding.");
279#endif
280
281/* LINUX26 */
282#endif
283
284
285/*
286 *  struct task_struct is defined in linux/sched.h
287 *
288 *  as of 2.4.20, the vanilla kernel holds (among others):
289 *        struct task_struct *next_task, *prev_task;
290 *
291 *  Redhat kernel seems to have a different scheduler.
292 *  use:
293 *        struct task_struct * find_task_by_pid (int pid);
294 */
295
296#if defined(SH_VANILLA_KERNEL) && !defined(LINUX26)
297/*
298 * Fetch the task struct for a given PID.
299 */
300struct task_struct * fetch_task_struct (int pid)
301{
302  struct task_struct * task_ptr;
303
304#ifdef PROC_DEBUG
305  printk("FETCH TASK %d\n", pid);
306#endif
307
308  task_ptr = current;
309
310  do 
311    {
312      if (task_ptr->pid == (pid_t) pid )
313        return (task_ptr);
314      task_ptr = task_ptr->next_task;
315    } 
316  while (task_ptr != current);
317
318#ifdef PROC_DEBUG
319  printk("FETCH TASK: NOT FOUND !!!\n");
320#endif
321
322  return (NULL);
323}
324
325#else
326#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,25)
327struct task_struct * fetch_task_struct (int pid)
328{
329  struct task_struct * task_ptr = NULL;
330  task_ptr = find_task_by_pid (pid);
331  return (task_ptr);
332}
333#else
334struct task_struct * fetch_task_struct (int pid)
335{
336  struct task_struct * task_ptr = NULL;
337  struct pid * task_pid = find_vpid(pid);
338  if (task_pid)
339    {
340      task_ptr = pid_task (task_pid, PIDTYPE_PID);
341    }
342  return (task_ptr);
343}
344#endif
345#endif
346
347/* Convert a string to an int.
348 * Does not recognize integers with a sign (+/-) in front.
349 */
350int my_atoi(char * in_str)
351{
352  int i      = 0;
353  int retval = 0;
354  int conv   = 0;
355
356  if (in_str == NULL)
357    return (-1);
358
359  while(in_str[i] != '\0')
360    {
361      /* Break if not numeric.
362       */
363      if (in_str[i] < '0' || in_str[i] > '9')
364        break;
365
366      ++conv;
367     
368      /* Leading zeroes (should not happen in /proc)
369       */
370      if (retval == 0 && in_str[i] == '0')
371        retval = retval;
372      else
373        retval = retval * 10;
374
375      retval = retval + (in_str[i] - '0');
376
377      i++;
378    }
379     
380  if (conv == 0)
381    return (-1);
382  else
383    return (retval); 
384}
385
386/* Purpose:
387 *
388 *   Hide all files/dirs that include the string MAGIC_HIDE in their
389 *   name.
390 */
391#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
392int new_getdents (unsigned int fd, struct dirent *dirp, unsigned int count)
393#else
394int new_getdents (unsigned int fd, struct linux_dirent *dirp, unsigned int count)
395#endif
396{
397  int                  status = 0;    /* Return value from original getdents */
398  struct inode       * dir_inode;
399  struct file        * fd_file;
400  int                  dir_is_proc = 0;
401
402#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
403  struct dirent      * dirp_prev;
404  struct dirent      * dirp_new;
405  struct dirent      * dirp_current;
406#else
407  struct linux_dirent      * dirp_prev;
408  struct linux_dirent      * dirp_new;
409  struct linux_dirent      * dirp_current;
410#endif
411
412  int                  dir_table_bytes;
413  int                  forward_bytes;
414  struct task_struct * task_ptr;
415  int                  hide_it = 0;
416  long                 dirp_offset;
417
418  unsigned long        dummy;
419
420  lock_kernel();
421
422  status = (*old_getdents)(fd, dirp, count);
423
424#ifdef FILE_DEBUG
425  printk("STATUS %d\n", status);
426#endif
427 
428  /*  0: end of directory.
429   * -1: some error
430   */
431  if (status <= 0)
432    {
433      unlock_kernel();
434      return (status);
435    }
436 
437  /* Handle directory caching. dir_inode is the inode of the directory.
438   */
439#if defined(files_fdtable)
440  {
441    struct fdtable *fdt = files_fdtable(current->files);
442    fd_file = rcu_dereference(fdt->fd[fd]);
443  }
444#else
445  {
446    fd_file = current->files->fd[fd];
447  }
448#endif
449 
450#if defined(__LINUX_DCACHE_H)
451  dir_inode  = fd_file->f_dentry->d_inode;
452#else
453  dir_inode  = fd_file->f_inode;
454#endif
455
456  /* Check for the /proc directory
457   */
458  if (dir_inode->i_ino == PROC_ROOT_INO
459#ifndef LINUX26
460      && !MAJOR(dir_inode->i_dev) && 
461      MINOR(dir_inode->i_dev) == 1
462#endif
463      )
464    dir_is_proc = 1;
465
466  /* Allocate space for new dirent table. Can't use GFP_KERNEL
467   * (kernel oops)
468   */
469#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
470  dirp_new = (struct dirent *) kmalloc (status, GFP_ATOMIC);
471#else
472  dirp_new = (struct linux_dirent *) kmalloc (status, GFP_ATOMIC);
473#endif
474
475  if (dirp_new == NULL)
476    {
477      unlock_kernel();
478      return (status);
479    }
480
481  /* Copy the dirp table to kernel space.
482   */
483  dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
484
485#ifdef FILE_DEBUG
486  printk("COPY to kernel: %ld\n", dummy);
487#endif
488
489  /* Loop over the dirp table to find entries to hide.
490   */
491  dir_table_bytes = status;
492  dirp_current    = dirp_new;
493  dirp_prev       = NULL;
494
495  while (dir_table_bytes > 0)
496    {
497      hide_it = 0;
498
499      if (dirp_current->d_reclen == 0)
500        break;
501
502      dirp_offset = dirp_current->d_off;
503     
504#ifdef FILE_DEBUG
505      printk("DIRENT %d  %d  %ld\n", 
506             dir_table_bytes,
507             dirp_current->d_reclen,
508             dirp_current->d_off);
509#endif
510
511      dir_table_bytes -= dirp_current->d_reclen;
512      forward_bytes    = dirp_current->d_reclen;
513
514#ifdef FILE_DEBUG
515      printk("ENTRY %s\n", dirp_current->d_name);
516#endif
517
518      /* If /proc is scanned (e.g. by 'ps'), hide the entry for
519       * any process where the executable has MAGIC_HIDE in its name.
520       */
521      if (dir_is_proc == 1)
522        {
523          task_ptr = fetch_task_struct(my_atoi(dirp_current->d_name));
524          if (task_ptr != NULL)
525            {
526              if (strstr(task_ptr->comm, hidden) != NULL)
527                hide_it = 1;
528            }
529        }
530      /* If it is a regular directory, hide any entry with
531       * MAGIC_HIDE in its name.
532       */
533      else
534        {
535          if (strstr (dirp_current->d_name, hidden) != NULL)
536            hide_it = 1;
537        }
538
539      if (hide_it == 1)
540        {
541#ifdef FILE_DEBUG
542          printk("  -->HIDDEN %s\n", dirp_current->d_name);
543#endif
544          if (dir_table_bytes > 0)
545            {
546              status -= dirp_current->d_reclen;
547              memmove (dirp_current, 
548                       (char *) dirp_current + dirp_current->d_reclen, 
549                       dir_table_bytes);
550
551              /* Set forward_bytes to 0, because now dirp_current is the
552               * (previously) next entry in the dirp table.
553               */
554              forward_bytes    = 0;
555              dirp_prev        = dirp_current;
556            }
557          else
558            {
559              status -= dirp_current->d_reclen;
560              if (dirp_prev != NULL)
561                dirp_prev->d_off = dirp_offset;
562            }
563         
564        }
565      else
566        {
567          dirp_prev        = dirp_current;
568          if (dir_table_bytes == 0 && dirp_prev != NULL)
569            dirp_prev->d_off = dirp_offset;
570        }
571
572      /* Next entry in dirp table.
573       */
574#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
575      if (dir_table_bytes > 0)
576        dirp_current = (struct dirent *) ( (char *) dirp_current + 
577                                           forward_bytes);
578#else
579      if (dir_table_bytes > 0)
580        dirp_current = (struct linux_dirent *) ( (char *) dirp_current + 
581                                           forward_bytes);
582#endif
583    }
584
585  /* Copy our modified dirp table back to user space.
586   */
587  dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
588#ifdef FILE_DEBUG
589  printk("COPY to user: %ld\n", dummy);
590#endif
591
592  kfree (dirp_new);
593#ifdef FILE_DEBUG
594  printk("KFREE\n");
595#endif
596
597  unlock_kernel();
598  return (status);
599}
600
601
602
603/* For 2.4 kernel
604 */
605#ifdef __NR_getdents64
606
607#if SH_KERNEL_NUMERIC >= 132628
608/*
609 * 'asmlinkage' is __required__ to get this to work.
610 */
611asmlinkage long new_getdents64 (unsigned int fd, struct linux_dirent64 __user *dirp, 
612                                unsigned int count)
613#else
614long new_getdents64 (unsigned int fd, struct dirent64 *dirp, unsigned int count)
615#endif
616{
617  long                 status = 0;    /* Return value from original getdents */
618  struct inode       * dir_inode;
619  struct file        * fd_file;
620  int                  dir_is_proc = 0;
621
622#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
623  struct dirent64    * dirp_prev;
624  struct dirent64    * dirp_new;
625  struct dirent64    * dirp_current;
626#else
627  struct linux_dirent64    * dirp_prev;
628  struct linux_dirent64    * dirp_new;
629  struct linux_dirent64    * dirp_current;
630#endif
631
632  int                  dir_table_bytes;
633  int                  forward_bytes;
634  struct task_struct * task_ptr;
635  int                  hide_it = 0;
636  __s64                dirp_offset;
637
638  unsigned long        dummy;
639
640#ifdef FILE_DEBUG
641  printk("FD64 %d\n", fd);
642#endif
643
644  lock_kernel();
645
646#ifdef FILE_DEBUG
647  if (!access_ok(VERIFY_WRITE, dirp, count))
648    printk("ACCESS64_BAD\n");
649  else
650    printk("ACCESS64_OK\n");
651#endif
652
653#if SH_KERNEL_NUMERIC >= 132628
654  status = (*old_getdents64)(fd, dirp, count);
655  /* status = my_real_getdents64(fd, dirp, count); */
656#else
657  status = (*old_getdents64)(fd, dirp, count);
658#endif
659
660#ifdef FILE_DEBUG
661  printk("STATUS64 %ld\n", status);
662#endif
663
664  /*  0: end of directory.
665   * -1: some error
666   */
667  if (status <= 0)
668    {
669      unlock_kernel();
670      return (status);
671    }
672
673  /* Handle directory caching. dir_inode is the inode of the directory.
674   */
675#if defined(files_fdtable)
676  {
677    struct fdtable *fdt = files_fdtable(current->files);
678    fd_file = rcu_dereference(fdt->fd[fd]);
679  }
680#else
681  {
682    fd_file = current->files->fd[fd];
683  }
684#endif
685
686#if defined(__LINUX_DCACHE_H)
687
688/* 2.6.20 (((2) << 16) + ((6) << 8) + (20)) */
689#if SH_KERNEL_NUMERIC >= 132628
690  dir_inode  = fd_file->f_path.dentry->d_inode;
691#else
692  dir_inode  = fd_file->f_dentry->d_inode;
693#endif
694
695#else
696  dir_inode  = fd_file->f_inode;
697#endif
698
699#ifdef FILE_DEBUG
700  printk("INODE64\n");
701#endif
702
703  /* Check for the /proc directory
704   */
705  if (dir_inode->i_ino == PROC_ROOT_INO
706#ifndef LINUX26 
707      && !MAJOR(dir_inode->i_dev) /*  &&
708      MINOR(dir_inode->i_dev) == 1 */
709      /* MINOR commented out because of problems with 2.4.17 */
710#endif
711      )
712    {
713      dir_is_proc = 1;
714
715#ifdef PROC_DEBUG
716      printk("PROC_CHECK64\n");
717#endif
718    }
719
720  /* Allocate space for new dirent table. Can't use GFP_KERNEL
721   * (kernel oops)
722   */
723  dirp_new = kmalloc ((size_t)status, GFP_ATOMIC);
724
725#ifdef FILE_DEBUG
726  printk("KMALLOC64_0\n");
727#endif
728
729  if (dirp_new == NULL)
730    {
731      unlock_kernel();
732      return (status);
733    }
734
735#ifdef FILE_DEBUG
736  printk("KMALLOC64\n");
737#endif
738
739  /* Copy the dirp table to kernel space.
740   */
741  dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
742
743#ifdef FILE_DEBUG
744  printk("COPY64 to kernel: %ld\n", dummy);
745#endif
746
747  /* Loop over the dirp table to find entries to hide.
748   */
749  dir_table_bytes = status;
750  dirp_current    = dirp_new;
751  dirp_prev       = NULL;
752
753  while (dir_table_bytes > 0)
754    {
755      hide_it = 0;
756
757      if (dirp_current->d_reclen == 0)
758        break;
759
760      dirp_offset = dirp_current->d_off;
761     
762#ifdef FILE_DEBUG
763      printk("DIRENT %d  %d  %lld\n", 
764             dir_table_bytes,
765             dirp_current->d_reclen,
766             dirp_current->d_off);
767#endif
768
769      dir_table_bytes -= dirp_current->d_reclen;
770      forward_bytes    = dirp_current->d_reclen;
771
772#ifdef FILE_DEBUG
773      printk("ENTRY %s\n", dirp_current->d_name);
774#endif
775
776      /* If /proc is scanned (e.g. by 'ps'), hide the entry for
777       * any process where the executable has MAGIC_HIDE in its name.
778       */
779      if (dir_is_proc == 1)
780        {
781#ifdef PROC_DEBUG
782          printk("PROC %s\n", dirp_current->d_name);
783#endif
784          task_ptr = fetch_task_struct(my_atoi(dirp_current->d_name));
785          if (task_ptr != NULL)
786            {
787#ifdef PROC_DEBUG
788              printk("PROC %s <> %s\n", task_ptr->comm, hidden);
789#endif
790              if (strstr(task_ptr->comm, hidden) != NULL)
791                hide_it = 1;
792            }
793        }
794      /* If it is a regular directory, hide any entry with
795       * MAGIC_HIDE in its name.
796       */
797      else
798        {
799          if (strstr (dirp_current->d_name, hidden) != NULL)
800            hide_it = 1;
801        }
802
803      if (hide_it == 1)
804        {
805#ifdef FILE_DEBUG
806          printk("  -->HIDDEN %s\n", dirp_current->d_name);
807#endif
808          if (dir_table_bytes > 0)
809            {
810              status -= dirp_current->d_reclen;
811              memmove (dirp_current, 
812                       (char *) dirp_current + dirp_current->d_reclen, 
813                       dir_table_bytes);
814
815              /* Set forward_bytes to 0, because now dirp_current is the
816               * (previously) next entry in the dirp table.
817               */
818              forward_bytes    = 0;
819              dirp_prev        = dirp_current;
820            }
821          else
822            {
823              status -= dirp_current->d_reclen;
824              if (dirp_prev != NULL)
825                dirp_prev->d_off = dirp_offset;
826            }
827         
828        }
829      else
830        {
831          dirp_prev        = dirp_current;
832          if (dir_table_bytes == 0 && dirp_prev != NULL)
833            dirp_prev->d_off = dirp_offset;
834        }
835
836      /* Next entry in dirp table.
837       */
838#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
839      if (dir_table_bytes > 0)
840        dirp_current = (struct dirent64 *) ( (char *) dirp_current + 
841                                             forward_bytes);
842#else
843      if (dir_table_bytes > 0)
844        dirp_current = (struct linux_dirent64 *) ( (char *) dirp_current + 
845                                             forward_bytes);
846#endif
847    }
848
849  /* Copy our modified dirp table back to user space.
850   */
851#ifdef FILE_DEBUG
852  printk("STATUS64 AT END %ld\n", status);
853#endif
854  dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
855#ifdef FILE_DEBUG
856  printk("COPY64 to user: %ld\n", dummy);
857#endif
858
859  kfree (dirp_new);
860  unlock_kernel();
861  return (status);
862}
863#endif
864
865#ifdef LINUX26
866static struct module *sh_find_module(const char *name)
867{
868        struct module *mod;
869        struct list_head * modules = (struct list_head *) SH_LIST_MODULES;
870
871        list_for_each_entry(mod, modules, list) {
872                if (strcmp(mod->name, name) == 0)
873                        return mod;
874        }
875        return NULL;
876}
877#endif
878
879/* The initialisation function. Automatically called when module is inserted
880 * via the 'insmod' command.
881 */
882#ifdef LINUX26
883static int __init samhain_hide_init(void)
884#else
885int init_module(void)
886#endif
887{
888
889#ifdef INIT_DEBUG
890  printk("INIT 0\n");
891#endif
892
893  lock_kernel();
894
895#ifdef INIT_DEBUG
896  printk("INIT 1\n");
897#endif
898
899  /* Unfortunately this does not fully prevent the module from appearing
900   * in /proc/ksyms.
901   */
902#ifndef LINUX26
903  EXPORT_NO_SYMBOLS;
904#endif
905
906#ifdef INIT_DEBUG
907  printk("INIT 1a (%d)\n", SYS_getdents);
908#endif
909
910  /* Replace the 'sys_getdents' syscall with the new version.
911   */
912  old_getdents                        = (void*) sh_sys_call_table[SYS_getdents];
913#ifdef INIT_DEBUG
914  printk("INIT 1b\n");
915#endif
916  sh_sys_call_table[SYS_getdents]     = (unsigned long) new_getdents;
917 
918#ifdef INIT_DEBUG
919  printk("INIT 2\n");
920#endif
921
922#ifdef __NR_getdents64
923  old_getdents64                      = (void*) sh_sys_call_table[SYS_getdents64];
924  sh_sys_call_table[SYS_getdents64]   = (unsigned long) new_getdents64;
925#endif
926
927#ifdef INIT_DEBUG
928  printk("INIT 3\n");
929#endif
930
931#ifdef LINUX26
932  {
933#if defined(SH_MODLIST_LOCK)
934    spinlock_t * modlist_lock = (spinlock_t * ) SH_MODLIST_LOCK;
935#endif
936#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,30)
937    struct mutex * sh_module_mutex = &module_mutex;
938#else
939#if (SH_KERNEL_NUMERIC >= SH_KERNEL_MIN)
940    struct mutex * sh_module_mutex = (struct mutex *) SH_MODLIST_MUTEX;
941#endif
942#endif
943
944    struct module *mod;
945
946#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
947#ifdef INIT_DEBUG
948    printk("INIT 4 0\n");
949#endif
950    mutex_lock(sh_module_mutex);
951#endif
952
953#ifdef INIT_DEBUG
954    printk("INIT 4 1\n");
955#endif
956
957    mod = sh_find_module(SH_INSTALL_NAME"_hide");
958
959#ifdef INIT_DEBUG
960    printk("INIT 4 2 (%d)\n", mod == 0 ? 0 : 1);
961#endif
962
963    if (mod) {
964      /* Delete from various lists */
965#if defined(SH_MODLIST_LOCK)
966#ifdef INIT_DEBUG
967      printk("INIT 4 3a\n");
968#endif
969      spin_lock_irq(modlist_lock);
970#ifdef INIT_DEBUG
971      printk("INIT 4 3b\n");
972#endif
973#endif
974      if (removeme == 1)
975        {
976#ifdef INIT_DEBUG
977          printk("INIT 4 4a\n");
978#endif
979          list_del(&mod->list);
980#ifdef INIT_DEBUG
981          printk("INIT 4 4b\n");
982#endif
983        }
984#if defined(SH_MODLIST_LOCK)
985#ifdef INIT_DEBUG
986          printk("INIT 4 5a\n");
987#endif
988      spin_unlock_irq(modlist_lock);
989#ifdef INIT_DEBUG
990          printk("INIT 4 5b\n");
991#endif
992#endif
993    }
994
995#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
996#ifdef INIT_DEBUG
997    printk("INIT 4 6a\n");
998#endif
999    mutex_unlock(sh_module_mutex);
1000#ifdef INIT_DEBUG
1001    printk("INIT 4 6b\n");
1002#endif
1003#endif
1004  }
1005#endif
1006
1007#ifdef INIT_DEBUG
1008  printk("INIT 4 7a\n");
1009#endif
1010  unlock_kernel();
1011#ifdef INIT_DEBUG
1012  printk("INIT 4 7b\n");
1013#endif
1014  return (0);
1015}
1016
1017/* The cleanup function. Automatically called when module is removed
1018 * via the 'rmmod' command.
1019 */
1020#ifdef LINUX26
1021static void __exit samhain_hide_cleanup(void)
1022#else
1023void cleanup_module(void)
1024#endif
1025{
1026  lock_kernel();
1027
1028  /* Restore the new syscalls to the original version.
1029   */
1030  sh_sys_call_table[SYS_getdents]     = (unsigned long) old_getdents;
1031
1032#ifdef __NR_getdents64
1033  sh_sys_call_table[SYS_getdents64]   = (unsigned long) old_getdents64;
1034#endif
1035
1036  unlock_kernel();
1037}
1038
1039#ifdef LINUX26
1040module_init(samhain_hide_init);
1041module_exit(samhain_hide_cleanup);
1042#endif
1043
1044
Note: See TracBrowser for help on using the repository browser.