source: trunk/src/samhain_hide.c@ 467

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

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

File size: 22.9 KB
RevLine 
[1]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 *
[96]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):
[1]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
[443]103#ifndef __KERNEL__
[1]104#define __KERNEL__
[443]105#endif
106#ifndef MODULE
[1]107#define MODULE
108#endif
[443]109#endif
[1]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 */
[331]118/* #define INIT_DEBUG */ /* module init */
[1]119
120/*****************************************************
121 *
122 * The include files:
123 *
124 *****************************************************/
125
126
127/* The configure options (#defines) for the Kernel
128 */
[327]129#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
[91]130/* 2.6.19 (((2) << 16) + ((6) << 8) + (19)) */
131#define SH_KERNEL_MIN 132627
132
[327]133#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,33)
[331]134#include <generated/autoconf.h>
[327]135#else
136#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,19)
[90]137#include <linux/autoconf.h>
138#else
[1]139#include <linux/config.h>
[90]140#endif
[327]141#endif
[1]142
[443]143#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,0)
[1]144#ifdef CONFIG_MODVERSIONS
145#include <linux/modversions.h>
146#endif
[443]147#else
148#ifndef LINUX26
149#define LINUX26
[1]150#endif
[443]151#endif
[1]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 */
[443]188#if SH_KERNEL_NUMERIC < KERNEL_VERSION(3,0,0)
[1]189#include <linux/smp_lock.h>
[443]190#else
191static inline void lock_kernel(void) { }
192static inline void unlock_kernel(void) { }
193#endif
[1]194
[91]195#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
[90]196#include <linux/mutex.h>
197#endif
198
[1]199/* Include for fget().
200 */
201#include <linux/file.h>
[327]202#if SH_KERNEL_NUMERIC >= KERNEL_VERSION(2,6,26)
203#include <linux/fdtable.h>
204#endif
[1]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 */
[327]225#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]226int (*old_getdents)(unsigned int, struct dirent *, unsigned int);
[327]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
[1]239#ifdef __NR_getdents64
[96]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
[1]246long (*old_getdents64)(unsigned int, struct dirent64 *, unsigned int);
247#endif
[96]248#endif
[1]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
[51]271#ifdef MODULE_PARM
[1]272MODULE_PARM (removeme, "i");
[51]273#else
274module_param(removeme, int, 0444);
[1]275#endif
276
[51]277#ifdef MODULE_PARM_DESC
278MODULE_PARM_DESC(removeme, "Choose zero for not hiding.");
279#endif
[1]280
[51]281/* LINUX26 */
282#endif
283
284
[1]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
[327]326#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,25)
[1]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}
[327]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}
[1]344#endif
[327]345#endif
[1]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 */
[327]391#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]392int new_getdents (unsigned int fd, struct dirent *dirp, unsigned int count)
[327]393#else
394int new_getdents (unsigned int fd, struct linux_dirent *dirp, unsigned int count)
395#endif
[1]396{
397 int status = 0; /* Return value from original getdents */
398 struct inode * dir_inode;
[6]399 struct file * fd_file;
[1]400 int dir_is_proc = 0;
401
[327]402#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]403 struct dirent * dirp_prev;
404 struct dirent * dirp_new;
405 struct dirent * dirp_current;
[327]406#else
407 struct linux_dirent * dirp_prev;
408 struct linux_dirent * dirp_new;
409 struct linux_dirent * dirp_current;
410#endif
[1]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
[90]418 unsigned long dummy;
419
[1]420 lock_kernel();
421
422 status = (*old_getdents)(fd, dirp, count);
423
424#ifdef FILE_DEBUG
425 printk("STATUS %d\n", status);
426#endif
[6]427
[1]428 /* 0: end of directory.
429 * -1: some error
430 */
431 if (status <= 0)
432 {
433 unlock_kernel();
434 return (status);
435 }
[6]436
[1]437 /* Handle directory caching. dir_inode is the inode of the directory.
438 */
[6]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
[1]450#if defined(__LINUX_DCACHE_H)
[6]451 dir_inode = fd_file->f_dentry->d_inode;
[1]452#else
[6]453 dir_inode = fd_file->f_inode;
[1]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 */
[327]469#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]470 dirp_new = (struct dirent *) kmalloc (status, GFP_ATOMIC);
[327]471#else
472 dirp_new = (struct linux_dirent *) kmalloc (status, GFP_ATOMIC);
473#endif
[1]474
475 if (dirp_new == NULL)
476 {
477 unlock_kernel();
478 return (status);
479 }
480
481 /* Copy the dirp table to kernel space.
482 */
[90]483 dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
[1]484
485#ifdef FILE_DEBUG
[96]486 printk("COPY to kernel: %ld\n", dummy);
[1]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 */
[327]574#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]575 if (dir_table_bytes > 0)
576 dirp_current = (struct dirent *) ( (char *) dirp_current +
577 forward_bytes);
[327]578#else
579 if (dir_table_bytes > 0)
580 dirp_current = (struct linux_dirent *) ( (char *) dirp_current +
581 forward_bytes);
582#endif
[1]583 }
584
585 /* Copy our modified dirp table back to user space.
586 */
[90]587 dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
[1]588#ifdef FILE_DEBUG
[96]589 printk("COPY to user: %ld\n", dummy);
[1]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
[327]601
602
[1]603/* For 2.4 kernel
604 */
605#ifdef __NR_getdents64
[96]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
[1]616{
617 long status = 0; /* Return value from original getdents */
618 struct inode * dir_inode;
[6]619 struct file * fd_file;
[1]620 int dir_is_proc = 0;
621
[327]622#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]623 struct dirent64 * dirp_prev;
624 struct dirent64 * dirp_new;
625 struct dirent64 * dirp_current;
[327]626#else
627 struct linux_dirent64 * dirp_prev;
628 struct linux_dirent64 * dirp_new;
629 struct linux_dirent64 * dirp_current;
630#endif
[1]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
[90]638 unsigned long dummy;
639
[96]640#ifdef FILE_DEBUG
641 printk("FD64 %d\n", fd);
642#endif
643
[1]644 lock_kernel();
645
[96]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
[1]654 status = (*old_getdents64)(fd, dirp, count);
[237]655 /* status = my_real_getdents64(fd, dirp, count); */
[96]656#else
657 status = (*old_getdents64)(fd, dirp, count);
658#endif
[1]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 */
[6]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
[1]686#if defined(__LINUX_DCACHE_H)
[96]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
[6]692 dir_inode = fd_file->f_dentry->d_inode;
[96]693#endif
694
[1]695#else
[6]696 dir_inode = fd_file->f_inode;
[1]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 */
[90]741 dummy = (unsigned long) copy_from_user(dirp_new, dirp, status);
[1]742
743#ifdef FILE_DEBUG
[96]744 printk("COPY64 to kernel: %ld\n", dummy);
[1]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 */
[327]838#if SH_KERNEL_NUMERIC < KERNEL_VERSION(2,6,27)
[1]839 if (dir_table_bytes > 0)
840 dirp_current = (struct dirent64 *) ( (char *) dirp_current +
841 forward_bytes);
[327]842#else
843 if (dir_table_bytes > 0)
844 dirp_current = (struct linux_dirent64 *) ( (char *) dirp_current +
845 forward_bytes);
846#endif
[1]847 }
848
849 /* Copy our modified dirp table back to user space.
850 */
[96]851#ifdef FILE_DEBUG
852 printk("STATUS64 AT END %ld\n", status);
853#endif
[90]854 dummy = (unsigned long) copy_to_user(dirp, dirp_new, status);
[96]855#ifdef FILE_DEBUG
856 printk("COPY64 to user: %ld\n", dummy);
857#endif
858
[1]859 kfree (dirp_new);
860 unlock_kernel();
861 return (status);
862}
863#endif
864
865#ifdef LINUX26
[327]866static struct module *sh_find_module(const char *name)
[1]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
[331]889#ifdef INIT_DEBUG
890 printk("INIT 0\n");
891#endif
892
[1]893 lock_kernel();
894
[331]895#ifdef INIT_DEBUG
896 printk("INIT 1\n");
897#endif
898
[1]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
[331]906#ifdef INIT_DEBUG
907 printk("INIT 1a (%d)\n", SYS_getdents);
908#endif
909
[1]910 /* Replace the 'sys_getdents' syscall with the new version.
911 */
912 old_getdents = (void*) sh_sys_call_table[SYS_getdents];
[331]913#ifdef INIT_DEBUG
914 printk("INIT 1b\n");
915#endif
[1]916 sh_sys_call_table[SYS_getdents] = (unsigned long) new_getdents;
917
[331]918#ifdef INIT_DEBUG
919 printk("INIT 2\n");
920#endif
921
[1]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
[331]927#ifdef INIT_DEBUG
928 printk("INIT 3\n");
929#endif
930
[1]931#ifdef LINUX26
932 {
[90]933#if defined(SH_MODLIST_LOCK)
[1]934 spinlock_t * modlist_lock = (spinlock_t * ) SH_MODLIST_LOCK;
[90]935#endif
[327]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;
[90]941#endif
[327]942#endif
[90]943
944 struct module *mod;
945
[91]946#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
[331]947#ifdef INIT_DEBUG
948 printk("INIT 4 0\n");
949#endif
[327]950 mutex_lock(sh_module_mutex);
[90]951#endif
952
[331]953#ifdef INIT_DEBUG
954 printk("INIT 4 1\n");
955#endif
956
[327]957 mod = sh_find_module(SH_INSTALL_NAME"_hide");
[331]958
959#ifdef INIT_DEBUG
960 printk("INIT 4 2 (%d)\n", mod == 0 ? 0 : 1);
961#endif
962
[1]963 if (mod) {
964 /* Delete from various lists */
[90]965#if defined(SH_MODLIST_LOCK)
[331]966#ifdef INIT_DEBUG
967 printk("INIT 4 3a\n");
968#endif
[1]969 spin_lock_irq(modlist_lock);
[331]970#ifdef INIT_DEBUG
971 printk("INIT 4 3b\n");
[90]972#endif
[331]973#endif
[1]974 if (removeme == 1)
975 {
[331]976#ifdef INIT_DEBUG
977 printk("INIT 4 4a\n");
978#endif
[1]979 list_del(&mod->list);
[331]980#ifdef INIT_DEBUG
981 printk("INIT 4 4b\n");
982#endif
[1]983 }
[90]984#if defined(SH_MODLIST_LOCK)
[331]985#ifdef INIT_DEBUG
986 printk("INIT 4 5a\n");
987#endif
[1]988 spin_unlock_irq(modlist_lock);
[331]989#ifdef INIT_DEBUG
990 printk("INIT 4 5b\n");
[90]991#endif
[331]992#endif
[1]993 }
[331]994
[91]995#if SH_KERNEL_NUMERIC >= SH_KERNEL_MIN
[331]996#ifdef INIT_DEBUG
997 printk("INIT 4 6a\n");
[90]998#endif
[331]999 mutex_unlock(sh_module_mutex);
1000#ifdef INIT_DEBUG
1001 printk("INIT 4 6b\n");
1002#endif
1003#endif
[1]1004 }
1005#endif
1006
[331]1007#ifdef INIT_DEBUG
1008 printk("INIT 4 7a\n");
1009#endif
[1]1010 unlock_kernel();
[331]1011#ifdef INIT_DEBUG
1012 printk("INIT 4 7b\n");
1013#endif
[1]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;
[327]1031
[1]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.