Linux内核之文件驱动随笔

前言

        近期需要实现linux系统文件防护功能,故此调研了些许知识,如何实现文件防护功能从而实现针对文件目录防护功能。当被保护的目录,禁止增删改操作。通过内核层面实现相关功能,另外在通过跟应用层面交互从而实现具体的业务功能。好了,话不多说,直接开始本文的主题,详情请见下文(下文实现介绍为ubuntu18.x版本)。

一.查看系统内核函数定义

如上所示,在系统中,每个系统函数都定义一个函数对应的原型号,如上mkdir方法定义的类型宏号表示。红框中,当时终端使用mkdir,内核中最终通过_SYSCALL调用sys_mkdir方法。

sys_mkdir方法的定义:

如上为函数原型的定义,可通过上述的函数定义进行拦截从而实现相关的业务功能。(注:在新的系统架构中,现在都通过寄存器来实现相关的函数定义,例如:

asmlinkage long hook_sys_mkdir(struct pt_regs *regs) {char __user *pathname = (const char __user *)regs->di; // x86_64 的第一个参数umode_t mode = (umode_t)regs->si; // 第二个参数// 钩子逻辑printk("mkdir: path=%s, mode=%o\n", pathname, mode);// 调用原始系统调用return orig_sys_mkdir(regs);
}

上述的方法定义,省略了函数的个数定义,从而使系统的拦截调用更加的方便灵活,所需的参数直接从pt_regs结构中直接获取,灵活方便,不用再定义每个方法各自的参数个数以及相关的定义方法。 

二.系统拦截调用实现

        如下通过自定义钩子函数来实现系统函数mkdir的拦截调用步骤

        1.定义钩子函数

asmlinkage long hook_sys_mkdir(struct pt_regs *regs);
typedef asmlinkage long (*sys_mkdir_ptr)(struct pt_regs *regs);
static sys_mkdir_ptr origin_mkdir;

        2.获取系统函数符号表   

        注:不同系统可能获取符号表方式存在偏差,另外如果和应用层交互时,也可以通过应用层通过netlink将对应的符号表地址传入内核当中。  

kallsyms_lookup_name_t get_kallsyms_lookup_name(void)
{int ret;kallsyms_lookup_name_t pfun;static struct kprobe kp ={.symbol_name = "kallsyms_lookup_name",};ret = register_kprobe(&kp);if (ret < 0){printk(KERN_INFO "register_kprobe failed, returned %d\n", ret);return NULL;}pfun = (kallsyms_lookup_name_t)kp.addr;unregister_kprobe(&kp);return pfun;
}static int obtain_sys_call_table_addr(unsigned long *sys_call_table_addr)
{unsigned long temp_sys_call_table_addr;kallsyms_lookup_name_t fn_kallsyms_lookup_name = 0;fn_kallsyms_lookup_name = get_kallsyms_lookup_name();if (fn_kallsyms_lookup_name == NULL){printk("Fail to get_allsyms_lookup_name\n");return -1;}temp_sys_call_table_addr = fn_kallsyms_lookup_name("sys_call_table");/* Return error if the symbol doesn't exist */if (0 == temp_sys_call_table_addr){printk("Can not found sys_call_table\n");return -1;}printk("Found sys_call_table: %p", (void *)temp_sys_call_table_addr);*sys_call_table_addr = temp_sys_call_table_addr;return 0;
}

        3.进行钩子操作

        因系统具备写保护,进行hook时需要先关闭写保护,钩子完成之后再将写保护恢复(函数的hook放在如下disable_cr0和enable_cr0之间)。

写保护和恢复保护函数处理:   

unsigned int disable_cr0(void)
{unsigned int cr0 = 0;unsigned int ret;asm volatile ("movq %%cr0, %%rax": "=a"(cr0));ret = cr0;//清理第16位的标志位cr0 &= 0xfffeffff;asm volatile ("movq %%rax, %%cr0"::"a"(cr0));return ret;
}void enable_cr0(unsigned int val)
{asm volatile ("movq %%rax, %%cr0": : "a"(val));
}

        函数钩子更换

// sys_call_table_addr为上述步骤获取的函数符号表地址void set_hook(){disable_cr0();origin_mkdir = ((unsigned long *)(sys_call_table_addr))[__NR_mkdir];enable_cr0();
}

        4.mkdir钩子运行流程

        自定义函数进行对mkdir函数的拦截,进行自己的业务处理,正常情况再调用原始内核函数

        注:在某些系统上,可能在内核中调用了其他的函数,例如麒麟系统,mkdir命令,内核中调用的不是sys_mkdir,虽然可以通过上述查询到,但是实际上调用的是sys_mkdirat.所以在ko中直接进行sys_mkdirat的hook即可。如何查看某个命令内核真正调用哪个内核函数,可以通过strace命令进行查看,例如mkdir命令查看,如下:(ubuntu18.04)

