开发一个LSM

0、基础

学会使用github获取kernel的更新日志。

1、LSM和IMA概念

首先得到的是LSM的概念,同时还有IMA。LSM的安全内涵可以自定义,因此kernel中可以存在多个LSM模块。IMA独一份,专注于完整性验证。因此,如果不仅仅是“完整性”,那么应该选择LSM。2.6.22内核版本之后开始不再支持模块方式,必须与内核一同编译。

2、LSM版本

LSM从4.2(4.19.110就没有了!!!!)版本开始裁剪掉了原来include/linux/security.h中的security_operations结构,因此下面的代码将无法编译通过:

static struct security_operations geek_ops = {
.name = "geek",
.task_create = task_create_hook,
};

先插入一段可用的代码:

#include<linux/lsm_hooks.h>
#include <linux/security.h>
#include <linux/sysctl.h>
#include <linux/ptrace.h>
#include <linux/prctl.h>
#include <linux/ratelimit.h>
#include <linux/workqueue.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/dcache.h>
#include <linux/path.h>

int test_file_permission(struct file *file, int mask)
{
    char *name = file->f_path.dentry->d_name.name;
    if(!strcmp(name, "test.txt"))
    {
        file->f_flags |= O_RDONLY;
        printk("========== you can have your control code here!\n");
    }
    return 0;
}


static struct security_hook_list test_security_ops[] = {
    LSM_HOOK_INIT(file_permission, test_file_permission),
};

static __init test_init(void)
{
    printk("========== enter test init!\n");
    security_add_hooks(test_security_ops, ARRAY_SIZE(test_security_ops), "demo");
}

security_initcall(test_init);

新的hooks定义和使用在include/linux/lsm_security.h中。从示例代码中可以看到,新的方式更加简洁。
版本变更信息可以参考:

commit b1d9e6b0646d0e5ee5d9050bd236b6c65d66faef
Author: Casey Schaufler <casey@schaufler-ca.com>
Date: Sat May 2 15:11:42 2015 -0700

LSM: Switch to lists of hooks

Instead of using a vector of security operations
with explicit, special case stacking of the capability
and yama hooks use lists of hooks with capability and
yama hooks included as appropriate.

The security_operations structure is no longer required.
Instead, there is a union of the function pointers that
allows all the hooks lists to use a common mechanism for
list management while retaining typing. Each module
supplies an array describing the hooks it provides instead
of a sparsely populated security_operations structure.
The description includes the element that gets put on
the hook list, avoiding the issues surrounding individual
element allocation.

The method for registering security modules is changed to
reflect the information available. The method for removing
a module, currently only used by SELinux, has also changed.
It should be generic now, however if there are potential
race conditions based on ordering of hook removal that needs
to be addressed by the calling module.

The security hooks are called from the lists and the first
failure is returned.

3、分类的hooks

这里大概看一下,有了概念,就去直接阅读lsm_hooks.h中的注释即可,最直接有效。

我想要控制运行进程,需要找到对应的hooks以及如何如何使用它们。
首先,需要一些基础知识:

security.h中定义了些结构(kernel source 4.19.109)

struct linux_binprm;
struct cred;
struct rlimit;
struct siginfo;
struct sembuf;
struct kern_ipc_perm;
struct audit_context;
struct super_block;
struct inode;
struct dentry;
struct file;
struct vfsmount;
struct path;
struct qstr;
struct iattr;
struct fown_struct;
struct file_operations;
struct msg_msg;
struct xattr;
struct xfrm_sec_ctx;
struct mm_struct;

它们具体是什么含义:


