execve系统调用_张凯捷—系统调用分析(3) (基于最新Linux5.0版本系统调用日志收集系统)...

6cc1510da245bca8e5845aac02c66dac.png

    在上一篇文章《系统调用分析(2)》中介绍和分析了32位和64位的快速系统调用指令——sysenter/sysexit和syscall/sysret,以及内核对快速系统调用部分的相关代码,并追踪了一个用户态下的系统调用程序运行过程。

    本篇中将基于最新的Linux-5.0内核,添加一个系统调用,完成一个“系统调用日志收集系统”; 并对这三篇文章进行一个总结。

 6cc1510da245bca8e5845aac02c66dac.png

加前两篇文章在这里:

https://mp.weixin.qq.com/s/3Dvd2dy0l6OYFVGzfEvOcg

https://mp.weixin.qq.com/s/7uXVXXqzN8wMqgxqrN_5og

加一个系统调用

//

  单纯添加一个系统调用会显得有些单调,出于既是作业又是学习角度,将系统调用、工作队列、修改内核、内核编译和内核模块编写插入等结合起来,通过完成一个系统调用日志收集系统。

1

系统调用日志收集系统的目的

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

2

系统调用日志收集系统概述

184c2596ec56e4595c638d1dae3f7f2d.png

图3-1 系统调用日志收集系统示意图

  根据示意图,系统调用日志收集系统所做工作为:当用户进程执行系统调用,运行到内核函数do_syscall_64时,进行判断是否为我们需要记录的系统调用,如果是我们需要记录的系统调用则通过my_audit这一函数将记录内容写入内核中的buffer里;同时编写用户态测试程序调用335号系统调用(myaudit),这一系统调用调用my_sysaudit这一函数将内核buffer中数据copy到用户buffer中并显示日志内容;其中我们调用的my_audit和my_sysaudit都是钩子函数,具体实现使用内核模块完成并插入,方便调试。

3

系统调用日志收集系统实现

 (1)增加系统调用表的表项

  打开arch/x86/entry/syscalls/syscall_64.tbl,添加一个系统调用表项:

335 common  myaudit         __x64_sys_myaudit

  (2)添加系统调用函数

  arch/x86/kernel/目录下添加myaudit.c文件完成系统调用函数:

#include

#include

#include

#include

#include

#include

#include

#include

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

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

SYSCALL_DEFINE4(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_sysadit is not exist\n");

   return 1;

}

EXPORT_SYMBOL(my_audit);

EXPORT_SYMBOL(my_sysaudit);

   这里可以看到实际上定义两个钩子函数,在我们系统调用里去调用这两个钩子函数,这样可以以模块的方式添加这两个函数的具体内容,方便调试。

  (3)修改Makefile

  修改arch/x86/kernel/Makefile,将myaduit.c文件加入内核编译:

obj-y           += myaudit.o

  (4)增加函数声明

  在include/linux/syscalls.h最后的endif前添加函数声明:

          asmlink long sys_myaudit(u8, u8 *, u16, u8);

extern void (*my_audit)(int, int);

  (5)拦截相关系统调用

正如前面对syscall执行的分析,修改do_syscall_64()函数(在/arch/x86/entry/common.c中),对系统调用号nr进行判断,如果是我们日志收集系统需要记录的系统调用,就调用我们的记录函数进行记录:

__visible void do_syscall_64(unsigned long nr, struct pt_regs *regs)

{

   ...    

    nr = syscall_trace_enter(regs);

   nr &= __SYSCALL_MASK;

   if (likely(nr < NR_syscalls)) {

       nr = array_index_nospec(nr, NR_syscalls);

       regs->ax = sys_call_table[nr](regs);

       if (nr == 57 || nr == 2 || nr == 3 || nr == 59 || nr == 39 || nr == 56) {            

            if (my_audit)

               (*my_audit)(nr, regs->ax);

           else

               printk("my_audit is not exist.\n");        }    }    syscall_return_slowpath(regs); }

   可以看到要记录的系统调用有:2:open;3:close;39:getpid;56:clone;57:fork;59:execve。

  (6)重新编译内核

#提前把原来内核版本的.config拷贝到5.0内核源码根目录下

cd linux-5.0的路径

sudo cp /usr/src/内核版本/.config ./  

#进入menuconfig后按照 load->OK->save->OK->exit->exit执行

sudo make menuconfig  

sudo make olddefconfig

#编译内核

sudo make bzImage -j2

sudo make modules

#安装内核修改引导

sudo make modules_install sudo make install

sudo update-grub2

#重启

sudo reboot

 (7)添加实现钩子函数的内核模块

  my_audit.c:#include

