LSM零知识学习三、插桩原理实现细节(1)

news2024/11/22 10:17:49

本文内容参考:

LSM(Linux Security Modules)框架原理解析_lsm框架_pwl999的博客-CSDN博客

Linux LSM(Linux Security Modules) Hook Technology_weixin_30929011的博客-CSDN博客

特此致谢!

一、插桩具体实现

前文介绍了插桩原理,本文来详述插桩原理的具体实现。

在安全相关的关键系统调用中都显式地插入了静态插桩点。例如,在open()系统调用中通过vfs_open函数最终调用了security_file_open函数(关于系统调用的具体过程请参考相关文章,在此不作讲述)。vfs_open函数在fs/open.c中,代码如下:

/**
 * vfs_open - open the file at the given path
 * @path: path to open
 * @file: newly allocated file with f_flag initialized
 * @cred: credentials to use
 */
int vfs_open(const struct path *path, struct file *file)
{
	file->f_path = *path;
	return do_dentry_open(file, d_backing_inode(path->dentry), NULL);
}

do_entry_open函数在同文件中,代码如下:

static int do_dentry_open(struct file *f,
			  struct inode *inode,
			  int (*open)(struct inode *, struct file *))
{
	static const struct file_operations empty_fops = {};
	int error;

	path_get(&f->f_path);
	f->f_inode = inode;
	f->f_mapping = inode->i_mapping;
	f->f_wb_err = filemap_sample_wb_err(f->f_mapping);
	f->f_sb_err = file_sample_sb_err(f);

	if (unlikely(f->f_flags & O_PATH)) {
		f->f_mode = FMODE_PATH | FMODE_OPENED;
		f->f_op = &empty_fops;
		return 0;
	}

	if ((f->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) {
		i_readcount_inc(inode);
	} else if (f->f_mode & FMODE_WRITE && !special_file(inode->i_mode)) {
		error = get_write_access(inode);
		if (unlikely(error))
			goto cleanup_file;
		error = __mnt_want_write(f->f_path.mnt);
		if (unlikely(error)) {
			put_write_access(inode);
			goto cleanup_file;
		}
		f->f_mode |= FMODE_WRITER;
	}

	/* POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
	if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))
		f->f_mode |= FMODE_ATOMIC_POS;

	f->f_op = fops_get(inode->i_fop);
	if (WARN_ON(!f->f_op)) {
		error = -ENODEV;
		goto cleanup_all;
	}

	error = security_file_open(f);
	if (error)
		goto cleanup_all;

	error = break_lease(locks_inode(f), f->f_flags);
	if (error)
		goto cleanup_all;

	/* normally all 3 are set; ->open() can clear them if needed */
	f->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
	if (!open)
		open = f->f_op->open;
	if (open) {
		error = open(inode, f);
		if (error)
			goto cleanup_all;
	}
	f->f_mode |= FMODE_OPENED;
	if ((f->f_mode & FMODE_READ) &&
	     likely(f->f_op->read || f->f_op->read_iter))
		f->f_mode |= FMODE_CAN_READ;
	if ((f->f_mode & FMODE_WRITE) &&
	     likely(f->f_op->write || f->f_op->write_iter))
		f->f_mode |= FMODE_CAN_WRITE;
	if ((f->f_mode & FMODE_LSEEK) && !f->f_op->llseek)
		f->f_mode &= ~FMODE_LSEEK;
	if (f->f_mapping->a_ops && f->f_mapping->a_ops->direct_IO)
		f->f_mode |= FMODE_CAN_ODIRECT;

	f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
	f->f_iocb_flags = iocb_flags(f);

	file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);

	if ((f->f_flags & O_DIRECT) && !(f->f_mode & FMODE_CAN_ODIRECT))
		return -EINVAL;

	/*
	 * XXX: Huge page cache doesn't support writing yet. Drop all page
	 * cache for this file before processing writes.
	 */
	if (f->f_mode & FMODE_WRITE) {
		/*
		 * Paired with smp_mb() in collapse_file() to ensure nr_thps
		 * is up to date and the update to i_writecount by
		 * get_write_access() is visible. Ensures subsequent insertion
		 * of THPs into the page cache will fail.
		 */
		smp_mb();
		if (filemap_nr_thps(inode->i_mapping)) {
			struct address_space *mapping = inode->i_mapping;

			filemap_invalidate_lock(inode->i_mapping);
			/*
			 * unmap_mapping_range just need to be called once
			 * here, because the private pages is not need to be
			 * unmapped mapping (e.g. data segment of dynamic
			 * shared libraries here).
			 */
			unmap_mapping_range(mapping, 0, 0, 0);
			truncate_inode_pages(mapping, 0);
			filemap_invalidate_unlock(inode->i_mapping);
		}
	}

	return 0;

cleanup_all:
	if (WARN_ON_ONCE(error > 0))
		error = -EINVAL;
	fops_put(f->f_op);
	put_file_access(f);
cleanup_file:
	path_put(&f->f_path);
	f->f_path.mnt = NULL;
	f->f_path.dentry = NULL;
	f->f_inode = NULL;
	return error;
}