root@ubuntu:~# strace -e trace=mkdir,mkdirat mkdir Test
mkdir("Test", 0777)                     = 0
+++ exited with 0 +++
root@ubuntu:~# 

如上,输出执行输出结果,mkdir,那么说明调用内核的sys_mkdir方法。 

     麒麟v10,aarch64架构,跟上述不一致,详情见:

[root@localhost]# strace -e trace=mkdir,mkdirat mkdir Test
mkdirat(AT_FDCWD, "Test", 0777)         = 0
+++ exited with 0 +++
[root@localhost]#

上述结果输出mkdirat,跟上述ubuntu差别很大,表示mkdir命令对应调用的是系统内核的sys_mkdirat函数。

综上两种情况,再编写系统拦截方法时,一定需要注意不同结构系统存在的偏差,依据实际情况而定再行决定处理相关hook方式函数。 

asmlinkage long origin_mkdir (struct pt_regs *regs)
{int ret;char *filename = NULL;char *regs_filename = (char *)(regs->di);int file_len = strnlen_user(regs_filename, MAX_PATH);filename = kmalloc(file_len, GFP_KERNEL);if (filename == NULL){printk("Fail to kmalloc\n");goto end;}ret = strncpy_from_user(filename, regs_filename, file_len);if (ret < 0){printk("Fail to strncpy_from_user\n");goto end;}printk("current opetation filename:  %s\n", filename);
end:if (filename){kfree(filename);}return old_sys_mkdir(regs);
}

        5.恢复系统原始函数   

        卸载该驱动文件记得恢复系统原始函数,避免发生崩溃问题。

// sys_call_table_addr为上述步骤获取的函数符号表地址void restore_hook()
{disable_cr0();((unsigned long *)(sys_call_table_addr))[__NR_mkdir] = origin_mkdir ;enable_cr0();
}

如上就是一个mkdir函数的完成hook过程的步骤,上述的分布代码将在如下第三标题中完美整合从而实现一个完整的调用并且实现生成一个ko文件可以进行使用。

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

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

相关文章

利用大模型实现地理领域文档中英文自动化翻译

一、 背景描述 在跨国性企业日常经营过程中&#xff0c;经常会遇到专业性较强的文档翻译的需求&#xff0c;例如法律文书、商务合同、技术文档等&#xff1b;以往遇到此类场景&#xff0c;企业内部往往需要指派专人投入数小时甚至数天来整理和翻译&#xff0c;效率低下&#x…

鸿蒙Flutter仓库停止更新?

停止更新 熟悉 Flutter 鸿蒙开发的小伙伴应该知道&#xff0c;Flutter 3.7.12 鸿蒙化 SDK 已经在开源鸿蒙社区发布快一年了&#xff0c; Flutter 3.22.x 的鸿蒙化适配一直由鸿蒙突击队仓库提供&#xff0c;最近有小伙伴反馈已经 2 个多月没有停止更新了&#xff0c;不少人以为停…

(七)深入了解AVFoundation-采集:采集系统架构与 AVCaptureSession 全面梳理

引言 在 iOS 开发中&#xff0c;AVFoundation 是构建音视频功能的强大底层框架。而在音视频功能中&#xff0c;“采集”往往是最基础也是最关键的一环。从摄像头捕捉图形、到麦克风获取声音&#xff0c;构建一条高效且稳定的采集链是开发高质量音视频应用的前提。 本系列将逐…

QML ShaderEffect(着色器效果)组件

ShaderEffect 是 QML 中用于实现自定义着色器效果的组件&#xff0c;允许开发者使用 GLSL 着色器语言创建图形效果。 核心属性 基本属性 属性类型默认值说明fragmentShaderstring""片段着色器代码vertexShaderstring""顶点着色器代码blendingbooltrue是…

基于javaweb的SSM教材征订与发放管理系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

大模型学习笔记------Llama 3模型架构之分组查询注意力(GQA)

大模型学习笔记------Llama 3模型架构之分组查询注意力&#xff08;GQA&#xff09; 1、分组查询注意力&#xff08;GQA&#xff09;的动机2、 多头注意力&#xff08;Multi-Head Attention, MHA&#xff09;3、 多查询注意力 (Multi-Query Attention&#xff0c;MQA)4、 分组查…

matlab 环形单层柱状图

matlab 环形单层柱状图 matlab 环形单层柱状图 matlab 环形单层柱状图 图片 图片 【图片来源粉丝】 我给他的思路是&#xff1a;直接使用风玫瑰图可以画出。 rose_bar 本次我的更新和这个有些不同&#xff01;是环形柱状图&#xff0c;可调节细节多&#xff1b; 只需要函数…

Docker--Docker网络原理

