Chinaunix首页 | 论坛 | 博客
  • 博客访问: 474046
  • 博文数量: 61
  • 博客积分: 2438
  • 博客等级: 大尉
  • 技术积分: 871
  • 用 户 组: 普通用户
  • 注册时间: 2010-07-28 08:04
文章分类
文章存档

2013年(1)

2012年(8)

2011年(15)

2010年(37)

分类: LINUX

2012-07-19 19:29:06

系统调用收集的重要性:
系统调用是用户程序与系统打交道的唯有入口,因此对系统调用的安全调用直接关系到系统的安全,比如一个用户恶意地不断调用fork()将导致系统负载增加,如果能收集到是谁调用了一些有危险的系统调用,以及调用系统调用的时间和其他信息,将有助于系统管理员进行时候追踪,从而提高系统的安全性。

该收集程序的总框架:

1、记录系统调用日志,将其写入内核缓冲区
2、建立新的系统调用,将其内核缓冲区中的日志信息返回到用户空间
3、循环利用系统调用,实时地返回系统调用的日志

具体的实现过程:(我当前的测试内核为2.6.36,其中红色为添加和修改的)
1、下载内核源代码,解压。
2、在arch/x86/include/asm/unistd_32.h和/usr/include/asm/unistd_32.h中添加系统调用号:

arch/x86/include/asm/unistd_32.h

点击(此处)折叠或打开

  1. ......
  2. 347 #define __NR_fanotify_mark 339
  3. 348 #define __NR_prlimit64 340
  4. 349 #define __NR_syscall_audit 341
  5. 350 #define __NR_myaudit 342
  6. 351
  7. 352 #ifdef __KERNEL__
  8. 353
  9. 354 #define NR_syscalls 343
  10. 355
  11. ......
/usr/include/asm/unistd_32.h

点击(此处)折叠或打开

  1. ......
  2. 345 #define __NR_recvmmsg 337
  3. 346
  4. 347 #define __NR_syscall_audit 341
  5. 348 #define __NR_myaudit 342
  6. 349
  7. 350 #endif /* _ASM_X86_UNISTD_32_H */
3、在arch/x86/kernel/syscall_table_32.S添加服务历程入口:

点击(此处)折叠或打开

  1. 342 .long sys_prlimit64 /* 340 */
  2. 343 .long sys_syscall_audit /*341*/
  3. 344 .long sys_myaudit /*342*/
4、修改系统调用入口处理,在arch/x86/kernel/entry_32.S添加:
第一种处理方式:int 0x80

点击(此处)折叠或打开

  1. 562 syscall_call:
  2. 563 call *sys_call_table(,%eax,4)
  3. 564 movl %eax,PT_EAX(%esp) # store the return value
  4. 565 /*
  5. 566 * new add
  6. 567 * 20 -- getpid()
  7. 568 * 116 -- sysinfo()
  8. 569 */
  9. 570 cmpl $20, 0x2C(%esp)
  10. 571 je myauditsys
  11. 572 cmpl $116, 0x2C(%esp)
  12. 573 je myauditsys
  13. 574
  14. 575 syscall_exit:
  15. 576 LOCKDEP_SYS_EXIT
  16. 577 DISABLE_INTERRUPTS(CLBR_ANY) # make sure we don't miss an interrupt
  17. 578 # setting need_resched or sigpending
  18. 579 # between sampling and the iret
  19. 580 TRACE_IRQS_OFF
  20. 581 movl TI_flags(%ebp), %ecx
  21. 582 testl $_TIF_ALLWORK_MASK, %ecx # current->work
  22. 583 jne syscall_exit_work
  23. 584
  24. 585 jmp restore_all
  25. 586 myauditsys:
  26. 587 pushl %eax
  27. 588 pushl 0x30(%esp)
  28. 589 call sys_syscall_audit
  29. 590 popl %eax
  30. 591 popl %eax
  31. 592 jmp syscall_exi

第二种处理方式:sysenter (继续在文件entry_32.S)

