歡迎您光臨本站 註冊首頁

LIDS精通與進階--二、保護文件系統

←手機掃碼閱讀     火星人 @ 2014-03-12 , reply:0
  冰塊


1、保護文件系統是LIDS的重要功能之一。這個功能是在內核的VFS(虛擬文件系統)層實現的,我們可以保護任何種類的文件系統,如EXT2,FAT。 在LIDS,保護的文件按種類分為以下幾種:

只讀的文件或目錄。只讀文件意味著它們不被允許改寫,如,在目錄/usr/bin,/sbin。這些類型的文件大多數都是二進位系統程序或是系統配置文件,除了在升級系統的時候,我們不需要改變它們。
只可增加文件或目錄。這些文件是那些只可以增加大小的文件。大多數是系統的日值文件,如在/var/log里的只可增加文件。
額外的文件或目錄,這些文件沒有被保護。一般來說,你想要保護目錄下的所有文件,但是,還需要有一些特殊的文件不要被保護。所以我們可以定義這些文件作為額外的其他的只讀文件。
保護掛載或卸載文件系統。當你在啟動的時候掛載文件系統的時候,你可以禁止所有人,甚至是root,去卸載文件系統。你也可以禁止任何人在當前文件系統下掛載文件系統來覆蓋它。
2、LIDS如何在內核保護文件

在這部分,我們會看到一些內核的代碼來理解LIDS是如何保護文件的。

(1)、Linux文件系統數據結構程序

首先,我們必須了解Linux的虛擬文件系統。

在Linux里的每一個文件,不管是什麼樣子的,都有一個結點inode數,文件系統提供了以下數據結構。

在/usr/src/linux/include/linux/fs.h

struct inode {
struct list_head     i_hash;
struct list_head     i_list;
struct list_head     i_dentry;

unsigned long       i_ino; ----> inode number.
unsigned int       i_count;
kdev_t          i_dev; ----> device number.
umode_t          i_mode;
nlink_t          i_nlink;
uid_t           i_uid;
......
}

注意:用來鑒定一個結點inode。這個意思是你可以用一對來得到一個系統里獨一無二的inode。

在/ur/src/linux/cinclude/linux/dcache.h里

struct dentry {
    int d_count;
    unsigned int d_flags;
    struct inode * d_inode;       /* Where the name belongs to - NULL is negative */
    struct dentry * d_parent;     /* parent directory */
    struct dentry * d_mounts;     /* mount information */
    struct dentry * d_covers; struct list_head d_hash;   /* lookup hash list */
    struct list_head d_lru;      /* d_count = 0 LRU list */
    struct list_head d_child;     /* child of parent list */
    struct list_head d_subdirs;    /* our
    ......
}

dentry是一個目錄文件的入口。通過這個入口,我們可以很容易的在文件的父目錄下移動。

例如,如果你一文件的inode是(struct inode*)file_inode,如果你可以用file_inode->d_entry來得到它的目錄入口並且用file_inode->d_entry->d_parent來得到父目錄的目錄入口。

(2)、LIDS保護數據結構

在分析完linux文件系統后,讓我們來看看LIDS是如何容VFS來保護文件和目錄的。

在/usr/src/linux/fs/lids.c

struct secure_ino {
    unsigned long int ino;     /* the inode number */
    kdev_t dev;           /* the dev number /*
    int type;            /* the file type */
    };

上面的結構用一對來存儲保護文件或目錄的結點。"type"是用來標明保護結點文件類型的。

LIDS有4種類型:

在/usr/src/linux/include/linux/fs.h

#define LIDS_APPEND    1    /* APPEND ONLY FILE */
#define LIDS_READONLY   2    /* Read Only File */
#define LIDS_DEVICE    3    /* Protect MBR Writing to device */
#define LIDS_IGNORE    4    /* Ignore the protection */

通過secure_ino結構,我們能很容易的初使化保護的文件或是在內核里執行以下函數。

在/usr/src/linux/fs/lids.c

int lids_add_inode(unsigned long int inode ,kdev_t dev , int type)
{

     if ( last_secure == (LIDS_MAX_INODE-1))
     return 0;

     secure[last_secure].ino = inode;
     secure[last_secure].dev = dev;
     secure[last_secure].type = type;
     secure[++last_secure].ino = 0;

#ifdef VFS_SECURITY_DEBUG
     printk("lids_add_inode : return %dn",last_secure);
#endif
     return last_secure;
}

就象你在上面代碼上可以看到的,給secure_ino加到一個結點上是非常容易的。被保護的結點會在系統啟動的時候初使化。初使化程序在/usr/src/linux/fs/lids.c的init_vfs_security()里。

現在,讓我們看看LIDS是如何來檢查是否一個結點已經受到保護。

在/usr/src/linux/fs/open.c

int do_truncate(struct dentry *dentry, unsigned long length)
{
     struct inode *inode = dentry->d_inode;
     int error;
     struct iattr newattrs;
     /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
     if ((off_t) length < 0)
     return -EINVAL;

#ifdef CONFIG_LIDS
     if (lids_load && lids_local_load) {
     error =
     lids_check_base(dentry,LIDS_READONLY);
     if (error) {
              lids_security_alert("Try to truncate a protected file (dev %d %d,inode %ld)",
              MAJOR(dentry->d_inode->i_dev),
              MINOR(dentry->d_inode->i_dev),
              dentry->d_inode->i_ino);
.....................

這個是LIDS加到內核里做檢測的一個例子。你會看到lids_check_base()是LIDS保護方法的一個核心函數。

你可以在LIDS要保護的地方看到很多LIDS保護方法用到lids_check_base()函數,特別是在linux內核的子目錄下。

在/usr/src/linux/fs/lids.c

int lids_check_base(struct dentry *base, int flag)
{
..................
inode = base->d_inode;     /* get the inode number */
parent = base->d_parent; /* get the parent diretory */
.................
---->  do {
         if ( inode == parent->d_inode)
         break;
         if ((retval = lids_search_inode(inode))) {
           if ( retval == LIDS_IGNORE || (retval == LIDS_DEVICE && flag != LIDS_DEVICE)) break;
           if ( flag == LIDS_READONLY || ( flag == LIDS_APPEND && retval >flag ) || ( flag == LIDS_DEVICE && flag == retval )) {
                         return -EROFS;
                      } break; }
                      inode = parent->d_inode;
                  } while( ((parent = parent->d_parent ) != NULL) );
            return 0;
     }

lids_check_base()會檢查一個給定文件的dentry和它的父目錄是否被保護。

注意:如果它的父目錄被保護,它下面的文件也會被保護。

例如,如果"/etc/"被保護,"/etc/passwd"也一樣被保護。

(3)、在內核保護系統調用

為了保護系統,LIDS會在一些檢查臨界的系統調用的時候做檢查。因此,我們可以保護系統調用和限制文件系統的用戶調用。

這些是一些例子:

open(),open是通過禁止一些權利來保護文件的打開。你可以在打開調用open_namei()調用的時候LIDS在檢測它。
mknod(),mknod是用來在指定目錄下保護mknod。
unlink(),在內核代碼檢查do_unlink()。


[火星人 ] LIDS精通與進階--二、保護文件系統已經有299次圍觀

http://coctec.com/docs/security/show-post-72922.html