从以上fs/open.c中do_entry_open函数的代码就可以看出前文提到的LSM框架的Hook机制。这里再来对照一下以加强认识:

机制如下:

首先用户执行系统调用时,先通过原有的内存接口进行功能性的错误检查;然后再进行自主访问控制DAC检查;在访问内核的内部对象之前,通过安全模块的Hook函数调用LSM,LSM查看操作上下文和主客体安全域的相关信息决定是否允许请求即确定访问的合法性,返回信息。

概括为3个步骤:

(1)先通过原有的内部接口进行功能性的错误检查;

(2)再进行自主访问控制DAC检查;

(3)调用LSM的Hook函数。
 

重点关注以下代码(片)段:

error = security_file_open(f);
if (error)
	goto cleanup_all;

这段代码就对应上图及流程中的调用LSM或者更准确地说具体安全模块的Hook函数。

欲知此函数详情,且看下回分解。

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

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

相关文章

chatgpt赋能python:Python图片大小怎么算?

Python图片大小怎么算? 在Web开发中,经常需要展示图片,但是为了让网页加载速度更快,我们需要对图片进行压缩和优化,其中一个重要的参数就是图片的大小。那么在Python中,如何计算图片大小呢? 图…

包扫描工具实现(详解)

文章目录 前言包扫描实现思路(需求分析): 具体实现完整代码 前言 注解在 Java 是一个非常重要的存在,而且它出现的非常频繁。 在一个工程下可能有许多的包或者Jar包,为了结合注解可以准确的定位到一个需要的类上&…

代码随想录算法训练营第四十六天|139.单词拆分

