acl在内核里的位置_Linux 2.6内核ACL机制数据结构和实现分析

Abstract:This paper makes an analysis on ACL's data structure and implements on Linux 2.6 kernel, which includes

data structure in abstract layer and EXT4 filesystem layer. It will also focus on the inode's access control algorithms

and acl's role or function in these algorithms. At last, this paper will describe the procedure of acl control with an

illustration of open system call.

Key words :ACL; Linux 2.6 kernel; EXT4; Access control algorithm; Open system call

摘 要 :本文对Linux2.6 内核的 ACL 机制的数据结构和实现进行分析,包括有抽象标准层面上的 ACL 数据结构以及其在 EXT4 具体文件系统层面上的数据结构。本文还将着重分析 Linux 中对节点的访问权限检查算法以及 ACL 访问控制机制在其中的位置与作用。本文最后将以 Open 系统调用为例说明 ACL 总体控制流程。

关键词 :ACL 、 Linux 2.6 内核、 EXT4 、访问权限检查、 Open 系统调用

绪 论

自从1991 年 9 月 17 日 Linux v0.01 版本发布以来,众多的开源组织和个人加入到 Linux 的开发和完善中, 2001 年 1 月 4 日推出 v2.4 版本, 2003 年 12 月 17 日又推出 v2.6 版本。版本的升级带来的是性能的提升和功能的完善,在目前 Linux 版本中已经包含了许多先进的技术和机制。

ACL访问控制机制就是其中的一种,它让人们摆脱了继承自 Unix 的 user/group/other 粗粒度访问控制模式带来的不便,使得人们可以更加自由的控制文件的访问权限。有关于 ACL 标准的描述在 IEEE 的Posix1003.1e 草案中, ACL 机制的实现在 Linux2.4 内核上是以补丁的方式存在,而在 Linux2.6 内核则以标准功能实现。 Linux 提供了 setfacl 和 getacl 等命令供用户对 ACL 进行设置,而关于如何在程序中应用ACL 则没有给出相应的规范,尽管目前也有不少开源小组在开发各种 libacl-devel 库来支持 ACL 编程。总的来说,目前对于 ACL 机制的实现和开发编程方面的研究还很少。

本文将分为四个部分对Linux2.6 内核 ACL 机制的数据结构和实现进行分析:

第一部分:简单介绍ACL 命令的用法和其访问控制机制的特点。

第二部分:分析抽象层面上的ACL 数据结构,包括有 Posix ACL 数据结构分析和 Posix 标准中对 ACL的各种操作,并重点分析抽象层面上 ACL 权限检查算法。

第三部分:分析EXT4 文件系统中 ACL 的数据结构和存储方式,并说明其与抽象 ACL 相互转化方式,如如何从外存中读取 ACL 属性到内存中,以及如何将内存中的 ACL 写入外存中。

第四部分:说明VFS 的基本原理,并从整体流程上阐述 ACL 访问控制的流程。另外分析了与 ACL 相关的系统调用,以及某些实现。

为了对ACL 机制有个完整的了解,本文的分析中会涉及到一些 Linux 2.4 和 2.6 内核的特性,以及EXT4 文件系统的基本结构。

1. ACL简介

在ACL 机制出现以前,人们都是通过 user/group/other 模式来实现文件的访问控制权限的设置。 Linux和 Unix 使用 9 个比特来表示这种文件的访问模式,如 rwxr-xr-- 就表示文件的属主拥有对文件的读写执行权限,文件属组中的成员对文件拥有读和执行权限,其他人只有读的权限。这种访问模式简单高效,对于早期简单的应用十分有效。但是随着人们对安全特性的要求提高,这种方式已经不能够满足现代的安全需求。

一个很简单的例子就是如何指定同组用户对文件的不同权限,如文件属于security 组,该组的成员对文件都有 r-x 权限,但是我们需要为其中的某个用户 tux 添加 w 权限。在上述模式中, Linux 管理员不得不为tux 再添加一个组,并设置相应的权限,这样做存在许多的不便和安全隐患。如果使用 ACL 机制则可以很好的解决上述问题,用户只需要使用命令 setfacl -m user:tux:rwx file 就能够为 tux 设置对 file 的读写执行的权限。另外也可以使用 ACL 机制对文件进行负授权(或者说权限的撤销),例如使用命令  setfacl -m user:tux:--- file 就可以使 tux 对 file 没有任何权限。

使用命令getfacl file, 可以看到如下输出 :

user::rwx

user:tux:rwx

group::r-w

other::r--

mask::rwx

其中每一行都是一个ACL 实体,对应于某一条具体的访问控制规则,而所有的 ACL 实体就构成了文件的 ACL 属性。每一个 ACL 实体由三部分组成: e_tag 、 e_id 、 e_perm 。 e_tag 表示 ACL 实体的标志,如 user:tux:rwx 中 user 就是一个 e_tag 。 e_id 是 ACL 实体限制的用户或组 id, 如 user:tux:rwx 中的tux, 在某些实体中这个项可以为空。 e_perm 说明的是具体的访问权限,主要有 rwx 三种,这和传统的u/g/o 模式是一致的。在 Posix 标准中规定一共有 6 种 e_tag ,分别是ACL_USER_OBJ, ACL_USER, ACL_GROUP_OBJ, ACL_GROUP, ACL_MASK, ACL_OTHER 。 ACL_USER_OBJ是文件属主的 ACL 实体, ACL_GROUP_OBJ 是文件属组的 ACL 实体, ACL_MASK 是掩码 ACL 实体, ACL_OTHER 是其他用户的 ACL 实体。这四种 ( 个 )ACL 实体的 id 都为空,其他类型的 ACL 实体的 e_id 都不能为空。

