news 2026/5/20 22:51:12

Linux内核安全模块深入剖析【1.8】

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux内核安全模块深入剖析【1.8】

6.系统(system)

文件可以有多个,套接字也可以有多个,但系统类别的客体实例是全局性的,只有一个。system 类型之上的操作有获取 ipc 信息(ipc_info)、 syslog 相关操作(syslog_console、 syslog_ mod、 syslog_read)和内核模块相关操作(module_request)。虽然叫系统,却只涉及寥寥几个操作许可,让人感到有些奇怪。

(1)进程间通信

● ipc_info 读取系统 ipc 信息

具体来说,当系统调用 msgctl 的 cmd 参数为 IPC_INFO 或 MSG_INFO 时,或当系统调用semctl 的 cmd 参数为 IPC_INFO 或 SEM_INFO 时,或当系统调用 shmctl 的 cmd 参数为 IPC_INFO或 SHM_INFO 时, SELinux 会判断此操作许可。

(2) syslog

以下几个操作都和系统调用 syslog 相关。

● syslog_read:读取 kernel 日志消息。

● syslog_mod:清空 kernel 消息缓冲区。

● syslog_console:控制 kernel 日志打印到控制台。

(3) module

● module_request:加载内核模块。

7.安全(security)

SELinux 的设计者希望设计出一个完备的系统,对于自身的管理也要纳入到 SELinux 的管理体系中。所以 SELinux 引入了新的客体类别——安全。在安全类别上的操作都和 SELinux 自身管理有关。

这里有一个问题: SELinux 是如何管理自身的呢?因为 Linux 内核对增加系统调用非常慎重,所以 SELinux 没有引入新的系统调用,而是构建了一个文件系统——selinuxfs。在 Linux上增加文件系统是很容易的。用户态进程通过读写 selinuxfs 上的文件来实现对 SELinux 的管理。相应地, SELinux 规定了以下操作:

● check_context:查看安全上下文是否合法。

● compute_av:根据源安全上下文、目的安全上下文、客体类型计算访问许可。

● compute_create:输入源安全上下文、目的安全上下文、客体类型,根据 type_transition策略计算新安全上下文。

● compute_member:输入源安全上下文、目的安全上下文、客体类型,根据 type_member策略计算新安全上下文。

● compute_relabel:输入源安全上下文、目的安全上下文、客体类型,根据 type_change策略计算新安全上下文。

● compute_user:输入安全上下文和用户名,计算新的安全上下文。

● load_policy:加载安全策略。

● setbool:改变 SELinux 布尔变量值。

● setcheckreqprot:修改 SELinux 变量 checkreqprot 值。在执行 mmap 和 mprotect 系统调用时,若值为 0,执行来自内核的检验方法,若值为 1,执行来自应用的检验模式。内核的检查方法是将 read 和 exec 联系起来。

● setenforce:改变 SELinux 的 enforcement 状态(permissive 或 enforcing)。

● setsecparam:改变 AVC 参数。

8.能力

能力是进程的特权。从逻辑上讲,能力是进程的一种资源。如果能力可以是一种客体,那么进程的内存大小、进程的描述符数量、文件占用的磁盘块数量、用户同时拥有的进程数量都可以是客体。

如果把能力作为一种客体,那么对能力的操作应该是添加、删除、查看。但是这样设计没有任何意义。因为在 execve 系统调用中不会区分添加和删除;在 capset 系统调用中只允许删除能力,而删除能力本身不应被限制;查看进程的能力也没有什么安全问题,没有限制的必要。

SELinux 要套用它的标准逻辑“主体操作客体”。所以 SELinux 将能力定义为一种客体类别,将能力上的操作定义为具体的能力,如 cap_chown。这种设计带来了三个问题:

(1)具体的能力怎么能成为能力的操作呢?这不合逻辑。

(2)进程是主体,能力是客体,能力本身就是进程的一个属性,主体和客体的安全上下文总是一样的。

(3) SELinux 为能力设计了两个客体类别: capability 和 capability2。 capability 对应前 32 个能力, capability2 对应后 32 个能力。

SELinux 内部用一个比特表示一个操作, 用一个 32 位整数表示在某个客体类别上的全部操作类型。如进程上的操作一共有 30 个,目录上的操作一共有 25 个,都没有超过 32。但是在能力上,原有代码的数据结构无法表示,为了解决这个问题, SELinux 就多引入了一个能力相关的客体类别 capability2。

能力只有一个, capability 和 capability2 在语义上没有区别,这种设计实在算不上优雅。9.用户态客体

