從頭開始生成 SELinux

發表于:2007-05-24來源:作者:點擊數: 標簽:從頭開始SELinux生成
SELinux 是美國國家 安全 局對于強制訪問控制的實現,是 Linux 上最杰出的新安全子系統。SELinux 默認安裝在 Fedora 和 Red Hat Enterprise Linux 上,也可以作為其他發行版上容易安裝的包得到。本文將向您展示如何手工轉換一個非 SELinux 的系統,目的是展示
SELinux 是美國國家安全局對于強制訪問控制的實現,是 Linux® 上最杰出的新安全子系統。SELinux 默認安裝在 Fedora 和 Red Hat Enterprise Linux 上,也可以作為其他發行版上容易安裝的包得到。本文將向您展示如何手工轉換一個非 SELinux 的系統,目的是展示 SELinux 是如何集成到系統中的。

簡介

SELinux 是 2.6 版本的 Linux 內核中提供的強制訪問控制 (MAC)系統。對于目前可用的 Linux 安全模塊來說,SELinux 是功能最全面,而且測試最充分的,它是在 20 年的 MAC 研究基礎上建立的。SELinux 在類型強制服務器中合并了多級安全性或一種可選的多類策略,并采用了基于角色的訪問控制概念。有關這些主題的更多信息的鏈接,請參見本文后面的 參考資料 部分。

大部分使用 SELinux 的人使用的都是 SELinux 就緒的發行版,例如 Fedora、Red Hat Enterprise Linux (RHEL)、Debian 或 Gentoo。它們都是在內核中啟用 SELinux 的,并且提供一個可定制的安全策略,還提供很多用戶層的庫和工具,它們都可以使用 SELinux 的功能。

如果您與很多用戶一樣希望讓系統與以前一樣工作,但是要求安全性更好一些,那么可以通過使用一些熟悉的應用程序或者通過使用高級語言編寫安全策略來查詢和操作 SELinux。然而,在出現問題時 —— 例如內核和用戶空間的內容不同步 —— 這些方法就不夠了。另外,這些方法還可能會干擾 UNIX® 工程師理解 SELinux 實際上是如何工作的。最后,工程師和安全社區應該明白除了目前發行版所使用的方法之外,還有其他一些方法可以使用 SELinux。

在本文中,我們將學習如何將一個最初根本不能支持 SELinux 的系統轉換成一個強制使用 SELinux 的系統。我們還將學習如何強制采用一些安全訪問策略。





回頁首


前提條件

要開始學習本文,您需要:

  • QEMU,一個免費且易于使用的處理器模擬器。這是一種很好的體驗新內核或系統映像的方法,而不會對真實系統造成任何損壞。我們可以從 QEMU 下載頁面 下載 QEMU。
  • Gentoo,一個基于源代碼的 Linux 發行版。Gentoo 對于本練習來說非常理想,因為我們可以在一個運行的系統上安裝 Gentoo,而不用管發行版是什么。我們可以在 Gentoo 下載頁面 找到最新的版本。

輸入下面的命令,創建一個磁盤映像文件:

qemu-img create -f raw gentoo.img 2G

下一個步驟是啟動 QEMU 來對裸磁盤映像文件進行分區,并格式化一個分區。這需要某種 Linux 引導 CD。Knoppix 可以實現這種功能,Gentoo liveCD 也可以實現這種功能。我們可以從下面的地址下載 Gentoo liveCD:

wget ftp://ftp.gtlib.cc.gatech.edu/pub/gentoo/releases/x86/current/installcd/install-x86-minimal-2006.0.iso

為了將來引用方便 —— 少輸入幾個字符 —— 您可能會希望對這個映像文件重新命名:

mv install-x86-minimal-2005.1.iso gentoo.iso

下面的命令會通知 QEMU 使用 gentoo.iso 作為自己的 CD,它使用 gentoo.img 作為自己的硬盤,并從 CDROM 開始引導:

qemu -hda gentoo.img -cdrom gentoo.iso -boot d

對于默認內核來說,我們只需要按回車鍵即可。然后輸入下面的內容對磁盤映像文件進行分區:


清單 1. 對磁盤映像文件進行分區
fdisk /dev/hda
            n
            p
            1
            (return)
            w
            

以上命令會創建一個新 (n) 主 (p) 分區,它從塊 1 (1) 開始,到默認的末尾塊(文件系統上的最后一個塊)結束。然后將新的分區表寫入 (w) 磁盤映像文件。

