Linux 内核安全模块学习总结
生活随笔
收集整理的這篇文章主要介紹了
Linux 内核安全模块学习总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Linux安全模塊(LSM)
LSM是Linux Secrity Module的簡(jiǎn)稱,即linux安全模塊。其是一種輕量級(jí)通用訪問控制框架,適合于多種訪問控制模型在它上面以內(nèi)核可加載模塊的形實(shí)現(xiàn)。用
戶可以根據(jù)自己的需求選擇合適的安全模塊加載到內(nèi)核上實(shí)現(xiàn)。
LSM設(shè)計(jì)思想:
LSM的設(shè)計(jì)思想:在最少改變內(nèi)核代碼的情況下,提供一個(gè)能夠成功實(shí)現(xiàn)強(qiáng)制訪
問控制模塊需要的結(jié)構(gòu)或者接口。LSM避免了利用如在systrace系統(tǒng)調(diào)用中的出
現(xiàn)過的系統(tǒng)調(diào)用干預(yù),因?yàn)樗荒軘U(kuò)展到多處理器內(nèi)核,并且它受制于參數(shù)替換
攻擊。還有LSM在設(shè)計(jì)時(shí)做了兩點(diǎn)考慮:對(duì)不使用的人來說盡量少引入麻煩,對(duì)
使用的人來說要帶來效率。以Linus Torvalds為代表的內(nèi)核開發(fā)人員對(duì)Linux安
全模塊(LSM)提出了三點(diǎn)要求:
1、真正的通用,當(dāng)使用一個(gè)不同的安全模型的時(shí)候,只需要加載一個(gè)不同的內(nèi)
核模塊。
2、概念上簡(jiǎn)單,對(duì)Linux內(nèi)核影響最小,高效,并且。
3、能夠支持現(xiàn)存的POSIX.1e capabilities邏輯,作為一個(gè)可選的安全模塊。
還有,針對(duì)linux上提出的各種不同的Linux安全增強(qiáng)系統(tǒng)對(duì)Linux安全模塊(LSM
)提出的要求是:能夠允許他們以可加載內(nèi)核模塊的形式重新實(shí)現(xiàn)其安全功能,
并且不會(huì)在安全性方面帶來明顯的損失,也不會(huì)帶來額外的系統(tǒng)開銷。
LSM框架結(jié)構(gòu):
LSM框架主要由五部分構(gòu)成:
1、在特定的內(nèi)核數(shù)據(jù)結(jié)構(gòu)中加入安全域。
2、在內(nèi)核源代碼中不同的關(guān)鍵點(diǎn)插入對(duì)安全鉤子函數(shù)的調(diào)用。
3、加入一個(gè)通用的安全系統(tǒng)調(diào)用。
4、提供了函數(shù)允許內(nèi)核模塊注冊(cè)為安全模塊或者注銷。
5、5、將capabilities邏輯的大部分移植為一個(gè)可選的安全模塊。
安全域是一個(gè)void*類型的指針,它使得安全模塊把安全信息和內(nèi)核內(nèi)部對(duì)象聯(lián)
系起來。下面列出被修改加入了安全域的內(nèi)核數(shù)據(jù)結(jié)構(gòu),以及各自所代表的內(nèi)核
內(nèi)部對(duì)象:
task_struct結(jié)構(gòu):代表任務(wù)(進(jìn)程)
linux_binprm結(jié)構(gòu):代表程序
super_block結(jié)構(gòu):代表文件系統(tǒng)
inode結(jié)構(gòu):代表管道,文件,或者Socket套接字
file結(jié)構(gòu):代表打開的文件
sk_buff結(jié)構(gòu):代表網(wǎng)絡(luò)緩沖區(qū)(包)
net_device結(jié)構(gòu):代表網(wǎng)絡(luò)設(shè)備
kern_ipc_perm結(jié)構(gòu):代表Semaphore信號(hào),共享內(nèi)存段,或者消息隊(duì)列
msg_msg:代表單個(gè)的消息
Linux安全模塊(LSM)提供了兩類對(duì)安全鉤子函數(shù)的調(diào)用:一類管理內(nèi)核對(duì)象的
安全域,另一類仲裁對(duì)這些內(nèi)核對(duì)象的訪問。對(duì)安全鉤子函數(shù)的調(diào)用通過鉤子來
實(shí)現(xiàn),鉤子是全局表security_ops中的函數(shù)指針,這個(gè)全局表的類型是
security_operations結(jié)構(gòu),這個(gè)結(jié)構(gòu)定義在include/linux/security.h這個(gè)頭
文件中。
LSM接口的核心是security_ops,當(dāng)系統(tǒng)啟動(dòng)時(shí),他們被初始化為傳統(tǒng)的DAC策略
。傳統(tǒng)DAC訪問控制是指控制系統(tǒng)中的主體(如進(jìn)程)對(duì)系統(tǒng)中的客體(如文件
目錄、文件)的訪問(讀、寫和執(zhí)行等)。自主訪問控制DAC 是指主體(進(jìn)程,
用戶)對(duì)客體(文件、目錄、特殊設(shè)備文件、IPC等)的訪問權(quán)限是由客體的屬
主或超級(jí)用戶決定的,而且此權(quán)限一旦確定,將作為以后判斷主體對(duì)客體是否有
訪問權(quán)限的依據(jù)。
在加載安全模塊時(shí),我們必需先對(duì)模塊進(jìn)行注冊(cè),我們可以使用
register_security()函數(shù)向LSM注冊(cè)一個(gè)安全模塊。在我們的模塊被加載成
功后,就可以進(jìn)行訪問控制操作。如果此時(shí)還有一個(gè)安全模塊要使用
register_security()函數(shù)進(jìn)行加載,則會(huì)出現(xiàn)錯(cuò)誤,直到使用
unregister_security()函數(shù)向框架注銷后,下一個(gè)模塊才可以載入。當(dāng)然LS
M還提供了mod_reg_security()函數(shù)和mod_unreg_security()函數(shù),可以連續(xù)注
冊(cè)多個(gè)安全模塊。如果有其他后來的模塊需要載入,可以通過mod_reg_security
()向第一個(gè)模塊注冊(cè),形成支持不同策略的模塊棧。
注:以上出現(xiàn)的函數(shù)均基于2.6.22以前的版本,對(duì)于后續(xù)的版本,出現(xiàn)了
register_security()函數(shù)未被導(dǎo)出或者取消掉了unregister_security()函數(shù)。
LSM執(zhí)行過程:
根據(jù)下圖的執(zhí)行步驟:用戶在執(zhí)行系統(tǒng)調(diào)用時(shí),先通過原有的內(nèi)核接口依次執(zhí)行
功能性的錯(cuò)誤檢查,接著進(jìn)行傳統(tǒng)的DAC檢查,并在即將訪問內(nèi)核的內(nèi)部對(duì)象之
前,通過LSM鉤子函數(shù)調(diào)用LSM。LSM再調(diào)用具體的訪問控制策略來決定訪問的合
法性。圖三顯示了LSM鉤子的調(diào)用:
圖三:基于LSM的內(nèi)核對(duì)象訪問過程
Lilinux安全模塊(LSM)主要支持"限制型"的訪問控制決策:當(dāng)Linux內(nèi)核授予
文件或目錄訪問權(quán)限時(shí),Linux安全模塊(LSM)可能會(huì)拒絕,而當(dāng) Linux內(nèi)核拒
絕訪問時(shí),可以跳過LSM。
========
使用LSM實(shí)現(xiàn)自己的訪問控制
首先對(duì)LSM 進(jìn)行簡(jiǎn)單介紹。雖然linux下的各位基本都知道一些,但是還要羅嗦
一下。
LSM中文全稱是linux安全模塊。英文全稱:linux security module.
LSM是一種輕量級(jí)、通用的訪問控制框架,適合多種訪問控制模型以內(nèi)核模塊的
形式實(shí)現(xiàn)。其特點(diǎn)是通用、簡(jiǎn)單、高效、支持POSIX。1e能力機(jī)制。
LSM的架構(gòu)圖如下:
通過系統(tǒng)調(diào)用進(jìn)入內(nèi)核之后,系統(tǒng)首先進(jìn)行傳統(tǒng)的權(quán)限檢查(傳統(tǒng)權(quán)限檢查主要
是基于用戶的,用戶通過驗(yàn)證之后就可以訪問資源),通過之后才會(huì)進(jìn)行強(qiáng)制訪
問控制。(強(qiáng)制訪問控制是不允許主體干涉的一種訪問控制,其采用安全標(biāo)識(shí)、
信息分級(jí)等信息敏感性進(jìn)行訪問控制。并且通過比較主體的級(jí)別和資源的敏感性
來確定是否允許訪問。比如說系統(tǒng)設(shè)置A用戶不允許訪問文件B,即便A是文件B的
所有者,訪問也是受限制的。)從圖上看來,LSM實(shí)現(xiàn)訪問控制主要通過安全模
塊的鉤子函數(shù)實(shí)現(xiàn)。
LSM框架主要由五部分組成:這個(gè)網(wǎng)上資料很多。
在關(guān)鍵的特定內(nèi)核數(shù)據(jù)結(jié)構(gòu)中加入了安全域;
在內(nèi)核源碼中不同的關(guān)鍵點(diǎn)處插入對(duì)安全鉤子函數(shù)的調(diào)用;
提供了一個(gè)通用的安全系統(tǒng)調(diào)用;
提供了注冊(cè)和注銷函數(shù),使得訪問控制策略可以以內(nèi)核模塊方式實(shí)現(xiàn);
將capabilities邏輯的大部分功能移植為一個(gè)可選的安全模塊。
我們這里重點(diǎn)結(jié)合源碼對(duì)LSM框架進(jìn)行解釋。我使用的源碼是3.5.4
首先介紹安全域字段,它是一個(gè)空類型的指針,在內(nèi)核中的很多內(nèi)核結(jié)構(gòu)中都存
在,比如inode、superblock、dentry、file等等。類型字段為void *?
security;
那么安全域怎么和安全模塊中的信息關(guān)聯(lián)起來?
當(dāng)安全模塊加載之后,安全域中的指針便指向安全模塊中的安全信息。這里以
selinux為例進(jìn)行介紹。
內(nèi)核里面security/selinux/include/objsec.h中定義了不同對(duì)象的安全信息,
格式為XXX_security_strut.
上面的文件的安全信息里面包含打開文件描述符時(shí)的安全I(xiàn)D、文件所有者的安全
ID等等。
要聯(lián)系安全模塊中安全信息和安全域需要幾個(gè)控制鉤子函數(shù)。這些鉤子函數(shù)實(shí)現(xiàn)
了對(duì)內(nèi)核關(guān)鍵信息的設(shè)置和管理。這里主要介紹alloc_security、
free_security。
selinux里面通過實(shí)現(xiàn)安全信息空間分配實(shí)現(xiàn)關(guān)聯(lián)。比如以文件安全信息為例
這里分配空間成功之后,通過file->f_security = fsec實(shí)現(xiàn)了關(guān)聯(lián)。
撤銷關(guān)聯(lián)是在安全模塊卸載之后調(diào)用file_free_security.
這里具體通過設(shè)置file->f_secrity為NULL,然后釋放安全信息結(jié)構(gòu)實(shí)現(xiàn)。
現(xiàn)在來看看內(nèi)核如何實(shí)現(xiàn)selinux的訪問控制。這里主要就是實(shí)現(xiàn)LSM里面的鉤子
函數(shù)了。LSM里面給出了結(jié)構(gòu)體security_operations,里面給出了很多鉤子函數(shù)
,實(shí)現(xiàn)了相關(guān)鉤子函數(shù)就可以實(shí)現(xiàn)訪問控制了。
上面的函數(shù)就實(shí)現(xiàn)了file_permission鉤子函數(shù)。可以看下inode結(jié)構(gòu)體的獲得,
感受內(nèi)核是通過文件->目錄項(xiàng)->inode。該函數(shù)主要實(shí)現(xiàn)自己的訪問控制策略就
OK 了。
哪selinux來說,在獲得文件安全I(xiàn)D之后,主要對(duì)掩碼和文件打開時(shí)相關(guān)的安全
信息進(jìn)行檢測(cè),符合就通過訪問控制。
selinux基本實(shí)現(xiàn)了LSM里面的所有鉤子函數(shù),待鉤子函數(shù)實(shí)現(xiàn)后,對(duì)LSM里面鉤
子域進(jìn)行填充就OK了。
做完以上這些還需要注冊(cè)安全模塊到LSM,這里注冊(cè)和注銷使用了
register_security和unregister_security。
比如selinux在注冊(cè)時(shí)使用語(yǔ)句register_security(&selinux_ops)實(shí)現(xiàn)。
接下來通過上面的分析我們可以實(shí)現(xiàn)簡(jiǎn)單的基于LSM的訪問控制。
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <linux/fcntl.h>
#include <linux/uaccess.h>
#include <linux/file.h>
#include <linux/namei.h>
static int lsm_test_file_permission(struct file *file,int mask)
{
? ? int path=0;
? ? struct file *filp;
? ? struct nameidata nd;
? ? path = path_lookup(FILENAME,LOOKUP_FOLLOW,&nd);
? ??
? ? if(!mask)
? ? ? ? ? ? return 0;
? ? if(path)
? ? {
? ? ? ? printk("lookup file failed!\n");
? ? ? ? return -1;
? ? }
? ? filp = filp_open("/home/yuyunchao/code/sb.c",O_RDONLY,0);
? ? {
? ? printk("open failed!\n");
? ? }
? ? return 0;
}
static struct security_operations lsm_test_security_ops = {
? ? .file_permission = lsm_test_file_permission,
};
static int __init lsm_file_init(void)
{ ? ?
? ? if(register_security(&lsm_test_security_ops)){
? ? ? ? printk("register error ..........\n");
? ? ? ? return -1;
? ? }
? ?
? ? printk("lsm_file init..\n ");
? ? return 0;
}
static void __exit lsm_file_exit(void)
{
? ? if(unregister_security(&lsm_test_security_ops)){
? ? ? ? printk("unregister error................\n");
? ? ? ? return ;
? ? }
? ? printk("module exit.......\n");
}
MODULE_LICENSE("GPL");
module_init(lsm_file_init);
module_exit(lsm_file_exit);
========
LSM(Linux Security Module)應(yīng)用方法(簡(jiǎn)單例子)
LSM在內(nèi)核中很多地方已經(jīng)插入了hook函數(shù),并且在security.c函數(shù)中聲明了
security_ops結(jié)構(gòu),要實(shí)現(xiàn)你自己的安全模塊,只需要定義你自己的struct?
security_operations,并且用register_security注冊(cè)即可,下面舉個(gè)簡(jiǎn)單例子
:
test.c代碼如下:
/*
* Test Linux Security Module
*
* Author: penghuan <penghuanmail@126.com>
*
* Copyright (C) 2010 UbuntuKylin, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2, as
* published by the Free Software Foundation.
*
*/
#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_operations test_security_ops = {
? ? ? ? .name = ? ? ? ? ? ? ? ? "test",
? ? ? ? .file_permission = ? ? ?test_file_permission,
};
static __init int test_init(void)
{
? ? ? ? printk("enter test init!\n");
? ? ? ? printk(KERN_INFO "Test: becoming......\n")
? ? ? ? if (register_security(&test_security_ops))
? ? ? ? ? ? ? ? panic("Test: kernel registration failed.\n");
? ? ? ? return 0;
}
security_initcall(test_init);
將該文件以模塊的形式放到security/下編譯進(jìn)內(nèi)核,啟用新的內(nèi)核后,當(dāng)你操
作文件test.txt時(shí),通過dmesg命令就能再終端看到”you can have your?
control code here!“輸出
所以一般的做法是:定義你自己的struct security_operations,實(shí)現(xiàn)你自己的
hook函數(shù),具體有哪些hook函數(shù)可以查詢include/linux/security.h文件,然后
調(diào)用register_security來用你的test_security_ops初始化全局的security_ops
指針
樓主,我剛開始研究LSM,但網(wǎng)上資料太少,您這個(gè)代碼,我編譯成ko文件老是
有警告,并且insmod時(shí),說Unknown symbol register_security。我最近看了看
內(nèi)核模塊變成,沒有對(duì)內(nèi)核進(jìn)行太深入的了解。不知能否把LSM的實(shí)驗(yàn)步驟給出
的再詳細(xì)點(diǎn),謝謝。
你需要把代碼編進(jìn)內(nèi)核
是需要把那段源碼拷到內(nèi)核目錄下,然后重新編譯內(nèi)核?。。沒有不編譯內(nèi)核的
方法嗎?。。直接按照模塊進(jìn)行編譯。另外那個(gè)test.txt放在哪個(gè)文件夾里?。
是需要把那段源碼拷到內(nèi)核目錄下,然后重新編譯內(nèi)核?。。沒有不編譯內(nèi)核的
方法嗎?。。直接按照模塊進(jìn)行 ...
是的,你去網(wǎng)上找下怎么把模塊編進(jìn)內(nèi)核,lsm模塊不能以模塊方式加載,涉及
安全;test.txt是測(cè)試文件,當(dāng)你把代碼編進(jìn)內(nèi)核后,用新內(nèi)核啟動(dòng),然后操作
test.txt文件,就會(huì)有輸出,test.txt隨便放哪里
樓主,您好,我剛開始學(xué)習(xí)lsm模塊,把您的模塊編譯進(jìn)內(nèi)核,新的內(nèi)核加載后
,register_security總是失敗,請(qǐng)問下可能是什么原因?qū)е碌摹N业膬?nèi)核版本
是3.13.11。
register_security的返回值是-11
========
LSM在Linux中的實(shí)現(xiàn)方式
LSM(Linux Secure Model)一種輕量級(jí)訪問控制機(jī)制.其實(shí)現(xiàn)方式有如在系統(tǒng)調(diào)用中加入一個(gè)后門....
方式如下:
static struct file *__dentry_open(struct dentry *dentry, struct?
vfsmount *mnt,
? ? ?struct file *f,
? ? ?int (*open)(struct inode *, struct file *),
? ? ?const struct cred *cred)
{
?struct inode *inode;
?int error;
?...............................................................
?error = security_dentry_open(f, cred); ? //LSM機(jī)制實(shí)現(xiàn)方式,在此加入了
一個(gè)LSM函數(shù).
?
//security_dentry_open的實(shí)現(xiàn)如下,相當(dāng)于一個(gè)接口,對(duì)一個(gè)函數(shù)指針再
//封裝一下.
//只返回是與否,這樣的控制信息.
?if (error)
? goto cleanup_all;
?................................................................
?return f;
cleanup_all:
?.................................................................
?return ERR_PTR(error);
}
//========簡(jiǎn)單封裝一個(gè)指針結(jié)構(gòu)體===========================
int security_dentry_open(struct file *file, const struct cred *cred)
{
?int ret;
?ret = security_ops->dentry_open(file, cred);
?if (ret)
? return ret;
?return fsnotify_perm(file, MAY_OPEN);
}
========
利用LSM實(shí)現(xiàn)更安全的linux
LSM的全稱是Linux Security Modules,它是linux內(nèi)核中用來支持更靈活的
安全策略的一個(gè)底層框架,雖然聽起來比較復(fù)雜,但是可以就把它理解成一組安
插在linux內(nèi)核的鉤子函數(shù)和一些預(yù)留的被稱為安全域的數(shù)據(jù)結(jié)構(gòu),下面先說說
這個(gè)框架的由來吧。
linux本身的機(jī)制就保證了linux擁有更好的安全機(jī)制,但是在這個(gè)機(jī)制下面
,還是隱藏了許多的問題:
?
1、權(quán)限粒度太大。用過linux的人應(yīng)該對(duì)0644這樣的訪問權(quán)限設(shè)置不陌生,
它對(duì)能夠操作這個(gè)文件的用戶做了限制,但是這個(gè)只是限制到了組,而沒有更進(jìn)
一步的細(xì)分,當(dāng)然,如果LSM只是用來限制這個(gè)的話,那么也就太沒意思了,因
為實(shí)現(xiàn)文件更細(xì)的控制粒度,ACL就能夠很出色的完成,順便提一下,ACL有一個(gè)
分配的限制,如果哪位朋友需要用ACL進(jìn)行粒度更細(xì)的訪問權(quán)限控制的話,可能
需要注意一下這方面的東西。
2、root用戶的權(quán)限太大。在linux中,root用戶就是至高無(wú)上的,他擁有對(duì)
機(jī)器的完全控制權(quán)限,可以做他想做的一切事情。但是很多時(shí)候,我們可能并不
希望有root有這么大的權(quán)限,比如在現(xiàn)在比較流行的云存儲(chǔ)中,用戶肯定不希望
服務(wù)提供商能夠隨意訪問我們的文件,那么這個(gè)時(shí)候,就需要對(duì)root用戶進(jìn)行一
定的設(shè)置了。
?
由于這些問題的存在,所以出現(xiàn)了像SE Linux(Securiy Enhanced Linux )
這樣的增強(qiáng)補(bǔ)丁。但是每個(gè)系統(tǒng)對(duì)于具體安全細(xì)節(jié)的控制不盡相同, 所以Linus?
Tovalds 提出應(yīng)該要有一個(gè) Linux 內(nèi)核所能接受的安全框架來支持這些安全策
略,這個(gè)安全框架應(yīng)該提供包含內(nèi)核數(shù)據(jù)結(jié)構(gòu)中的透明安全域以及用來控制、維
護(hù)安全域操作的安全鉤子,于是就有了LSM。
?
LSM在內(nèi)核中的位置,可以用下圖來表示:
當(dāng)用戶態(tài)程序調(diào)用某些操作系統(tǒng)提供的函數(shù)的時(shí)候,比如read()函數(shù),其會(huì)
對(duì)應(yīng)于內(nèi)核中的一個(gè)系統(tǒng)調(diào)用,然后該首先會(huì)進(jìn)行一些常規(guī)的錯(cuò)誤檢測(cè),接著進(jìn)
行DAC(Discretionary Access Control)檢測(cè),再接著它會(huì)進(jìn)行LSM檢測(cè)。從上
圖中能夠看出來,LSM其實(shí)是一個(gè)非常底層的安全策略框架,利用LSM,可以接管
所有的系統(tǒng)調(diào)用,這樣,我們就能對(duì)包括root在內(nèi)的所有用戶的權(quán)限進(jìn)行控制,
并且實(shí)現(xiàn)粒度更細(xì)的訪問權(quán)限控制。
?
當(dāng)系統(tǒng)初始化的時(shí)候,LSM就是一個(gè)空的框架,它不提供任何的檢測(cè),其所
做的全部工作幾乎就是返回0,當(dāng)然,有些不帶返回值的函數(shù)除外。而我們則可
以針對(duì)自己特定的需求來編寫LSM,然后將我們編寫的LSM鉤子函數(shù),通過其數(shù)據(jù)
結(jié)構(gòu)struct security_operations注冊(cè)到系統(tǒng)中去,這樣,我們的LSM檢測(cè)就開
始起作用了。
?
在接下來的文章中,會(huì)通過項(xiàng)目中的一個(gè)部分——限制root用戶對(duì)某些文件
的訪問權(quán)限來更具體的說明LSM這個(gè)框架,
========
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的Linux 内核安全模块学习总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java设计模式理论知识要点总结
- 下一篇: opencv角点检测学习总结