Linux 系统中还有一些客体存在于用户态。如数据库,在内核眼里只有文件,没有表( table)、记录(record)之类。所以对数据库的控制自然就应该由用户态服务进程来实施。但是,相关的策略仍然被内核掌控,整个系统只有一个策略库,这个策略库存储在内核内存之中,由内核的安全服务器负责管理。那些用户态服务进程所做的工作就是查询策略库确定对用户态客体的操作是否允许。

SELinux 的用户态客体包括数据库类型(db_database、 db_table、 db_procedure、 db_column、db_tuple……)、 X-Window 相关类型(x_drawable、 x_screen、 x_gc、 x_font、 x_colormap……)、dbus 等。

10.其他

SELinux 中还有一些很少用到的客体,这里就不列举了。

7.2.3 安全上下文的生成和变化

7.2.1 节介绍了安全上下文, 7.2.2 节介绍了客体类别和客体上的操作。有了安全上下文,有了操作,再加上 7.3 节要介绍的 SELinux 策略,系统管理员就可以规定安全上下文为 A 的进程可以对安全上下文为 B 的文件进行 C 操作。这样就完成了 SELinux 的强制访问控制。

但是,主体和客体的安全上下文的值是怎么设置的?主体和客体的安全上下文能不能改变?如果能,可以改变成什么值?

1.安全上下文的初始值

进程的安全上下文的初始值有两个来源:

(1)创建进程时,子进程的安全上下文是父进程的安全上下文的副本。

security/selinux/hooks.c static int selinux_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) { const struct task_security_struct *old_tsec; struct task_security_struct *tsec; old_tsec = old->security; tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp); if (!tsec) return -ENOMEM; new->security = tsec; return 0; }

(2) Linux 系统中第一个进程的安全上下文是 SECINITSID_KERNEL 所对应的安全上下文。

security/selinux/hooks.c static void cred_init_security(void) { struct cred *cred = (struct cred *) current->real_cred; struct task_security_struct *tsec; tsec = kzalloc(sizeof(struct task_security_struct), GFP_KERNEL); if (!tsec) panic("SELinux: Failed to initialize initial task.\n"); tsec->osid = tsec->sid = SECINITSID_KERNEL; cred->security = tsec; }

SELinux 代码将所有的安全上下文存储在一个数组中,为了提高效率, SELinux 代码用数组项的序号来代表安全上下文。这个序号被称作 sid。上面代码中的 SECINITSID_KERNEL 就是一个 sid。

cred_init_security 函数被 SELinux 的初始化函数调用,它所设置的进程正是系统的第一个进程:

security/selinux/hooks.c static __init int selinux_init(void) { if (!security_module_enable(&selinux_ops)) { selinux_enabled = 0; return 0; } if (!selinux_enabled) { printk(KERN_INFO "SELinux: Disabled at boot.\n"); return 0; } printk(KERN_INFO "SELinux: Initializing.\n"); /* Set the security state for the initial task. */ cred_init_security(); default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); sel_inode_cache = kmem_cache_create("selinux_inode_security", sizeof(struct inode_security_struct), 0, SLAB_PANIC, NULL); avc_init(); if (register_security(&selinux_ops)) panic("SELinux: Unable to register with kernel.\n"); if (selinux_enforcing) printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); else printk(KERN_DEBUG "SELinux: Starting in permissive mode\n"); return 0; }

2.安全上下文的改变

不是所有的主体和客体都需要改变安全上下文,进程间通信类客体就没有必要改变安全上下文。下面列出改变进程和文件的安全上下文的逻辑。

(1)进程

SELinux 提供了两种方式改变进程的安全上下文。第一种方式是进程调用 execve 系统调用,第二种方式是通过写/proc/self/attr/current 文件。这两种方式在前面已经列举。

(2)文件

文件的安全上下文记录在文件的扩展属性 security.selinux 中,修改扩展属性 security.selinux的值就是修改文件的安全上下文。

security/selinux/hooks.c static int selinux_inode_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { struct inode *inode = dentry->d_inode; struct inode_security_struct *isec = inode->i_security; struct superblock_security_struct *sbsec; struct common_audit_data ad; u32 newsid, sid = current_sid(); int rc = 0; if (strcmp(name, XATTR_NAME_SELINUX)) return selinux_inode_setotherxattr(dentry, name); sbsec = inode->i_sb->s_security; if (!(sbsec->flags & SBLABEL_MNT)) return -EOPNOTSUPP; if (!inode_owner_or_capable(inode)) return -EPERM; ad.type = LSM_AUDIT_DATA_DENTRY; ad.u.dentry = dentry; rc = avc_has_perm(sid, isec->sid, isec->sclass, FILE__RELABELFROM, &ad); if (rc) return rc; rc = security_context_to_sid(value, size, &newsid); … if (rc) return rc; rc = avc_has_perm(sid, newsid, isec->sclass, FILE__RELABELTO, &ad); if (rc) return rc; rc = security_validate_transition(isec->sid, newsid, sid, isec->sclass); if (rc) return rc; return avc_has_perm(newsid, sbsec->sid, SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, &ad); }