現在,我們將返回到 QEMU 中的 shell 提示符?,F在輸入:

mksf.ext2 /dev/hda1

為了給 udev 一個機會來創建設備,我們可能需要執行這個命令兩次。然后,通過輸入下面的命令關機:

poweroff

這會返回真實系統的 shell。如果沒有返回,或掛起了很長時間,請按 Ctrl-c 鍵結束。

下一個步驟是將基本的發行版安裝到磁盤映像文件上。Gentoo 非常適合本練習的原因是我們可以下載并提取出一個 “步驟 3” 映像文件,這樣我們就可以獲得一個功能完備的 Gentoo 系統。我們應該要找一個本地映像站點來下載一個步驟 3 的 tarball。如果您離 Sandia National Laboratories 很近,就可以使用下面這個示例站點:

wget ftp://mirror.iawnet.sandia.gov/pub/gentoo/releases/x86/current/stages/stage3-x86-2006.0.tar.bz2

這個文件包含了一個完整 Gentoo 系統的壓縮文件。要將這個系統提取到我們的磁盤映像文件上,首先要將磁盤映像文件掛載到系統中。下面這個命令用來掛載這個空文件系統,并將 tarball 展開到這個磁盤映像上。


清單 2. 將 Gentoo tarball 展開到磁盤映像上
su  (give root password)
            ORIG=`pwd`
            mount -oloop,offset=32256 gentoo.img /mnt
            cd /mnt
            tar jxf $ORIG/stage3-x86-2005.1.tar.bz2
            

當這個映像掛載到系統上時,需要注意幾個基本的問題。/etc/fstab 文件告訴系統要將文件系統掛載到什么地方。對于這個簡單的系統來說,不需要引導或交換項。下面的命令用來刪除這些設置,并為根分區插入一個正確的項。它還會為 root 用戶設置密碼。請確保在運行 passwd 命令時,選擇一個可以記住的密碼。安全性對于這個玩具系統來說不是什么關鍵,因此使用 “password” 作為密碼就可以了。


清單 3. 系統基本設置
mv /mnt/etc/fstab /mnt/etc/fstab.orig
            sed -e '/[BR]OOT/d' -e '/SWAP/d' /mnt/etc/fstab.orig >             /mnt/etc/fstab
            cat >> /mnt/etc/fstab << EOF
            /dev/hda1 / ext2 noatime 0 1
            EOF
            chroot /mnt
            passwd
            exit
            cd $ORIG
            umount /mnt
            

要啟動 QEMU 映像文件,就必須使用內核?,F在我們可以啟用 SELinux 的支持來編譯 Linux 內核了,盡管您可能并不知道自己正在使用 SELinux。從 kernel.org 下載 linux-2.6.14.tar.bz2(或更新版本)的一個拷貝,并將其解壓:

wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.14.tar.bz2
tar jxf Linux-2.6.14.tar.bz2

然后,切換到 Linux-2.6.14 目錄,并對內核進行配置,如下所示:

cd linux-2.6.14
make defconfig
make menuconfig

確保至少啟用以下選項:


清單 4. 內核 .config 文件節選
CONFIG_EXT2_FS=y
            CONFIG_EXT2_FS_XATTR=y
            CONFIG_EXT2_FS_SECURITY=y
            CONFIG_SECURITY=y
            CONFIG_SECURITY_CAPABILITIES=y
            CONFIG_SECURITY_SELINUX=y
            CONFIG_SECURITY_SELINUX_BOOTPARAM=y
            CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE=1
            CONFIG_SECURITY_SELINUX_DISABLE=y
            CONFIG_SECURITY_SELINUX_DEVELOP=y
            CONFIG_SECURITY_SELINUX_AVC_STATS=y
            CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1
            

現在使用下面的命令來編譯內核:

make
cp arch/i386/boot/bzImage ..

當然,在轉換到 SELinux 之前,我們首先需要對系統進行測試。這可以使用下面的命令來實現:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

四處瀏覽一下,添加幾個用戶,在系統中玩耍一陣。完成之后,使用 poweroff 命令關閉系統?,F在,我們已經準備好將這個系統轉換成 SELinux 了。





回頁首


轉換成 SELinux

要將這個系統轉換成支持并啟用 SELinux 的系統,我們需要修改開始引導系統的程序 /sbin/init,并添加另外幾個軟件來構建 SELinux 策略及與 SELinux 進行交互。

SysVinit