1. struct linux_binprm; // 程序
2. struct cred; // 进程相关数据结构
3. struct rlimit; // 进程相关数据结构
4. struct siginfo; // 信号
5. struct sembuf; // 信号量
6. struct kern_ipc_perm; // Semaphore信号,共享内存段,或者消息队列
7. struct audit_context; // 审计
8. struct super_block; // 文件系统
9. struct inode; // 管道,文件,或者Socket套接字
10. struct dentry; // 与文件相关的目录项对象,指向相关目录项的指针
11. struct file; // 文件系统相关数据结构
12. struct vfsmount; // 文件系统相关数据结构
13. struct path; // 文件路径
14. struct qstr; // 是一个内核字符串的包装器,它存储了实际的char*字符串以及字符串长度和散列值,这使得更容易处理查找工作。 要注意的是,这里并不存储绝对路径,而是只有路径的最后一个分量,例如对/usr/bin/emacs只存储emacs,因为在linux中,路径信息隐含在了dentry层次链表结构中了 
15. struct iattr; // inode相关?
16. struct fown_struct; // 该结构的作用是通过信号进行I/O时间通知的数据
17. struct file_operations; // 指向文件操作表的指针, 定义在linux/include/linux/fs.h中,其中包含着与文件关联的操作
18. struct msg_msg; // 单个的消息
19. struct xattr; // 文件系统扩展属性
20. struct xfrm_sec_ctx; //  安全上下文, 加密时使用。解密呢?
21. struct mm_struct; // 进程地址空间

以上是中文的简单解释,更为确定的解释从代码struct定义处的注释可以知道:
1、struct linux_binprm

/*
 * This structure is used to hold the arguments that are used when loading binaries.
 */

这个结构用于控制二进制加载时所用的参数。具体是什么意思呢?
4、如何开始开发
回到上面的例子,

` LSM_HOOK_INIT(file_permission, test_file_permission),`

从头文件lsm_hooks.h找到LSM_HOOK_INIT

#define LSM_HOOK_INIT(HEAD, HOOK) \
    { .head = &security_hook_heads.HEAD, .hook = { .HEAD = HOOK } }

然后是 security_hook_heads 的定义,可以看到一大堆的东西,根据前文结果中定义的关键字bprm“程序”找到相关的

    struct hlist_head bprm_set_creds;
    struct hlist_head bprm_check_security;
    struct hlist_head bprm_committing_creds;
    struct hlist_head bprm_committed_creds;

cred 和 task 是不是呢?

    struct hlist_head cred_alloc_blank;
    struct hlist_head cred_free;
    struct hlist_head cred_prepare;
    struct hlist_head cred_transfer;
    struct hlist_head cred_getsecid;

5 钩子的选取

以上,通过lsm_hooks.h,查看注释部分对钩子的分类,就可以大致判断自己需要使用哪个钩子了。首先选择的是 bprm_check_security, 因为我想要捕获deb安装过程。因为暂时还不知道怎么自己打包一个deb包,所以先从a.out这样的绿色可执行程序开始。通过printk打印linux_binprm结构中的filename,可以看到当a.out被执行时, bprm_check_security捕获了该动作,filename清楚地打印出了a.out的名字。
随后,在a.out向下调用b.so的情形下,发现b.so被调用的点并不会被捕获。考虑应该可以通过监控file类实现。


6 文件扩展

同步进行的其它工作:
想让用户太操作a.out的时候,将其stat.st_ino,即inode号通知给内核模块,让其一步定位到对应的file结构,以进一步对其添加EA文件扩展内容。
找到两种办法,一个通过netlink传递inode给内核,内核根据inode,使用namei提供的函数反向查找inode结构……发现不好做,需要像根据一个叶子节点反查整棵树一样。
将传递inode改为传递filename绝对路径名给内核,问题依旧。
后来发现用户态即可通过setxattr接口实现,网上找到一个有用但很扯的例子:

void testset(){
    char key[7] = {'u','s','e','r','.','#','\0'};
    char value[2] = {'#','\0'};
    int i, ret;
    for(i = 0; i < 10; i++){
        key[5] = value[0] = '0'+i;
        ret = setxattr("test", key, value, 2, 0);
    }
}

以上key和value中的‘#’、‘\0’让人费解,又以为key是“security”、“user”这样的赋值方式,结果走了弯路。其实简单的方法是:

char key[] = "user.test";
char value[] = "123";

以上通过getxattr可以确认键值对是:

<user.test, 123>

bingo!

对EA的安全性进行了摸底确认,root创建的EA内容,copy到另一处后,EA内容消失。mv则会保留。被root添加的EA,其他用户无法删除或修改,但可以读取。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容