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