開始我們可以使用一個干凈的 SysVInit 拷貝。從 ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz 下載 2.86 版本,或者在 freshmeat 上尋找 SysVinit 頁面 上的最新版本。我們可以使用后文中 下載 一節所給出的鏈接以 zip 文件的形式來下載補丁 (sysvinit-init.c.diff);這個補丁可以使用清單 5 中的過程應用于文件 init.c。這個補丁會在系統引導時加載 SELinux 策略。它引入了一個標志 no_selinux,如果引導命令包括了 -p 選項,這個標志就被設置為 1。如果這個標志被設置了,那么就會給出一條警告消息,然后像正常方式一樣引導。否則就調用函數 load_policy(),這個函數是在這個補丁中定義的。


清單 5. 對文件 init.c 應用補丁
wget ftp://ftp.cistron.nl/pub/people/miquels/sysvinit/sysvinit-2.86.tar.gz
            cd sysvinit-2.86
            cd src
            patch -p0 < $ORIG/sysvinit-init.c.diff
            make init
            (su)
            mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
            mv /mnt/sbin/init /mnt/sbin/init.good
            cp init /mnt/sbin/init
            umount /mnt
            exit
            

函數 load_policy() 會將 selinuxfs 文件系統的一個實例加載到 /selinux 目錄中,并打開文件 /etc/policy.bin 準備讀取內容。注意,/selinux 和 /etc/policy.bin 都是強制使用的名字,這樣任何希望使用它的用戶空間工具都可以遵守這種命名方式。在編譯 SELinux 策略時,我們需要將二進制版本拷貝成 /etc/policy.bin。接下來,load_policy() mmap() 會對文件 /etc/policy.bin 進行映射操作,并調用 security_load_policy,這是在 load_policy 上面定義的。它會依次打開文件 /selinux/load(這是 selinuxfs 文件系統中的一個文件)來寫入內容,并將 /etc/policy.bin 的所有內容都寫入到 /selinux/load 中。這就是二進制策略在引導時如何加載到內核中的。

創建策略

SELinux 是一個靈活的訪問控制系統,其訪問決策都是由管理員定義的策略來決定的。這些策略依賴于系統中文件的布局和配置。支持 SELinux 的發行版提供了預定義的策略,可以靈活地排除與系統中沒有安裝的軟件有關的策略。然而在本練習中,我們可以定義自己的策略。

由于新對象類和權限不是同時引入的,因此策略最終對內核版本會有一定的依賴。mdp.tar.gz (后面 下載 一節中的 zip 文件)中的程序會根據內核版本號自動構建一個空策略。由于這需要對內核進行分析,因此我們需要向其指出用來為 QEMU 映像編譯內核所使用的源代碼樹。將 mdp.tar.gz 解壓到 $ORIG/ 中,并進入結果目錄 mdp/。

輸入:

./build.sh -k ../linux-2.6.14.

這會編譯程序 mdp,并使用內核目錄作為一個參數來運行它。mdp 接著會查看內核所了解的對象類和權限,并創建一個包含數據的 SELinux 策略。所生成的策略有一個 SELinux 用戶、一個 SELinux 角色以及一個 SELinux 類型。單個類型可以應用于所有的文件、內核對象和進程,它對自己具有完全的訪問權限。后面我們會對這個策略進行定制,但是現在它可以用來進行初始化并使用 SELinux。

當 build.sh 運行 mdp 時,它會創建幾個文件。我們需要 policy.conf 和 file_contexts。第一個是策略的文本表示,后一個是如何標記文件系統的一些指示。

現在我要將對 policy.conf 的全面學習推遲到后面,因此我們暫時跳過前面 500 到 600 行代碼,直接跳到下面這行:

type base_t;

這是該策略中所定義的惟一一個類型。下面這行代碼:

role base_r types { base_t };

定義了一個角色 base_r,它與 base_t 類型關聯在一起。這意味著角色 code_r 中的一個進程可能會在域 base_t 下面運行。接下來是一些長長的 allow 語句,每個語句指定了一個對象類,這為 domain base_t 下面的進程提供了對為該類定義的所有權限來訪問 base_t 類型的對象類的能力。

接下來,策略會定義一個用戶 user_u,它與角色 base_r 建立了關聯。作為 SELinux 用戶 user_u 運行的進程可以在 base_r 角色下面運行。我們早已看到 base_r 是與 base_t 類型關聯在一起的,因此這兩個語句一起使 user_u:base_r:base_t 成為一個有效的上下文,這意味著允許進程在這個上下文中運行。