上述代码判断的操作许可较多,主要的有三个: 1)文件的安全上下文不再是现在的值(RELABELFROM)。2)文件的安全上下文可以是新的值(RELABELTO)。3)文件所在的文件系统允许文件新的安全上下文(ASSOCIATE)。

7.3 安全策略

UNIX/Linux 的设计传统是机制和策略分离。 SELinux 遵循了这一传统。 7.2 节介绍的SELinux 机制是:

1)主体是进程,客体细分为若干类别。2)在每个客体类别上定义若干操作。3)每一个主体和客体的实例都关联安全上下文。4)主体操作客体时, SELinux 会根据策略判断操作是否允许。本节集中讲述一下 SELinux 的策略。下面看一个策略的例子:

策略语句 策略含义
allow init sshd_exec_t:file { getattr open read execute }; 允许执行
allow init sshd:process transition; 允许域转换
allow sshd sshd_exec_t:file { entrypoint read execute }; 允许作为入口点
allow sshd init:process sigchild; 允许发 sigchild
allow init sshd:process { siginh rlimitinh }; 允许发 siginh
type_transition init sshd_exec_t:process sshd; 让域转换成为缺省操作

简单来说,上述语句就是让 init 进程可以执行 sshd 文件,并且新的 sshd 进程的安全上下文是sshd。

策略是用策略语言编写的。用户态策略语言文件一般有多个,其格式是适合用户阅读的文本格式。要让策略起作用,管理员需要用 SELinux 用户态工具将策略文件编译成一个二进制文件, 然后通过 selinuxfs 接口, 将这个二进制文件所表示的策略输入到内核存储空间的策略库中,即图 7-3 中的 Security Server(安全服务器)。最终使用策略的是 SELinux 的钩子函数(hooks),为了提高效率, SELinux 的设计者在安全服务器和钩子函数之间放置了一个缓存——Access Vector Cache。内核代码在系统调用函数中嵌入了对内核安全模块钩子函数的调用, SELinux 的钩子函数会根据策略返回结果。这个返回值会影响系统调用成功与否。图 7-3 简单描述了SELinux 的架构。

强调一下, SELinux 的策略是允许策略,访问控制是白名单机制,没有在策略中定义的操作都是被禁止的,即“法无允许即禁止”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 22:50:37

学术论文翻译翻车重灾区!Perplexity翻译查询功能如何通过引用锚点保留+LaTeX公式智能隔离实现零失真输出(仅限Pro+订阅用户可见的隐藏模式)

更多请点击: https://intelliparadigm.com 第一章:学术论文翻译翻车重灾区的底层归因分析 学术论文翻译失准并非偶然现象,其背后存在系统性语言学、认知科学与工程实践三重张力。当非母语研究者依赖通用大模型或词典式工具进行技术文本转译时…

作者头像 李华
网站建设 2026/5/20 22:49:45

医用包装工厂实践案例及靠谱之选

为您梳理了国内几家有代表性的医用包装工厂实践案例,并附上选择供应商的实用建议,供您参考。🏭 典型医用包装工厂实践案例工厂名称核心产品亮点实践适用场景山东力诺医药包装中硼硅玻璃安瓿瓶、模制瓶🔹 智能制造:部署…

作者头像 李华
网站建设 2026/5/20 22:43:06

终极AEUX插件指南:如何轻松实现设计到动画的无缝转换

终极AEUX插件指南:如何轻松实现设计到动画的无缝转换 【免费下载链接】AEUX Editable After Effects layers from Sketch artboards 项目地址: https://gitcode.com/gh_mirrors/ae/AEUX 想要打破设计软件与动画软件之间的壁垒吗?AEUX插件正是你需…

作者头像 李华
网站建设 2026/5/20 22:42:19

MH2103(兆讯恒达)兼容替代 GD32F103(兆易创新)

MH2103(兆讯恒达)VS GD32F103(兆易创新)参数对比 & Pin‑to‑Pin 兼容性结论先给核心结论:同封装下,MH2103 与 GD32F103 引脚完全兼容、寄存器高度兼容,可直接 Pin‑to‑Pin 替换&#xff1…

作者头像 李华
网站建设 2026/5/20 22:33:03

github收藏网站

github 热门仓库https://trendshift.io/精选整理的使用 RAG、AI 智能体、多智能体团队、MCP、语音智能体等技术构建的 Awesome LLM 应用集合https://github.com/Shubhamsaboo/awesome-llm-apps将 GitHub 代码仓库自动转化为结构化、可阅读、可对话的交互式百科页面https://gith…

作者头像 李华