#include

#include

#include

#include

#define COMM_SIZE 16

#define AUDIT_BUF_SIZE 100

MODULE_LICENSE("GPL v2");

struct syscall_buf {

u32 serial; u64 ts_sec; u64 ts_micro; u32 syscall;

u32 status;

        pid_t pid;

        uid_t uid;

u8 comm[COMM_SIZE]; };

DECLARE_WAIT_QUEUE_HEAD(buffer_wait);

static struct syscall_buf audit_buf[AUDIT_BUF_SIZE];

static int current_pos = 0;

static u32 serial = 0;

void syscall_audit(int syscall, int return_status)

{

        struct syscall_buf *ppb_temp;

struct timespec64 nowtime;

ktime_get_real_ts64(&nowtime);

        if (current_pos < AUDIT_BUF_SIZE) {

ppb_temp = &audit_buf[current_pos]; ppb_temp->serial = serial++; ppb_temp->ts_sec = nowtime.tv_sec; ppb_temp->ts_micro = nowtime.tv_nsec; ppb_temp->syscall = syscall; ppb_temp->status = return_status; ppb_temp->pid = current->pid;

ppb_temp->uid = current->tgid;

memcpy(ppb_temp->comm, current->comm, COMM_SIZE);

if (++current_pos == AUDIT_BUF_SIZE * 8 / 10)

{ printk("IN MODULE_audit: yes, it near full\n"); wake_up_interruptible(&buffer_wait); } }

}

int sys_audit(u8 type, u8 *us_buf, u16 us_buf_size, u8 reset)