虚拟网卡 虚拟网卡&#xff08;Virtual Network Interface&#xff0c;简称vNIC&#xff09; 是一种在软件层面模拟的网卡设备&#xff0c;不依赖于物理硬件&#xff0c;而是通过操作系统或虚拟化技术实现网络通信功能。它允许计算机在虚拟环境中模拟物理网卡的行为&#xff0…

linux基础14--dns和web+dns

DNS&#xff1a;域名系统&#xff08;Domain Name System&#xff09; DNS协议是用来将域名转换为IP地址或将IP地址转换为相应的域名 DNS使用TCP和UDP端口53&#xff0c;给用户提供解析时一般使用UDP53 对于每一级域名长度的限制是63个字符&#xff0c;域名总长度则不能超过2…

C++抽象基类定义与使用

在 C 中&#xff0c;抽象基类&#xff08;Abstract Base Class, ABC&#xff09; 是一种特殊的类&#xff0c;用于定义接口规范和约束派生类的行为。它通过纯虚函数&#xff08;Pure Virtual Function&#xff09;强制要求派生类实现特定功能&#xff0c;自身不能被实例化。以下…

用selenium4 webdriver + java 搭建并完成第一个自动化测试脚本

自动化测试任务&#xff1a; 百度搜索自己的姓名。点击第一个链接&#xff08;或者第二个&#xff09;&#xff0c;在新的页面上&#xff0c;添加断言&#xff0c;验证你的名字是否存在。 实验资料百度网盘下载路径&#xff1a; 链接: https://pan.baidu.com/s/1nVlHX_ivres…

LLM大模型中的基础数学工具—— 约束优化

Q26: 推导拉格朗日乘子法 的 KKT 条件 拉格朗日乘子法与 KKT 条件是啥&#xff1f; 拉格朗日乘子法是解决约束优化问题的利器。比如&#xff0c;想最小化函数 &#xff0c;同时满足约束 &#xff0c;就构造拉格朗日函数 &#xff08; 是乘子&#xff09;。KKT 条件是解这类问…

net+MySQL中小民营企业安全生产管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 近些年来&#xff0c;随着科技的飞速发展&#xff0c;互联网的普及逐渐延伸到各行各业中&#xff0c;给人们生活带来了十分的便利&#xff0c;中小民营企业安全生产管理系统利用计算机网络实现信息化管理&#xff0c;使企业的中小民营企业安全生产管理发展和服务水平有显…

论文阅读:2024 arxiv AI Safety in Generative AI Large Language Models: A Survey

总目录 大模型安全相关研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 AI Safety in Generative AI Large Language Models: A Survey 生成式人工智能大型语言模型中的人工智能安全性:一项调查 https://arxiv.org/pdf/2407.18369 https://www.doubao.com…

【MySQL数据库】表的约束

目录 1&#xff0c;空属性 2&#xff0c;默认值 3&#xff0c;列描述 4&#xff0c;zerofill 5&#xff0c;主键primary key 6&#xff0c;自增长auto_increment 7&#xff0c;唯一键unique 8&#xff0c;外键foreign key 在MySQL中&#xff0c;表的约束是指用于插入的…

基于javaweb的SpringBoot校园失物招领系统设计与实现(源码+文档+部署讲解)

技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…

多模态大语言模型arxiv论文略读(二十六)

Holistic Autonomous Driving Understanding by Bird’s-Eye-View Injected Multi-Modal Large Models ➡️ 论文标题&#xff1a;Holistic Autonomous Driving Understanding by Bird’s-Eye-View Injected Multi-Modal Large Models ➡️ 论文作者&#xff1a;Xinpeng Ding,…

“星睿O6” AI PC开发套件评测 - 部署PVE搭建All in One NAS服务器

Radxa O6平台上部署PVE搭建All in One NAS服务器 Radxa O6是一款性能卓越的单板计算机&#xff0c;其强劲的硬件配置和多样化的接口设计&#xff0c;使其成为家庭和小型企业理想的All in One服务器解决方案。值得一提的是&#xff0c;O6原生配备了两个5G网口&#xff0c;便于直…

C++ linux打包运行方案(cmake)

文章目录 背景动态库打包方案动态库转静态库动态库打到软件包中 运行 背景 使用C编写的一个小项目&#xff0c;需要打包成ubuntu下的可执行文件&#xff0c;方便分发给其他ubuntu执行&#xff0c;因为docker镜像方案过于臃肿&#xff0c;所以需要把项目的动态库都打在软件包中…

Linux内核编译(Ubuntu)

实验内容&#xff1a;在系统中下载统一发行版本的版本号较高的内核&#xff0c;编译之后运行自己编译的内核&#xff0c;并使用uname-r命令查看是否运行成功。 实验步骤&#xff1a; 1.查看实验环境和内核版本 图1 实验环境 VMware中虚拟机Ubuntu&#xff08;24.04&#xff…