点击(此处)折叠或打开

  1. 455 sysenter_do_call:
  2. 456 cmpl $(nr_syscalls), %eax
  3. 457 jae syscall_badsys
  4. 458 call *sys_call_table(,%eax,4)
  5. 459 movl %eax,PT_EAX(%esp)
  6. 460
  7. 461 /****************************************************/
  8. 462 cmpl $20, 0x2C(%esp)
  9. 463 je enter_audit
  10. 464 cmpl $116, 0x2C(%esp)
  11. 465 je enter_audit
  12. 466 audit_exit:
  13. 467 /****************************************************/
  14. 468
  15. 469 LOCKDEP_SYS_EXIT
  16. 470 DISABLE_INTERRUPTS(CLBR_ANY)
  17. 471 TRACE_IRQS_OFF
  18. 472 movl TI_flags(%ebp), %ecx
  19. 473 testl $_TIF_ALLWORK_MASK, %ecx
  20. 474 jne sy***it_audit
  21. 475
  22. 476 /****************************************************/
  23. 477 jmp sysenter_exit
  24. 478 enter_audit:
  25. 479 pushl %eax
  26. 480 pushl 0x30(%esp)
  27. 481 call sys_syscall_audit
  28. 482 popl %eax
  29. 483 popl %eax
  30. 484 jmp audit_exit
  31. 485 /****************************************************/
5、在arch/x86/kernel/下添加系统调用服务历程程序,这里采用的是直接添加myaudit.c文件,然后修改Makefile文件的方式:

点击(此处)折叠或打开

  1. /**
  2.  * myaudit.c
  3.  */

  4. #include <linux/proc_fs.h>
  5. #include <linux/init.h>
  6. #include <linux/types.h>
  7. #include <linux/sched.h>
  8. #include <asm/current.h>

  9. void (*my_audit)(int, int) = 0;

  10. asmlinkage void sys_syscall_audit(int syscall_number, int return_value)
  11. {
  12.     if (my_audit) {
  13.         return (*my_audit)(syscall_number, return_value);
  14.         printk("IN KERNEL: %s(%d), syscall: %d, return: %d\n", current->comm, (int)current->pid, syscall_number, return_value);
  15.         //printk("IN KERNEL: %s\n", current);
  16.     } else {
  17.         printk("my_audit is empty!\n");
  18.     }
  19.     return ;
  20. }

  21. int (*my_sysaudit)(u8, u8*, u16, u8) = 0;

  22. asmlinkage int sys_myaudit(u8 type, u8 *us_buf, u16 us_buf_size, u8 reset)
  23. {
  24.     if (my_sysaudit) {
  25.         return (*my_sysaudit)(type, us_buf, us_buf_size, reset);
  26.         printk("IN KERNEL: my system call sys_myaudit() working...\n");
  27.     } else {
  28.         printk("my_sysaudit is empty!\n");
  29.     }
  30.     return 0;
  31. }
修改Makefile文件:只需在其中一条后面添加myaudit.o就OK了

点击(此处)折叠或打开

  1.  ......
  2.  34 obj-y := process_$(BITS).o signal.o entry_$(BITS).o myaudit.o
  3.  35 obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
6、导出接口函数my_audit和my_sysaudit,在arch/x86/kernel/i386_ksyms_32.c最后添加:

点击(此处)折叠或打开

  1. EXPORT_SYMBOL(my_audit);
  2. EXPORT_SYMBOL(my_sysaudit);
在include/linux/kernel.h最后添加申明:

点击(此处)折叠或打开

  1. ......
  2. 783 #endif
  3. 784
  4. 785 extern void (*my_audit)(int, int);
  5. 786 extern int (*my_sysaudit)(unsigned char, unsigned char *, unsigned short, unsigned char);
  6. 787
  7. 788 #endif

到此,内核态需要修改文件的都修改完毕,下来就需要重新编译、安装内核了。
可参考: 开始的介绍。
需要注意的是有时在安装时没有生成initrd.img文件的话,就需要手动的生成img文件,并更新grub。
生成img文件:在源码解压后的目录下用命令:mkinitramfs -o initrd.img-2.6.36
更新grub:update-grub
有关用户态下的程序将在二中介绍。
阅读(1611) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~