{

    int ret = 0;

if (!type) {

    if (clear_user(us_buf, us_buf_size)) {

printk("Error:clear_user\n");

return 0;

            }

    printk("IN MODULE_systemcall:starting...\n");     ret = wait_event_interruptible(buffer_wait, current_pos >= AUDIT_BUF_SIZE * 8 / 10);

    printk("IN MODULE_systemcall:over, current_pos is %d\n", current_pos);

    if(copy_to_user(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_sysaudit = sys_audit;     my_audit =  syscall_audit;

    printk("Starting System Call Auditing\n");

    return 0;

}

module_init(audit_init);

static void __exit audit_exit(void)

{

my_audit = NULL; my_sysaudit = NULL;

printk("Exiting System Call Auditing\n");

return ;

} module_exit(audit_exit);

   (8)实现用户空间收集日志进程程序

    test_syscall.c:

#include

#include

#include

#include

#include

#include

#include

#include

#define COMM_SIZE 16

typedef unsigned char u8;

typedef unsigned int u32;

typedef unsigned long long u64;

struct syscall_buf {

   u32 serial;    u64 ts_sec;    u64 ts_micro;    u32 syscall;

   u32 status;    

    pid_t pid;    

    uid_t uid;

   u8 comm[COMM_SIZE];

};

#define AUDIT_BUF_SIZE (20 * sizeof(struct syscall_buf))

int main(int argc, char *argv[]){

   u8 col_buf[AUDIT_BUF_SIZE];

   unsigned char reset = 1;

   int num = 0;

   int i, j;

   struct syscall_buf *p;

   while(1) {        num = syscall(335, 0, col_buf, AUDIT_BUF_SIZE, reset);        printf("num: %d\n", num);

       p = (struct syscall_buf *)col_buf;

       for(i = 0; i < num; i++) {

           printf("num [%d], serial: %d,\t syscall: %d,\t pid: %d,\t comm: %s,\t ts_sec: %ld\n", i, p[i].serial, p[i].syscall, p[i].pid, p[i].comm, ctime(&p[i].ts_sec));

       }    }    return 1; }

    (9)测试系统

  运行用户空间收集日志进程程序,随着OS系统的运行,不断从内核里记录相关系统调用日志的buffer中取出打印在屏幕上:

da069f57c4325898e17379ca544a3a11.png

//

图3-2 系统测试截图

总结

d29d45d74be57832897d0dc2d664d3fe.png

图 4-1 系统调用总结图

《系统调用分析》一共三篇文章,先从最早的系统调用方法——(int 80)开始,基于Linux-2.6.39内核开始分析,对用软中断系统调用的初始化、处理流程和系统调用表进行了学习探究。随后,基于Linux-4.20内核分析学习了从机制上对系统调用进行优化的方法——vsyscalls和vDSO。之后对32位下的快速系统调用指令——sysenter/sysexit进行指令学习和对相关Linux源码分析。然后在Linux-4.20内核下编写调用系统调用的程序,使用gdb进行调试跟踪并分析出最后使用syscall指令执行系统调用,再对64位下的快速系统调用指令syscall/sysret进行指令学习和对相关Linux源码分析。最后在Linux-5.0内核上完成一个系统调用日志收集系统,其中包含着添加系统调用,编译内核,修改内核代码,添加内核模块,编写用户态程序测试。

参考文献

[1] 英特尔®64和IA-32架构软件开发人员手册合并卷. https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf

[2] The Definitive Guide to Linux System Calls. https://blog.packagecloud.io/eng/2016/04/05/the-definitive-guide-to-linux-system-calls/#32-bit-fast-system-calls

[3] Linux 2.6 对新型 CPU 快速系统调用的支持. https://www.ibm.com/developerworks/cn/linux/kernel/l-k26ncpu/index.html

[4] vsyscalls and vDSO. https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-3.html

[5] Linux系统调用过程分析. https://www.binss.me/blog/the-analysis-of-linux-system-call/

[6] Fix-Mapped Addresses and ioremap. https://0xax.gitbooks.io/linux-insides/content/MM/linux-mm-2.html

[7] 王宗涛. Linux快速系统调用实现机制分析. TP316.81

[8] linux下系统调用的实现. https://www.pagefault.info/2010/10/09/implementation-of-system-call-under-linux.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/259816.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

批量下载小说网站上的小说(python爬虫)

随便说点什么 因为在学python&#xff0c;所有自然而然的就掉进了爬虫这个坑里&#xff0c;好吧&#xff0c;主要是因为我觉得爬虫比较酷&#xff0c;才入坑的。 想想看&#xff0c;你可以批量自动的采集互联网上海量的资料数据&#xff0c;是多么令人激动啊&#xff01; 所以我…

华为欧拉系统服务器开接口,华为操作系统 euleros

华为操作系统 euleros 内容精选换一换Atlas 900 AI集群安装上架、服务器基础参数配置、安装操作系统等操作&#xff0c;请根据集群配置参见对应的手册&#xff1a;《Atlas 900 PoD 用户指南 (型号9000, 直流)》《Atlas 900 PoD 用户指南 (型号9000, 交流)》《Atlas 900 计算节点…

对勾函数_对勾函数?2020福建省中考压轴题分析

训练营机密视频大公开欢迎转发、分享传播知识&#xff0c;传播力量&#xff01;福建也是全省统一考选择题&#xff1a;这题考的是二次函数的性质&#xff0c;先求出对称轴就好了填空题&#xff1a;这题看似有反比例&#xff0c;确实会用到反比例函数的对称性。但其实重点是考察…

通过Ajax解析和jQuery写了一个小小的导航条

最近在用ajax和jquery做开发&#xff0c;所以闲来无事写了些小导航条&#xff0c;通过ajax解析XML文件动态的创建WEB网站的导航条。 <link href"css/style.css" rel"stylesheet" type"text/css" /><script src"js/jquery-1.8.2.mi…

一次生产事故的优化经历

在一次正常的活动促销之后&#xff0c;客服开始陆续反馈有用户反应在抢标的时候打不开网页或者APP&#xff0c;在打开的时候标的就已经被抢光了&#xff0c;刚开始没有特别的上心&#xff0c;觉得抢标不就是这样吗&#xff0c;抢小米手机的时候也不就这样吗&#xff1f;随着活动…

Win系统利用本地安全策略全面禁止360等软件的安装与运行-1

这个理论应该也可以用在域对下设域用户上.各位不知道有没有这种经历&#xff0c;机子让别人玩了一上午&#xff0c;回来发现&#xff0c;自己干干净净的系统多了一堆某某安全助手&#xff0c;某某杀毒&#xff0c;某某手机助手等等&#xff0c;最可恨的还是不知一系列的&#x…

access考试素材_NCRE考试当天常见问题处理办法及各科目注意事项大汇总

温馨提醒为了方便大家在21-22号讨论考试抽中的题目&#xff0c;请自觉加入QQ群&#xff1a;776167039考试当天常见问题及处理办法大汇总问题一&#xff1a;考试当天忘记带身份证和准考证原因&#xff1a;这种情况&#xff0c;要么是忘了&#xff0c;要么真没有提前领到准考证。…

腾讯开源手游热更新方案,Unity3D下的Lua编程

写在前面\\xLua是Unity3D下Lua编程解决方案&#xff0c;自2016年初推广以来&#xff0c;已经应用于十多款腾讯自研游戏&#xff0c;因其良好性能、易用性、扩展性而广受好评。现在&#xff0c;腾讯已经将xLua开源到GitHub。\\2016年12月末&#xff0c;xLua刚刚实现新的突破&…

1加6投屏_6月1日起驾考要加项目?真相是这样

来源&#xff1a;新闻晨报近日网上流传一则消息让还没考出驾照的朋友们瑟瑟发抖网传消息称&#xff0c;上海、海南、陕西、贵州、浙江等地驾考科目二于6月1日起加项&#xff0c;因而“朋友们要抓紧时间报名&#xff0c;录入旧系统”。网传消息截图上海6月1日起科目二考试增加到…

网站等保测评针对服务器,互联互通测评知识分享之信息安全建设要点

原创 医疗测评实验室 中国软件评测中心 1周前医院互联互通测评&#xff0c;即国家医疗健康信息互联互通标准化成熟度测评&#xff0c;近年来随着政策的要求、需求的驱动、技术的更迭、价值的引领&#xff0c;越来越被业内人士接受和认可&#xff0c;测评热度也水涨船高。国家卫…

pandas合并groupby_pandas实践之GroupBy()

官网地址&#xff1a;https://pandas.pydata.org/docs/reference/groupby.htmlpandas中对数据进行分组操作的方法&#xff0c;官方有很详细的教程。下面的案例是真实遇到的问题&#xff0c;看一看用pandas是如何解决的。构造数据import pandas as pdimport numpy as npdf pd.D…

erdas遥感图像几何校正_定量/高光谱遥感之—光谱分析技术

文章转载自微信公众号CSDN&#xff0c;作者冰清-小魔鱼&#xff0c;版权归原作者及刊载媒体所有。在定量遥感或者高光谱遥感中&#xff0c;信息提取主要用到光谱/波谱分析技术。本专题对光谱/波谱分析中涉及的流程及一些技术进行讲解&#xff0c;包括以下内容&#xff1a;基本概…

Zipkin-1.19.0学习系列1:java范例

2019独角兽企业重金招聘Python工程师标准>>> 官网地址: https://github.com/openzipkin/zipkin http://zipkin.io/ https://www.oschina.net/p/zipkin 截止到2017/1/4为止&#xff0c;最新版本为: Zipkin 1.19 下载地址: https://github.com/openzipkin/zipkin/arc…

PageRank算法

1. PageRank算法概述 PageRank,即网页排名&#xff0c;又称网页级别、Google左側排名或佩奇排名。 是Google创始人拉里佩奇和谢尔盖布林于1997年构建早期的搜索系统原型时提出的链接分析算法&#xff0c;自从Google在商业上获得空前的成功后&#xff0c;该算法也成为其他搜索引…

linux中_在 Linux 桌面中开始使用 Lumina | Linux 中国

本文是 24 天 Linux 桌面特别系列的一部分。Lumina 桌面是让你使用快速、合理的基于 Fluxbox 桌面的捷径&#xff0c;它具有你无法缺少的所有功能。-- Seth Kenlon多年来&#xff0c;有一个名为 PC-BSD 的基于 FreeBSD 的桌面操作系统(OS)。它旨在作为一个常规使用的系统&#…

hdu 2612 Find a way (广搜)

Problem DescriptionPass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki.Yifenfei’s home is at the countryside, but Merceki’s home is in t…

正则表达式里转义字符_五分钟搞定正则表达式,如果没搞定,再加两分钟

五分钟搞定正则表达式&#xff0c;如果没搞定&#xff0c;再加两分钟【这是 ZY 第 18 篇原创文章】 文章概览一、正则表达式介绍正则表达式&#xff0c;又称规则表达式。&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xf…

百度富文本编辑器,改变图片上传存储路径

我用的是最新版&#xff01; 找到以下2个关键文件&#xff1a; YourPath.../Ueditor/php/config.json YourPath.../Ueditor/php/Uploader.class.php config.json找到如下代码&#xff1a; "imagePathFormat": "...(这里不用管)",//找到imagePathFormat所在…

如何手动给Docker容器设置静态IP

2019独角兽企业重金招聘Python工程师标准>>> 要点&#xff1a; 1.首先需要在宿主机上虚拟出来一个真实可用桥接网卡比如br0 2.docker启动的时候默认使用br0进行桥接网络 3.创建docker容器的时候使用--netnone模式 4.手动为每个创建的容器生成静态ip。但是ip每次在重…

的函数原型_JS基础函数、对象和原型、原型链的关系

JS的原型、原型链一直是比较难理解的内容&#xff0c;不少初学者甚至有一定经验的老鸟都不一定能完全说清楚&#xff0c;更多的"很可能"是一知半解&#xff0c;而这部分内容又是JS的核心内容&#xff0c;想要技术进阶的话肯定不能对这个概念一知半解&#xff0c;碰到…