下面幾行代碼也非常有用。首先:

sid kernel user_u:base_r:base_t

將一個有效上下文分配給系統中的第一個進程。兩行之后,您可以看到:

sid unlabeled user_u:base_r:base_t

這會將相同的上下文分配給任何沒有標記的文件。

現在來看一下文件 file_contexts。其中包括兩行內容,格式如下:

<regexp> <context>

其中 regexp 是一個用來對文件名進行比較的正則表達式,context 是如果這個正則表達式可以匹配就對文件應用的 SELinux 上下文。下面這行代碼:

/.* user_u:base_r:base_t

用來將這個上下文分配給系統上的所有文件。

安裝 SELinux 用戶空間

下一個步驟是安裝將以文本形式編寫的 SELinux 策略編譯成內核所需要的二進制格式的代碼,以及一個對根文件系統進行標記的程序。源代碼可以使用清單 6 所示的代碼通過 CVS 從 SourceForge 上獲得:


清單 6. 得到 SELinux 用戶空間源代碼
su
            mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
            cd /mnt/usr/src
            cvs -z3 -d:pserver:anonymous@cvs.sf.net:/cvsroot/selinux co -P             nsa/selinux-usr
            

將純文本策略拷貝到磁盤映像文件上,方法如下:

cp -r $ORIG/mdp /mnt/usr/src

進入 nsa/selinux-usr 目錄,并編譯 libsepol、checkpolicy、libselinux 和 policycoreutils,方法如下:


清單 7. 編譯 SELinux 用戶空間代碼
chroot /mnt
            cd /usr/src/nsa/selinux-usr/
            cd libsepol/
            make && make install
            cd ../libselinux/
            make && make install
            cd ../checkpolicy/
            make && make install
            cd ../policycoreutils/
            make && make install
            

如果在上一個步驟中碰到了錯誤,請確保所需要的 setfiles 都已經安裝了,方法如下:


清單 8. 安裝 setfiles
cd setfiles
            make
            make install
            

現在,要編譯策略,請使用 checkpolicy 程序,方法如下:


清單 9. 編譯 SELinux 策略
cd /usr/src/mdp
            checkpolicy -o policy.bin policy.conf
            cp policy.bin /etc/
            exit  # exit chroot
            exit  # exit root shell
            

重新對文件系統進行標記需要引導進虛擬機中。記住現在要指定 -p 選項,這樣 /sbin/init 就不會加載 SELinux 策略:

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1 -p"

SELinux 是通過自己的文件系統 selinuxfs 來與用戶空間的程序進行交互的。用戶空間程序期望它被掛載到 /selinux 上。創建 /selinux 目錄,并對文件系統重新進行標記,方法如下:


清單 10. 重新標記文件系統
mkdir /selinux
            cd /usr/src/mdp
            setfiles file_contexts /
            poweroff
            

最后,您可以在 SELinux 下重新啟動機器了!

qemu -hda gentoo.img -kernel bzImage -append "ro root=/dev/hda1"

學習 SELinux 策略

SELinux 是基于為進程、文件和其他對象所分配的安全上下文來制定訪問決策的。SELinux 為查詢這些上下文并對它們進行設置(假設有所需的訪問權限)提供了接口。例如,SELinux 通過 procattr 接口來報告進程的上下文。如果輸入:

cat /proc/$$/attr/current

就會看到當前進程($$)的上下文。通過使用腳本 pidctx.sh(請參見后文 下載 一節中的 zip 文件),我們可以簡單地查看系統中所有進程的上下文。這個腳本會簡單地打印系統上每個進程的 /proc/<pid>/attr/current 文件的內容。

SELinux 使用擴展屬性來保存文件的內容。Linux 中大部分永久文件系統(ext2、ext3、jfs、xfs 等)都可以支持擴展屬性,而 reiserfs 是一個不幸的例外。這些是一些 (name, value) 的數據對,與 inode 關聯在一起,其中名字被周期性地劃分成名稱空間。SELinux 擴展屬性在安全性名稱空間中,是由 “selinux” 來標識的,因此完整的 xattr 值應該是 “security.selinux”。新的系統調用集允許用戶空間查詢并設置擴展屬性。用來對 xattr 進行查詢的系統調用是 getxattr(2)。它接受一個文件名、一個屬性名、一個緩沖區(xattr 的返回值就保存在這里)以及所提供的緩沖區的大小作為參數。