LeetCode139.单词拆分 动态规划五部曲: 1,确定dp数组以及下标的含义: dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。 2,确定递推公式: 如果确定dp[j…

javascript基础二十:说说你对DOM的理解,常见的操作有哪些?

一、DOM 文档对象模型 (DOM) 是 HTML 和 XML 文档的编程接口 它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容 任何 HTML或XML文档都可以用 DOM表示为一个由节点构成的层级结构…

交通物流模型 | Python建模实现动态交通分配优化问题求解

文章目录 效果一览文章概述研究内容程序设计参考资料效果一览 文章概述 交通物流模型 | Pyomo建模框架实现动态交通分配优化问题求解,DTA 交通分配问题通常需要考虑许多因素,例如道路容量、交通需求、速度限制、车辆类型、交通信号灯等,在城市规划和交通管理领域中具有重要的…

分布式系统概念和设计——分布式事务

分布式系统概念和设计 分布式事务 访问多个服务器管理的对象的事务称为分布式事务。 当一个分布式事务结束时,事务的原子特性要求所有参与事务的服务器必须全部提交或全部放弃。 实现: 其中一个服务器承担了协调者的角色,保证在所有的服务器…

chatgpt赋能python:Python图片取模:提高网页加载速度与用户体验

Python图片取模:提高网页加载速度与用户体验 随着互联网的发展与全球化进程的加速,网站的速度与易用性成为用户选择网站的重要因素。在这种情况下,我们需要优化网站的加载速度与用户体验。其中一种优化方法就是使用图片取模。 本文将向您介…

chatgpt赋能python:Python图像处理技术:学习Python,掌握图像处理!

Python图像处理技术:学习Python,掌握图像处理! 在当今时代,图像处理已成为现代生活中不可或缺的一部分,从照片、视频到尖端医疗设备中的医学图像,都需要使用图像处理技术。Python图像处理技术是当今广泛使…

2023年淘宝天猫京东618活动时间安排和活动攻略

2023年淘宝天猫京东618活动力度大吗?活动什么时候开始?有什么省钱技巧?让我们来一起看一下! 2023年淘宝618活动一览 时间安排 第一波(开门红) 预售时间:5月26日 14:00-5月26日 20:00 定金时间:5月26日 …

快排+归并

&#x1f947;快排 &#x1f380;快排题目 &#x1f3ab;快排代码实现 #include<iostream> using namespace std; const int N100010;//定义一个只读变量 int a[N]{0};//开辟空间&#xff0c;定义全局变量&#xff0c;后来就不用传参了 void quicksort1(int l,int r) {…

(三)多文件云传输框架项目实现(详解)

文章目录 前言《多文件云传输》框架概述简介技术实现框架基本思想 《多文件云传输》框架思考需求分析 《多文件云传输》框架实现数据基础实现技术难点实现 前言 《多文件云传输》框架的实现是本人的一个编程训练项目&#xff0c;为了提升本人的编程能力、JAVA 编程思想&#x…

第二章 数据类型、运算符与表达式

如何打开项目 如何打开已经存在的解决方案&#xff1f; 找到要打开的解决方案目录&#xff0c;进去之后双击后缀为.sln的文件即可打开该解决方案。 或者从最近打开项目中打开&#xff1a; Online Judge使用 OJ简介 在线判题系统&#xff08;Online Judge&#xff0c;缩写OJ…

GIN框架(GOLANG)讲解如何疯速入门

1.初始化项目&#xff1a; 1.初始化项目&#xff1a;go mod init 2.下载gin框架&#xff1a;go get -u github.com/gin-gonic/gin 3.引入&#xff1a;import "github.com/gin-gonic/gin" 注意点&#xff1a; 报错&#xff1a;$GOPATH/go.mod exists but should …

Python可视化分析项目

今天给大家分享一个基于python的django框架结合爬虫以及数据可视化和数据库的项目&#xff0c;该项目总体来说还是挺不错的&#xff0c;下面针对这个项目做具体介绍。 1&#xff1a;项目涉及技术&#xff1a; 项目后端语言&#xff1a;python 项目页面布局展现&#xff1a;前…

代码随想录算法训练营第四十二天|416. 分割等和子集

LeetCode416. 分割等和子集 背包问题&#xff0c;有N件物品和一个最多能背重量为W 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。背包问题有多种背包方式&#xff0c;常见…

地理探测器的应用方法

关于地理探测器的使用&#xff0c;网络上有大量的教学视频及资料&#xff0c;既可以用Excel计算&#xff0c;也可以利用R语言计算&#xff0c;本文主要分享利用Excel计算的方法&#xff0c;借鉴了大量的学习资料&#xff0c;记录一下供自己参考&#xff0c;也希望能帮到有需要的…

CLR via C#(一)CLR的执行模型

一、什么是CLR CLR全称Common Language Runtime&#xff0c;即公共语言运行时。它可以为所有面向CLR的语言提供运行时的内存管理、程序集加载、安全性、异常处理和线程同步等功能。 事实上&#xff0c;CLR并不关心开发者使用的到底是哪种语言&#xff0c;只要这门语言的编译器…

chatgpt赋能python:Python图像处理优化技巧:提高网站SEO效果的必修课程

Python图像处理优化技巧&#xff1a;提高网站SEO效果的必修课程 介绍 在当前数字化时代&#xff0c;网站的SEO优化已经成为了网站营销的重要一环。在优化网站SEO的同时&#xff0c;提升图像处理技巧也成为了重要的一环。Python作为当前最为火热的数据科学语言之一&#xff0c…

chatgpt赋能python:Python计算圆柱体积的方法

Python计算圆柱体积的方法 Python是一种广泛使用的编程语言&#xff0c;由于其易于学习和使用的特点&#xff0c;许多人在业余时间选择了学习Python。Python可以用来解决各种计算问题&#xff0c;其中包括计算圆柱体积。在本文中&#xff0c;我们将探讨如何使用Python计算圆柱…

chatgpt赋能python:Python在一个程序里调用另一段程序

Python在一个程序里调用另一段程序 随着Python程序的复杂度越来越高&#xff0c;有时候一个程序难以处理所有的任务。这时候我们可能需要将任务拆分成多个脚本来执行。但是&#xff0c;这会导致代码的复杂性增加&#xff0c;同时也会增加可读性和维护成本。这时候&#xff0c;…