2. 抽象ACL 表示

2.1. 内存中的ACL 数据结构

在Linux 中, ACL 是按照 Posix 标准来实现,其数据结构和 Posix 规定的 ACL 的数据是一致的。其定义在 include/linux/posix_acl.h ,实现在 fs/posix_acl.c 中:

struct posix_acl_entry { //acl_entry

short e_tag;   //tag element,used to present user/group/other

unsigned short e_perm; //permission element,used to present rwx

unsigned int e_id; //id element,used to present uid/gid

};

struct posix_acl { //file acl,witch contains lot of acl_entry

atomic_t a_refcount; //counter of process who reference this

unsigned int a_count; //count erof acl_entries

struct posix_acl_entry a_entries[0];//real acl_entries

};

首先我们来对上述数据结构作个说明:

我们在使用setfacl (或 getfacl )设置 ( 或查看 )ACL 的时候,我们通常会表示为如下结构user:tux:rwx ,这其实就是一个 ACL 实体( posix_acl_entry )。 user 对应 e_tag ,表示 ACL 的类型。rwx 对应的是 e_perm ,说明的是赋予的权限。 tux 对应的 e_id ,说明的是这个实体的 id, 如果 e_tag 指定的是 user 那么 e_id 表明是用户 id, 如果 e_id 指定的是 group 那么它表示的就是组 id 。采用这种策略部分原因是为了与原始的 9bit 模式兼容。

一个文件的ACL 属性由多个这样的 ACL 实体构成,描述文件的 ACL 属性就是 posix_acl 数据结构。其中的 a_refcount 指示有多少个进程在使用该 ACL (每有一个新的进程用到这个 ACL 属性,就将该计数器加一;每当一个进程不再使用这个 ACL 属性就将该计数器减一,当减到 0 后就会销毁该 ACL )。a_count 表示这个 ACL 属性中包含多少个 ACL 实体 (posix_acl_entry) , a_entries 为内存中实际存放ACL 项的数组。这里有一个问题:为什么要采用数组的方式实现,这样实现对实体的增删改不会很不方便吗?我们将在后面的表述中说明 Linux 为什么采用数组的方式。

2.2. ACL与内核其他数据结构的关系

上文中我们说到ACL 是一个文件的属性,这是我们通常的观点。在 Linux 中文件这个词的含义稍稍有些变化, File 数据结构特指与进程相关联的一个读写物理文件的上下文关联,实际代表物理文件的是另外一个数据结构 Inode 。这就是为什么你看 File 的数据结构中不包括 9bit 位以及 ACL 属性的原因,它们都是与具体读写上下文无关的属性,是属于物理文件的自身特性的数据。

那么我们来看看内存中的ACL 是如何与具体的 Inode 相关联的吧。查看 Inode 数据结构(include/linux/fs.h) ,我们看到:

00779: #ifdef CONFIG_FS_POSIX_ACL

00780: struct posix_acl *i_acl;

00781: struct posix_acl *i_default_acl;

00782: #endif

也就是说通过i_acl 和 i_default_acl 两个 posix_acl 指针将 Inode 和具体的 ACL 属性关联起来。我们注意到有两个 ACL 属性, acl 和 default_acl ,这两个属性有不同的作用。 acl 属性是用于访问控制的,对一个文件读写执行都要通过这个 acl 属性来控制。 default_acl 属性是目录特有的 ACL 属性,在此目录中创建的文件和目录都将继承这个 default_acl 属性。(对于普通文件来说,该指针为空)。在这里我们要注意的是这两个 ACL 属性都是缓存的 ACL 的属性,在一开始的时候为空,当某个进程要用到这个 ACL 属性的时候,内核就从外存中读取 ACL 属性,并缓存到 inode 的 i_acl 和 i_default_acl 。以后其他进程需要使用到 ACL 的信息就先在内存缓存中查询。我们将在第二部分介绍如何从外存中读取 inode 的 ACL 属性。

2.3. 内存中对ACL 的操作

下表是Posix 中规定的在内存中对 ACL 的操作,列举如下:

函数申明

描述

posix_acl_dup()

实际上是将acl 引用计数加 1

posix_acl_release()

释放内核中acl 的空间

posix_acl_alloc()

分配一个新的ACL

posix_acl_valid()

检查一个ACL 是否合法

posix_acl_permission()

使用acl 检查当前进程是否对 inode 有访问权限

get_posix_acl()

对应于具体文件系统中的操作

set_posix_acl()

对应于具体文件系统中的操作

posix_acl_equiv_mode()

检查acl 是否可以完全代表 9bit 模式

posix_acl_create_masq()

创建新节点时修改其ACL

posix_acl_chmod_masq()

当发生

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值