在一当中主要是对内核修改的部分做了介绍,我们接着介绍:
在myaudit.c文件中有两个函数指针,下来介绍实现。
- #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");
这个是总控程序,用来从内核收集信息,并写到用户BUF中。
Makefile:
- obj-m := mod.o
- Kernel_path=/home/linux/kernel/linux-2.6.36 #这个是我重新编译内核后的路径
- all:
- make -C $(Kernel_path) M=$(PWD) modules
- clean:
- make -C $(Kernel_path) M=$(PWD) clean
然后插入模块就ok了。
用户态监控/显示程序:
- #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(__NR_myaudit, 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);
- }
- }
- return 0;
- }
将收集到的信息显示出来。
触发程序:
- #include <stdio.h>
- #include <stdlib.h>
- #include
- #include <sys/sysinfo.h>
- int main()
- {
- int ret, i;
- pid_t pid;
- struct sysinfo info;
- for (i = 100; i >= 0; i--) {
- ret = sysinfo(&info);
- pid = getpid();
- }
- exit(1);
- }
该程序的运行过程:
1、先将模块程序插入内核,属于内核态下的监控程序。
2、运行用户态下的监控程序,该程序会向系统发出系统调用,如果内核态下的满足条件,则这边会显示。
3、运行触发程序。
小结:该程序(系统调用日志收集系统)主要是从内核态下监控系统,防止一些用户非法的申请资源,从而达到对系统安全维护的一种措施。该程序还有许多要扩充的地方,例如,用户态下的监控程序可以做成一个守护进程,可以对非法用户采取一定的措施。
阅读(2714) | 评论(0) | 转发(0) |