linux security model (LSM)加载实现顺序

转载 2013年12月05日 16:27:35

Linux Security Module的注册层次

 

===================================================

作者:ietf AT doit.com.cn

所有源文件来自于linux kernel 2.6.20

请在GNU Library General Public License下参考。

引用请注明出处。

===================================================

selinux的出现着实扰乱了文件系统的进度,不过送算慢慢搞清楚了其中的来龙去脉。下面将通过2.6.20内核中的security代码进行一番简单的分析。该版本的security系统在capabilityrootplug之间还存在一些问题,有很多新的补丁程序,具体可以参考下列邮件列表。

 

http://lists.jammed.com/linux-security-module/2005/08/

 

初次接触LSM时,其间复杂的模块加载方式和顺序很是让人头疼。光其中的ops操作就有security_ops, capability_ops, secondary_ops, selinux_ops, rootplug_ops, selinux_ops, original_ops,再有init函数security_init, capability_init, rootplug_init, selinux_init中的注册关系register_secrity反反复复的来回赋值,最后究竟ops操作都是什么,已经成了一团乱麻。为此,不得不从系统的启动过程开始,寻找其间的因果顺序,事情的经过是这样的:

 

一、LSM的初始化

 

LSM系统的初始化发生在系统内核初始化阶段,在src/init/main.cstart_kernel()里,其位置如下所示:

      fork_init(num_physpages);

      proc_caches_init();

      buffer_init();

      unnamed_dev_init();

      key_init();

      security_init();

      vfs_caches_init(num_physpages);

      radix_tree_init();

      signals_init();

unnamed_dev_init(), key_init()之后,vfs_caches_init之前,其在内核中的位置层次也基本上如此。

 

security_init()的具体实现在/src/security/security.c中,

/**

 * security_init - initializes the security framework

 *

 * This should be called early in the kernel initialization sequence.

 */

int __init security_init(void)

{

      printk(KERN_INFO "Security Framework v" SECURITY_FRAMEWORK_VERSION

            " initialized\n");

 

      if (verify(&dummy_security_ops)) {

             printk(KERN_ERR "%s could not verify "

                   "dummy_security_ops structure.\n", __FUNCTION__);

             return -EIO;

      }

 

      security_ops = &dummy_security_ops;

      do_security_initcalls();

 

      return 0;

}

在此,很有必要了解一下dummy_security_ops的定义,在src/security/dummy.c中,给出了其定义

 

struct security_operations dummy_security_ops;

 

定义后的dummy_security_ops并没有初始化,也就是说,它是security_operations的一个结构,该结构里是一系列的指针,每个指针都指向一个函数,而这些函数,就是security框架所能覆盖的领域,通过修改函数指针,可以达到为原先的系统通过钩子增加一个安全过滤层的目的。即,系统的这些调用,先通过你设计的函数过滤相关操作,再有你的函数调用原先的实现,实现增加一层的目的,这和NT中注册操作的回调函数相似。

 

struct security_operations {.......

dummy_security_ops的初始化是在上面给出的security_initverify(&dummy_security_ops)函数实现的,它将参数XXX_ops中的所有空指针的函数,初始化为dummy.c中定义的dummy_XXX类型对应函数体,每个函数体只提供一个表示成功的返回值,而不执行任何操作。具体参见src/security/dummy.c

 

dummy_security_ops初始化完成后,通过security_ops=&dummy_security_ops,使得security_ops指向一个不做任何操作的过滤层。再通过do_security_initcalls()加载具体配置的安全过滤模块。

 

在来看看do_security_initcalls()函数是怎么实现的:

 

static void __init do_security_initcalls(void)

{

      initcall_t *call;

      call = __security_initcall_start;

      while (call < __security_initcall_end) {

             (*call) ();

             call++;

      }

}

 

在系统中,security_initcall.init的函数总共有三个,分别为:capability_init(), rootplug_init()selinux_init()。其中,selinux只能第一个注册(即作为security_ops上的第一个过滤层),否则注册会失败。selinux注册后,original_ops=secondary_ops=dummy_ops; securuty_ops=selinux_ops。前两者的注册方式完全一致,并且,在当前代码实现中,两者只能注册一个,另外一个在第一个注册成功后,即使以模块方式加载也会失败。例如,capability_init()注册后,secondary_ops=capability_ops; original_ops=dummy_ops; security_ops=selinux_ops。此时如果再调用rootplug_init(),将因为security_ops!=dummy_security_ops而调用register_security失败,然后因为secondary_ops != original_ops而在调用security_ops->register_securityselinux_register_security函数中返回出错,原因为几经存在了一个第二层模块。

 

具体代码不在这里列出,有兴趣者可以到src/security/目录下分别查看capability.c, root_plug.cselinux/hooks.c

 

因此可见,主要得代码实现都是在selinux中实现的。以我所感兴趣的selinux_mountselinux_umount为例,其代码如下:

 

static int selinux_mount(char * dev_name,

                        struct nameidata *nd,

                        char * type,

                        unsigned long flags,

                        void * data)

{

      int rc;

 

      rc = secondary_ops->sb_mount(dev_name, nd, type, flags, data);

      if (rc)

             return rc;

 

      if (flags & MS_REMOUNT)

             return superblock_has_perm(current, nd->mnt->mnt_sb,

                                       FILESYSTEM__REMOUNT, NULL);

      else

             return dentry_has_perm(current, nd->mnt, nd->dentry,

                                   FILE__MOUNTON);

}

 

static int selinux_umount(struct vfsmount *mnt, int flags)

{

      int rc;

 

      rc = secondary_ops->sb_umount(mnt, flags);

      if (rc)

             return rc;

 

      return superblock_has_perm(current,mnt->mnt_sb,

                                FILESYSTEM__UNMOUNT,NULL);

}

 

由上面的ops赋值关系可知,secondary_ops->sb_mountsecondary_ops->sb_umount无论capabilityroot_plug是否加载,因为其在这两者中都没有定义实现,所以,为dummy_XXX函数,相关的代码如下:

 

static int dummy_sb_mount (char *dev_name, struct nameidata *nd, char *type,

                      unsigned long flags, void *data)

{

      return 0;

}

 

static int dummy_sb_check_sb (struct vfsmount *mnt, struct nameidata *nd)

{

      return 0;

}

 

static int dummy_sb_umount (struct vfsmount *mnt, int flags)

{

      return 0;

}

 

static void dummy_sb_umount_close (struct vfsmount *mnt)

{

      return;

}

 

static void dummy_sb_umount_busy (struct vfsmount *mnt)

{

      return;

}

 

static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags,

