系统调用日志收集系统
2,系统调用日志收集系统总体框架图。
主要是在系统调用的两个入口进行监控,发现调用了如下四个系统调用(getpid,sysinfo,fork,execv)
将会执行sys_syscall_audit函数。
- syscall_call:
- call *sys_call_table(,%eax,4)
- movl %eax,PT_EAX(%esp) # store the return value
- #如下位添加代码
- #----------------------------------------------------
- cmpl $20,0x2c(%esp) #getpid()
- je myauditsys
- cmpl $116,0x2c(%esp) #sysinfo()
- je myauditsys
- cmpl $2,0x2c(%esp) #fork
- je myauditsys
- cmpl $11,0x2c(%esp) #execv
- je myauditsys
- #-----------------------------------------------
- syscall_exit:
- LOCKDEP_SYS_EXIT
- ...
- jne syscall_exit_work
- #如下位添加代码
- #------------------------------------------------
- jmp restore_all
- myauditsys:
- pushl %eax
- pushl 0x30(%esp)
- call sys_syscall_audit
- popl %eax
- popl %eax
- jmp syscall_exit
- #------------------------------------------------
- restore_all:
- TRACE_IRQS_IRET
- sysenter_do_call:
- ...
- movl %eax,PT_EAX(%esp)
- #如下为添加代码
- /*--------------------------------------------------------*/
- cmpl $20,0x2c(%esp) #getpid()
- je enter_audit
- cmpl $116,0x2c(%esp) #sysinfo()
- je enter_audit
- cmpl $2,0x2c(%esp) #fork
- je enter_audit
- cmpl $11,0x2c(%esp) #execv
- je enter_audit
- come_back:
- /*--------------------------------------------------------*/
- sysenter_exit:
- ....
- ENABLE_INTERRUPTS_SY***IT
- /*--------------------------------------------------------*/
- jmp sysenter_audit
- enter_audit:
- pushl %eax
- pushl 0x30(%esp)
- call sys_syscall_audit
- popl %eax
- popl %eax
- jmp come_back
- /*--------------------------------------------------------*/
--------------------------------------------------------------------------------------------
3.4,添加系统调用的服务例程。
在arch/x86/kernel/下面添加文件myaudit.c
该文件中实现了系统调用的服务例程,但这儿实现的服务例程都只有一个接口,
真正的实现将在模块中实现,这样是为了方便调试,避免了多次编译内核。这儿主要
是通过两个全局变量(my_audit和my_sysaudit)与内核模块之间建立了联系。
- /**
- * myaudit.c
- */
- #include <linux/proc_fs.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <asm/current.h>
- void (*my_audit)(int, int) = 0;
- asmlinkage void sys_syscall_audit(int syscall_number, int return_value)
- {
- if (my_audit) {
- return (*my_audit)(syscall_number, return_value);
- printk("IN KERNEL: %s(%d), syscall: %d, return: %d\n", current->comm, (int)current->pid, syscall_number, return_value);
- //printk("IN KERNEL: %s\n", current);
- } else {
- printk("my_audit is empty!\n");
- }
- return ;
- }
- int (*my_sysaudit)(u8, u8*, u16, u8) = 0;
- asmlinkage int sys_myaudit(u8 type, u8 *us_buf, u16 us_buf_size, u8 reset)
- {
- if (my_sysaudit) {
- return (*my_sysaudit)(type, us_buf, us_buf_size, reset);
- printk("IN KERNEL: my system call sys_myaudit() working...\n");
- } else {
- printk("my_sysaudit is empty!\n");
- }
- return 0;
- }
----------------------------------------------------------------------------------------------
3.5,修改makefile。位置:arch/x86/kernel/Makefile
- obj-y := process_$(BITS).o signal.o entry_$(BITS).o myaudit.o
----------------------------------------------------------------------------------------------
3.6,导出全局变量。(不导出的话,内核模块将对其不可见)
修改arch/x86/kernel/i386_ksyms_32.c文件,在其末尾追加:
- EXPORT_SYMBOL(my_audit);
- EXPORT_SYMBOL(my_sysaudit);
----------------------------------------------------------------------------------------------
3.7,声明全局变量。
修改:include/linux/module.h 添加:
- extern void (*my_audit)(int,int);
- extern int (*my_sysaudit)(u8,u8*,u16,u8);
接系统调用日志收集系统 (1)
---------------------------------------------------------------
3.8重新编译内核。
如何编译内核就不再说了。
----------------------------------------------------------------
3.9插入模块。
- #include <linux/module.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/types.h>
- #include <asm/current.h>
- #include <linux/sched.h>
- #include <asm/uaccess.h>
- #define COMM_SIZE 16
- struct syscall_buf {
- u32 serial;
- u32 ts_sec;
- u32 syscall;
- u32 status;
- pid_t pid;
- uid_t uid;
- u8 comm[COMM_SIZE];
- };
- //初始化一个队列buffer_wait
- DECLARE_WAIT_QUEUE_HEAD(buffer_wait);
- #define AUDIT_BUF_SIZE 100
- //长度为100的缓冲区。
- static struct syscall_buf audit_buf[AUDIT_BUF_SIZE];
- static int current_pos = 0;//缓冲区中的位置.
- static u32 serial = 0;//序列号
- void write_buf_audit(int syscall,int return_value)
- {
- struct syscall_buf *ppb_tmp;
- printk("write_buf_audit is execing!\n");
- if (current_pos < AUDIT_BUF_SIZE) {
- ppb_tmp = &audit_buf[current_pos];
- ppb_tmp->serial = serial++;
- ppb_tmp->ts_sec = 1;
- ppb_tmp->syscall = syscall;
- ppb_tmp->status = return_value;
- ppb_tmp->pid = current->pid;
- ppb_tmp->uid = current->tgid;
- memcpy(ppb_tmp->comm,current->comm,COMM_SIZE);
- if (++current_pos == AUDIT_BUF_SIZE *1/10) {
- printk("in syscall_audit,it near full!\n");
- wake_up_interruptible(&buffer_wait);
- }
- }
- return ;
- }
- int read_buf_audit(u8 type,u8 *us_buf,u16 us_buf_size,u8 reset)
- {
- int ret = 0;
- printk("read_buf_audit is execving!\n");
- if (!type) {
- if (clear_user((void *)us_buf, (unsigned long)us_buf_size)) {
- printk("error:clear_user!\n");
- return 0;
- }
- ret= wait_event_interruptible(buffer_wait,current_pos >= AUDIT_BUF_SIZE*1/10);
- if (copy_to_user((void *)us_buf,audit_buf,(current_pos)*sizeof(struct syscall_buf))) {
- printk("error:copy error!\n");
- return 0;
- }
- ret = current_pos;
- current_pos = 0;
- }
- return ret;
- }
- static int __init audit_init(void)
- {
- my_audit = write_buf_audit;
- my_sysaudit = read_buf_audit;
- printk("starting syscall audit!\n");
- return 0;
- }
- static void __exit audit_exit(void)
- {
- my_audit = NULL;
- my_sysaudit = NULL;
- printk("exiting syscall audit!\n");
- return ;
- }
- module_init(audit_init);
- module_exit(audit_exit);
- MODULE_LICENSE("GPL");
------------------------------------------------------------------------------------------------------
3.10,启动用户测试程序。
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <signal.h>
- #include <unistd.h>
- #include <sys/syscall.h>
- #include <sys/types.h>
- typedef unsigned char u8;
- typedef unsigned int u32;
- #define COMM_SIZE 16
- struct syscall_buf {
- u32 serial;
- u32 ts_sec;
- u32 syscall;
- u32 status;
- pid_t pid;
- uid_t uid;
- u8 comm[COMM_SIZE];
- };
- #define AUDIT_BUF_SIZE 100*sizeof(struct syscall_buf)
- int main(int argc, char *argv[])
- {
- u8 col_buf[AUDIT_BUF_SIZE];
- unsigned char reset = 1;
- int num = 0;
- struct syscall_buf *p = NULL;
- u8 j = 0;
- int i;
- while (1) {
- num = syscall(346, 0, col_buf, AUDIT_BUF_SIZE, reset);
- printf("num is: %d\n", num);
- p = (struct syscall_buf *)col_buf;
- for (i = 0; i < num; i++) {
- printf("serial: %d ", p[i].serial);
- printf("syscall: %d ", p[i].syscall);
- printf("ts_sec: %d ", ((struct syscall_buf *)col_buf)[i].ts_sec);
- printf("status: %d ", p[i].status);
- printf("pid: %d ", ((struct syscall_buf *)col_buf)[i].pid);
- printf("uid: %d ", ((struct syscall_buf *)col_buf)[i].uid);
- printf("comm: %s\n", ((struct syscall_buf *)col_buf)[i].comm);
- }
- putchar('\n');
- }
- return 0;
- }
--------------------------------------------------------------------------------------------------------
3.11,其中用户触发程序。(向内核不断地申请系统调用)
- #include <stdio.h>
- #include <unistd.h>
- #include <sys/sysinfo.h>
- int main(void)
- {
- struct sysinfo info;
- unsigned long value = 0;
- int i = 0;
- while (1) {
- sysinfo(&info);
- printf("sysinfo is execving!\n");
- value = (unsigned long)getpid();
- printf("pid = %lu\n",value);
- sleep(1);
- }
- return 0;
- }
----------------------------------------------------------------------------------------------------------------
感想:
经过几天的时间调试这个程序,最终还是调试通过了,收获还是蛮大的,这个程序中
既要内核编程,还有编写内核模块,还要编写用户态程序。内核态和用户态协调合作。当然
在其中也出现了不少问题,开始我们就没有考虑到sysenter,结果导致使用库函数,对内核
就没有触发,只能使用int 0x80,直接在用户态使用汇编或嵌入汇编才能对其触发。后来把
sysenter这条路“堵死”就好了。
------------------------------------------------------------------------------------------------------------------
系统调用日志收集系统相关推荐
- execve系统调用_张凯捷—系统调用分析(3) (基于最新Linux5.0版本系统调用日志收集系统)...
在上一篇文章<系统调用分析(2)>中介绍和分析了32位和64位的快速系统调用指令--sysenter/sysexit和syscall/sysret,以及内核对快速系统调用部分的相关代码,并 ...
- 基于Flume的美团日志收集系统(二)改进和优化
在<基于Flume的美团日志收集系统(一)架构和设计>中,我们详述了基于Flume的美团日志收集系统的架构设计,以及为什么做这样的设计.在本节中,我们将会讲述在实际部署和使用过程中遇到的问 ...
- 借鉴开源框架自研日志收集系统
踏浪无痕 岂安科技高级架构师 十余年数据研发经验,擅长数据处理领域工作,如爬虫.搜索引擎.大数据应用高并发等.担任过架构师,研发经理等岗位.曾主导开发过大型爬虫,搜索引擎及大数据广告DMP系统目前负责 ...
- python分布式日志收集系统_Go实现海量日志收集系统(一)
项目背景 每个系统都有日志,当系统出现问题时,需要通过日志解决问题 当系统机器比较少时,登陆到服务器上查看即可满足 当系统机器规模巨大,登陆到机器上查看几乎不现实 当然即使是机器规模不大,一个系统通常 ...
- 探秘Hadoop生态12:分布式日志收集系统Flume
这位大侠,这是我的公众号:程序员江湖. 分享程序员面试与技术的那些事. 干货满满,关注就送. 在具体介绍本文内容之前,先给大家看一下Hadoop业务的整体开发流程: 从Hadoop的业务开发流程 ...
- Flume日志收集系统架构详解--转
2017-09-06朱洁大数据和云计算技术 任何一个生产系统在运行过程中都会产生大量的日志,日志往往隐藏了很多有价值的信息.在没有分析方法之前,这些日志存储一段时间后就会被清理.随着技术的发展和分析能 ...
- fluentd mysql_使用Fluentd + MongoDB构建实时日志收集系统
日志处理场景 日志量大 日志分散不易进行统一分析 难以添加有效监控 系统实现 Fluentd(td-agent) MongoDB Python Script(PyMongo module) Zabbi ...
- 你居然还去服务器上捞日志,搭个日志收集系统难道不香么!
摘要 ELK日志收集系统进阶使用,本文主要讲解如何打造一个线上环境真实可用的日志收集系统.有了它,你就可以和去服务器上捞日志说再见了! ELK环境安装 ELK是指Elasticsearch.Kiban ...
- java 如何去掉http debug日志_你居然还去服务器上捞日志,搭个日志收集系统难道不香吗?...
作者:MacroZheng 链接:https://juejin.im/post/5eef217d51882565d74fb4eb 来源:掘金 SpringBoot实战电商项目mall(35k+star ...
最新文章
- c java 开发android_java代码与纯C代码混编完成android应用的开发
- linux负载很高是什么原因导致的?
- Jerry的ABAP, Java和JavaScript乱炖
- python实现文件转数组
- Source Insight 4.0 常用设置
- eclipse中安装TestNg
- Ubuntu视频教程
- 自相关函数互相关函数
- 入门级概述光学相干层析(OCT)原理
- NFC framework introduce(一)
- Python将Qt的ui文件转成py代码文件
- vue中细枝末节的知识点总结
- “金三银四”春招指南!java语言程序设计第二版答案朱庆生
- 毛绒玩具需做哪些测试项目?出口欧盟CE认证
- 实验二 词频统计软件项目报告
- 目前互联网最详细的5G注册流程
- java实现来电弹屏_屏信小编告诉你呼叫中心的来电弹屏有哪些功能
- 安装配有NVIDIA GRID K2服务器系统不能正常安装和其他的GPU卡如K20x不能正常安装原厂驱动
- 由于文件不可访问,或者内存或磁盘空间不足,所以无法打开数据库 ‘msdb‘。无法打开数据库msdb 恢复操作已将该数据库标记为SUSPECT
- 用Shell脚本画矩形;直角、等腰三角形;梯形;菱形