LSM安全模块开发
内核版本:5.4.120
LSM 安全模块的开发主要步骤
- 明确需要的
hook
(所有的hook
都定义在include/linux/lsm_hooks.h
中) - 编写
hook
处理函数(具体来说,hook
是一个函数指针,我们要做的就是编写具体的处理函数) - 关联对应
hook
到上述的hook
处理函数,并添加到security_hook_list
结构体中。(将这个hook
函数指针指向上述的处理函数) - 注册添加了
hook
处理函数的security_hook_list
结构体 - 将指定的安全模块添加到LSM框架中
内核代码整体结构中的必要修改
- 在
security
目录下新建自己的模块主目录security/sec_file
- 在
security/sec_file
目录下新建三个文件,分别是:sec_file.c
( 添加自己的代码逻辑)、Kconfig
(构造内核模块的框架)、Makefile
(用于内核编译) - 修改目录
security
下的Kconfig
、Makefile
文件,将我们自己的模块包含进来。
具体代码结构及内容
security/sec_file/sec_file.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
*sec_file_file_permission 函数的就是hook处理函数
*在这里需要注意的是 sec_file_file_permission 的函数头需要和 include/linux/lsm_hooks.h 文件
*中对应hook的函数头保持一致(在这里就是和 ’file_permission‘ hook的函数头对应)
*/
static int sec_file_file_permission(struct file *file, int mask)
{
// only deal with the file_name which contain '.'
if (strstr(file->f_path.dentry->d_iname, "."))
{
printk(KERN_INFO "[+ xiaolei_test] 'file_name' of the access file is:%s\n",file->f_path.dentry->d_iname);
printk(KERN_INFO "[+ xiaolei_test] 'mask' of the access file is:%d\n",mask);
}
return 0;
}
/*
*LSM_HOOK_INIT 就是将file_permission hook 和 处理函数 sec_file_file_permission 关联起来,并
*添加到 security_hook_list 结构体中
*/
static struct security_hook_list sec_file_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(file_permission,sec_file_file_permission),
};
/*
* 注册添加了hook处理函数的 security_hook_list 结构体
*/
static __init int sec_file_init(void)
{
printk(KERN_ALERT "[+ xiaolei] sec_file: Initializing .!!!!!!]n");
security_add_hooks(sec_file_hooks,ARRAY_SIZE(sec_file_hooks), "sec_file");
return 0;
}
/*
*将指定的安全模块添加到LSM框架中
*这里需要注意 DEFINE_LSM(sec_file) 中的 sec_file 就是指定在LSM安全框架启动过程中要启用的安全模
*块的标识。(LSM安全框架要启动的模块后续在.config 文件需要进行手动修改或者通过 make menuconfig 过程中的配置来进行修改。)
*/
DEFINE_LSM(sec_file) = {
.name = "sec_file",
.init = sec_file_init,
};security/sec_file/Kconfig
1
2
3
4
5
6config SECURITY_FILE #安全模块的标识(用于Kconfig中)
bool "sec_file - LSM" #make menuconfig 界面中显示的模块名称
depends on SECURITY #依赖模块
default y #该安全模块的默认值
help #help 信息
This our lab LSM module.security/sec_file/Makefile
1
2
3obj-$(CONFIG_SECURITY_FILE) := sec_file.o #将对应的模块编译进内核(obj-y 生成 build-in.a)或者编译成第三方模块(obj-m 生成 xxx.ko)
sec_file-y := sec_file.osecurity/Kconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46# SPDX-License-Identifier: GPL-2.0-only
#
# Security configuration
#
menu "Security options"
source "security/keys/Kconfig"
......
source "security/selinux/Kconfig"
source "security/uob/Kconfig"
source "security/sec_file/Kconfig" # 将sec_file 的Kconfig 包含进来
source "security/smack/Kconfig"
source "security/tomoyo/Kconfig"
source "security/apparmor/Kconfig"
source "security/loadpin/Kconfig"
source "security/yama/Kconfig"
source "security/safesetid/Kconfig"
source "security/lockdown/Kconfig"
source "security/integrity/Kconfig"
......
config LSM # 在下面添加对应的模块标识(DEFINE_LSM() 括号中的标识)[这个也可以不添加]
string "Ordered list of enabled LSMs"
default "lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,uob,sec_file" if DEFAULT_SECURITY_SMACK
default "lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,uob,sec_file" if DEFAULT_SECURITY_APPARMOR
default "lockdown,yama,loadpin,safesetid,integrity,tomoyo,uob,sec_file" if DEFAULT_SECURITY_TOMOYO
default "lockdown,yama,loadpin,safesetid,integrity,uob,sec_file" if DEFAULT_SECURITY_DAC
default "lockdown,yama,loadpin,safesetid,integrity,uob,sec_file" if DEFAULT_SECURITY_UOB
default "lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,uob,sec_file"
help
A comma-separated list of LSMs, in initialization order.
Any LSMs left off this list will be ignored. This can be
controlled at boot with the "lsm=" parameter.
If unsure, leave this as the default.
source "security/Kconfig.hardening"
endmenusecurity/Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the kernel security code
#
obj-$(CONFIG_KEYS) += keys/
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
subdir-$(CONFIG_SECURITY_UOB) += uob
subdir-$(CONFIG_SECURITY_FILE) += sec_file #添加模块主目录
subdir-$(CONFIG_SECURITY_SMACK) += smack
subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
subdir-$(CONFIG_SECURITY_YAMA) += yama
subdir-$(CONFIG_SECURITY_LOADPIN) += loadpin
subdir-$(CONFIG_SECURITY_SAFESETID) += safesetid
subdir-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown
# always enable default capabilities
obj-y += commoncap.o
obj-$(CONFIG_MMU) += min_addr.o
# Object file lists
obj-$(CONFIG_SECURITY) += security.o
obj-$(CONFIG_SECURITYFS) += inode.o
obj-$(CONFIG_SECURITY_UOB) += uob/
obj-$(CONFIG_SECURITY_FILE) += sec_file/ #添加对应的编译文件,与sec_file/Makefile中的obj-$(CONFIG_SECURITY_FILE) :=
#sec_file.o 相对应(sec_file)
obj-$(CONFIG_SECURITY_SELINUX) += selinux/
obj-$(CONFIG_SECURITY_SMACK) += smack/
obj-$(CONFIG_AUDIT) += lsm_audit.o
obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/
obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/
obj-$(CONFIG_SECURITY_YAMA) += yama/
obj-$(CONFIG_SECURITY_LOADPIN) += loadpin/
obj-$(CONFIG_SECURITY_SAFESETID) += safesetid/
obj-$(CONFIG_SECURITY_LOCKDOWN_LSM) += lockdown/
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
# Object integrity file lists
subdir-$(CONFIG_INTEGRITY) += integrity
obj-$(CONFIG_INTEGRITY) += integrity/
修改LSM 安全框架启动的安全模块集合的两种方法:
手动修改
linux源代码根目录/.config
文件找到下图中的行,将模块标识手动添加进去(此处的模块标识就是 DEFINE_LSM()中的字符串)
- 通过
make menuconfig
来进行配置在下图配置界面中,进入
security options
子目录确保我们的模块被选中开启
在
Ordered list of enable LSMs
中加上我们的模块标识。
附录
内核打印函数介绍
printk
与
printf
类似,但是printf
运行在用户态,printk
运行在内核态1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17格式:
printk(fmt, <print message>)
其中fmt为printk打印的控制函数,fmt的定义:
没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上)pr_xxx
是内核中对
printk
的封装1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18