showctx.c 文件簡單地運行作為命令行提供的所有文件名,并打印 security.selinux 擴展屬性的值,這假設它是存在、可讀的,并且具有合適的大小。

我們可以從后文 下載 一節的 zip 文件中獲得 showctx.tar.gz 文件,并從中解壓出 showctx.c 文件。然后將其放入 QEMU 機器。一種方法是關閉 QEMU 映像,然后執行下面的命令:


清單 11. 安裝 showctx
(su)
            mount -oloop,offset=32256 $ORIG/gentoo.img /mnt
            cp showctx.c /mnt/usr/src
            umount /mnt
            exit
            

現在如果 QEMU 沒在運行,就啟動它。要編譯 showctx,請輸入:

gcc -o showctx showctx.c cp showctx /bin/

現在可以輸入:

showctx / /tmp /home /root /usr/src

當然,對每個文件我們都會看到相同的內容。下一節會通過增強策略來讓這變得更加有趣。





回頁首


使用 SELinux 策略

秘密類型

現在可以創建一個秘密目錄 /secret,SELinux 應該不允許其他進程在這個目錄下面讀取數據。實際上我們可以先在這個目錄中創建一個目錄和幾個文件:

mkdir /secret echo "hello, world" > /secret/helloworld echo "You can't see me" > /secret/dontlook

在 SELinux 策略中,現在創建一個新類型 secret_t,其他類型 base_t 無權訪問它。首先,我們可以將下面的內容:

type secret_t;

添加到 policy.conf 中的 base_t 聲明之后來定義這個類型。另外,由于 secret_t 類型的文件都是角色 base_r 的,而角色 base_r 必須要允許與 secret_t 關聯在一起。因此剛才添加的這行代碼要讀?。?

role base_r types { base_t };

對其進行編輯,使其讀?。?/p>

role base_r types { base_t secret_t };

現在,要重新編譯這個策略,請輸入:

checkpolicy -o policy.bin policy.conf
cp policy.bin /etc/

接下來將下面的行添加到 file_contexts 文件中:


清單 12. /secret 中的文件內容
/secret user_u:base_r:secret_t
            /secret/helloworld user_u:base_r:base_t
            /secret/.* user_u:base_r:secret_t
            

這告訴系統 /secret 目錄及其中的任何文件都是 secret_t類型的,只有 /secret/helloworld 文件例外,它應該是 base_t 類型的。要分配磁盤上的上下文,請使用 setfiles

setfiles file_contexts /

噢不,有錯!SELinux 不認識 secret_t 類型。實際上,我們可以動態重新加載 SELinux 策略。不過現在為了簡單起見,我們還是重新啟動 QEMU 映像好了。當然,由于我們沒有安裝引導程序,因此簡單地重新啟動并不能正常工作。因此,我們需要輸入 poweroff 關閉 QEMU 映像。如果窗口在打印 “Power down” 之后就沒有顯示了,請使用 Ctrl-c 來中斷 qemu 命令。重新運行 qemu 命令來重新啟動它。然后嘗試再次運行上面的 setfiles 命令。

驗證策略的重新加載正確工作了:

showctx / /secret /secret/helloworld /secret/dontlook cat /secret/dontlook

不過等一會兒!您可以看到秘密類型了。

這是一個編譯時內核選項 CONFIG_SECURITY_SELINUX_DEVELOP 的結果。這個選項默認將 SELinux 設置為非強制狀態。要驗證這個設置,請輸入:

cat /selinux/enforce

這應該會返回 0。要將 SELinux 設置成強制模式,請輸入:

echo 1 > /selinux/enforce

如果希望,您可以在系統引導時通過 init 腳本來自動實現這種功能,如清單 13 所示;或者簡單地編譯一個沒有 SELINUX_DEVELOP 支持的內核。


清單 13. 在引導時將 SELinux 設置成強制模式
cat >> /etc/rc.d/selinux-enforce << EOF
            #!/bin/sh
            echo 1 > /selinux/enforce
            EOF
            chmod ugo+x /etc/rc.d/selinux-enforce
            rc-update add default selinux-enforce
            

現在 SELinux 已經處于強制模式了,請再試圖瀏覽 /secret 下面的內容。注意,盡管進程上下文有權讀取 /secret/helloworld,但實際上您并不能真正讀取它,因為無法通過 /secret。當然,創建一個到這個文件的硬鏈接可以跳過這個問題。






回頁首


下載

描述名字大小下載方法
Scripts and C code described in this article l-selinux.zip 4KB HTTP

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97