                             void *data)

{

      return;

}

 

 

static void dummy_sb_post_mountroot (void)

{

      return;

}

 

然后给出一定的pemmision的判断。permmision判断通过查找avchash表实现,它是以数据库的形式在内核维护的。在selinux中,ss目录下的文件负责维护security所有安全检查需要的数据库,对于数据库的详细操作和保存和加载,请参考src/security/selinux/ss/policydb.c中的相关函数。

 

Linux 内核安全模块学习总结

Linux安全模块(LSM) LSM是Linux Secrity Module的简称,即linux安全模块。其是一种轻量级通用访 问控制框架,适合于多种访问控制模型在它上面以内核可加载模块的形实现...
  • bcbobo21cn
  • bcbobo21cn
  • 2016年03月15日 18:34
  • 3099

学习LSM(Linux security module)之二:编写并运行一个简单的demo

各种折腾,经过了一个蛋疼的周末,终于在Ubuntu14.04上运行了一个基于LSM的简单demo程序。 一:程序编写   先简单的看一下这个demo: //demo_lsm.c#...
  • hanmengaidudu
  • hanmengaidudu
  • 2017年04月06日 09:58
  • 479

Linux 安全模块(LSM)简介

  • 2011年04月26日 09:05
  • 48KB
  • 下载

基于Linux文件系统安全性的LSM框架的研究

  • 2013年01月20日 18:10
  • 72KB
  • 下载

Linux 内核安全模块学习总结

Linux安全模块(LSM) LSM是Linux Secrity Module的简称,即linux安全模块。其是一种轻量级通用访 问控制框架,适合于多种访问控制模型在它上面以内核可加载模块的形实现...
  • bcbobo21cn
  • bcbobo21cn
  • 2016年03月15日 18:34
  • 3099

B+树与LSM树的区别与联系

首先来回答一个问题:为什么在磁盘中要使用b+树来进行文件存储呢? 原因还是因为树的高度低得缘故,磁盘本身是一个顺序读写快,随机读写慢的系统,那么如果想高效的从磁盘中找到数据,势必需要满足一个最重要的...
  • yyd19921214
  • yyd19921214
  • 2017年04月08日 16:36
  • 1069

Linux Kernel Project

Linux Kernel Project Table of Contents ...
  • hansel
  • hansel
  • 2007年10月20日 16:33
  • 4272

linux框架

  • sxlwzl
  • sxlwzl
  • 2013年09月03日 09:10
  • 397

HBase总结(七)LSM理解

讲LSM树之前,需要提下三种基本的存储引擎,这样才能清楚LSM树的由来: 哈希存储引擎  是哈希表的持久化实现,支持增、删、改以及随机读取操作,但不支持顺序扫描,对应的存储系统为key-valu...
  • lifuxiangcaohui
  • lifuxiangcaohui
  • 2014年10月10日 15:11
  • 5971

从【SELINUX】策略中学习【LSM】编写规则

最近涉及到了LSM的编写,在网上基本上搜不到关于LSM的
  • WSRspirit
  • WSRspirit
  • 2014年05月20日 21:53
  • 2491
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux security model (LSM)加载实现顺序
举报原因:
原因补充:

(最多只允许输入30个字)