catalog

. 简介
. 扩展属性
. 访问控制表
. 小结

0. 简介

许多文件系统都提供了一些特性,扩展了VFS层提供的标准功能,虚拟文件系统不可能为所有特性都提供具体的数据结构。超出标准的UNIX文件模型的附加特性,通常需要将一个组扩展属性关联到每个文件系统对象
Linux内核能够提供的是一个框架,容许增加特定于文件系统的扩展,扩展属性(extended attribute xattrs)是能够关联到文件的任意属性,由于每个文件通常都只关联了所有可能扩展属性的一个子集,扩展属性存储在常规的inode数据结构之外,以避免增加该结构在内存中的长度和浪费磁盘空间,这实际上容许使用一个通用的属性集合,而不会对文件系统性能或磁盘空间需求有任何显著影响
0x1: 扩展用途

. 实现访问控制表(access control list)
对UNIX风格的权限模型进行扩展,它们允许实现细粒度的访问控制,不仅仅使用用户、组、其他用户的概念,而是将各个用户及其允许的操作组成一个明确的列表,关联到文件
这种列表很自然地融合到扩展属性模型中 . 为SELINUX提供标记信息

Relevant Link:

1. 扩展属性

从文件系统用户的角度来看,一个扩展属性就是与文件系统对象关联的一个"名称/值"对

. 名称: 一个普通字符串
. 值: 内核对值的内容不作限制,可以是文本,也可以是包含任意二进制数据

属性名称会按命名空间细分,这意味着,访问属性也需要给出命名空间,按照符号约定,用一个点来分隔命名空间和属性名(例如user.mime_type)
内核使用宏定义了有效的顶层命名空间的列表(例如XATTR_*_PREFIX),在从用户空间传递来一个名字串,需要与命名空间前缀比较时,一组辅助性的宏XATTR_*_PREFIX_LEN是很有用的
\linux-2.6.32.63\include\linux\xattr.h

/* Namespaces */
#define XATTR_OS2_PREFIX "os2."
#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1) #define XATTR_SECURITY_PREFIX "security."
#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) #define XATTR_SYSTEM_PREFIX "system."
#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1) #define XATTR_TRUSTED_PREFIX "trusted."
#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) #define XATTR_USER_PREFIX "user."
#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)

内核提供了几个系统调用来读取和操作扩展属性

. setxattr: 用于设置或替换某个扩展属性的值,或创建一个新的扩展属性
. getxattr: 获取某个扩展属性的值
. removexattr: 删除一个扩展属性
. listxattr: 列出与给定的文件系统对象相关的所有扩展属性

0x1: 到虚拟文件系统的接口

虚拟文件系统向用户空间提供了一个抽象层,使得所有应用程序都可以使用扩展属性,而无需考虑底层文件系统实现如何在磁盘上存储该信息,要注意的是,尽管VFS作为扩展属性提供了一个抽象层,这并不意味着每个文件系统都必须实现该特性,实际上,内核中的大多数文件系统都不支持扩展属性,但是Linux上的所有主流硬盘型的文件系统(如Ext3、reiscrfs、xfs等)都支持扩展属性

1. 数据结构

由于扩展属性的结构非常简单,内核并没有提供一个特定的结构来封装这样的名称/值对,相反,内核使用了一个简单的字符串来表示名称,而用一个void指针来表示值在内存中的存储位置
但是仍然需要一些方法来设置、检索、删除、列出扩展属性,由于这些操作是特定于inode的,因此它们归入struct inode_operations
事实上,文件系统可以为这些操作提供定制实现,但内核也提供了一组通用的处理程序(例如Ext3文件系统即使用了内核的通用实现),在理解其实现之前,我们需要先了解基本的数据结构,对每一对扩展属性,都需要函数与块设备之间来回传输信息,这些函数封装在下列结构中
\linux-2.6.32.63\include\linux\xattr.h

struct xattr_handler
{
//表示命名空间,该操作即应用到这个命名空间的属性上,它可以是XATTR_*_PREFIX中的任何值
char *prefix; //list方法列出一个与文件相关的所有扩展属性
size_t (*list)(struct inode *inode, char *list, size_t list_size, const char *name, size_t name_len); //get方法从底层块设备读取扩展属性
int (*get)(struct inode *inode, const char *name, void *buffer, size_t size);
//set方法向底层块设备写入扩展属性
int (*set)(struct inode *inode, const char *name, const void *buffer, size_t size, int flags);
};

超级块提供了到一个数组的关联,该数组给出了相应文件系统的所有支持的处理程序

http://www.cnblogs.com/LittleHann/p/3865490.html
//搜索:0x10: struct super_block

处理程序在数组中出现的次序不是固定的,内核通过比较处理程序的前缀与所述扩展属性的命名空间的前缀,可以找到一个适当的次序

aaarticlea/png;base64,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" alt="" />
2. 系统调用

我们知道,每个扩展属性操作(get、set、list)都对应了3个系统调用,三者的区别在于指定目标的方法,为避免代码复制,这些系统调用在结构上分为两部分

. 查找与目标对象相关联的dentry实例
查找dentry实例时,可使用user_path_walk、或user_path_walk_link、或直接读取包含在file实例中的指针,具体的做法取决于使用了哪个系统调用,在找到dentry实例后,就为3个系统调用建立了一个公共的基础 . 其他工作委托给一个函数,该函数对3个系统调用是通用的

我们以setxattr系统调用为例,相关代码流程图如下

aaarticlea/png;base64,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" alt="" />

/source/fs/xattr.c

/*
* Extended attribute SET operations
*/
static long setxattr(struct dentry *d, const char __user *name, const void __user *value, size_t size, int flags)
{
int error;
void *kvalue = NULL;
char kname[XATTR_NAME_MAX + ]; if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
return -EINVAL; //将属性的名称/值从用户空间复制到内核空间
error = strncpy_from_user(kname, name, sizeof(kname));
if (error == || error == sizeof(kname))
error = -ERANGE;
if (error < )
return error; if (size) {
if (size > XATTR_SIZE_MAX)
return -E2BIG;
kvalue = memdup_user(value, size);
if (IS_ERR(kvalue))
return PTR_ERR(kvalue);
} //进一步的处理委托给vfs_setxattr
error = vfs_setxattr(d, kname, kvalue, size, flags);
kfree(kvalue);
return error;
}

/source/fs/xattr.c

int vfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
{
struct inode *inode = dentry->d_inode;
int error; //内核需要确认用户是否有执行目标操作的权限,对于只读或不可修改的inode,操作会立即失败
error = xattr_permission(inode, name, MAY_WRITE);
if (error)
//VFS层并不关注security、system命名空间中的属性,如果xattr_permission返回0,则允许请求,内核忽略这些命名空间,并将选择权委派给安全模块
return error; mutex_lock(&inode->i_mutex);
//LSM Hook
error = security_inode_setxattr(dentry, name, value, size, flags);
if (error)
goto out; error = __vfs_setxattr_noperm(dentry, name, value, size, flags); out:
mutex_unlock(&inode->i_mutex);
return error;
}
EXPORT_SYMBOL_GPL(vfs_setxattr);

error = xattr_permission(inode, name, MAY_WRITE);

static int xattr_permission(struct inode *inode, const char *name, int mask)
{
/*
* We can never set or remove an extended attribute on a read-only
* filesystem or on an immutable / append-only inode.
*/
if (mask & MAY_WRITE)
{
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
return -EPERM;
} /*
* No restriction for security.* and system.* from the VFS. Decision
* on these is left to the underlying filesystem / security module.
VFS不限制security.*和system.*,对此类属性的判断留给底层文件系统/安全模块
*/
if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
return ; /*
* The trusted.* namespace can only be accessed by a privileged user.
trusted.*命名空间只能由特权用户访问
*/
if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
return (capable(CAP_SYS_ADMIN) ? : -EPERM); /* In user.* namespace, only regular files and directories can have
* extended attributes. For sticky directories, only the owner and
* privileged user can write attributes.
在user.*命名空间中,只有普通文件和目录可以有扩展属性
对于"粘着位"置位的目录来说,只有所有者和特权用户能够写入属性值
*/
if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
return -EPERM;
if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
(mask & MAY_WRITE) && !is_owner_or_cap(inode))
return -EPERM;
} return inode_permission(inode, mask);
}

如果inode通过了权限检查,则vfs_setattr继续进行以下步骤

. 如果inode_operations中提供了特定于文件系统的setattr方法,则调用该方法与文件系统进行底层交互,接下来,fsnotify_xattr使用inotify机制将扩展属性的改变通知用户层
. 如果没提供setattr方法(即底层文件系统不支持扩展属性),但所述的扩展属性属于security命名空间,那么内核会试图使用由安全框架(例如SEINUX)提供的一个函数,如果没有注册此类框架,则拒绝该操作
//在不支持扩展属性的文件系统中,这种做法能够在文件上加上安全标记。同时以一种合理的方法来存储该信息,则是安全子系统的任务

3. 通用处理程序函数

安全是一项重要的工作,如果做出错误的决策,那么即使最佳的安全机制也毫无价值,由于代码的复制增加了细节出错的可能性,所以内核对处理扩展属性的inode_operations方法提供了通用实现(实际上,内核对VFS的很多函数都封装了通用的实现),文件系统开发者可以直接使用这些实现
/source/fs/xattr.c

/*
* Find the handler for the prefix and dispatch its set() operation.
*/
int generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
{
struct xattr_handler *handler;
struct inode *inode = dentry->d_inode; if (size == )
value = ""; /* empty EA, do not remove */ //首先,xattr_resolve_name查找适用于所述扩展属性的命名空间的xattr_handler实例
handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
if (!handler)
return -EOPNOTSUPP;
//如果存在一个处理程序,则调用其set方法来执行设置属性值的操作,handler->set是一个特定于文件系统的方法
return handler->set(inode, name, value, size, flags);
}

0x2: ext3中的实现

在所有文件系统中,Ext3是最杰出的成员之一,因为它提供了对扩展属性的良好支持,我们继续讨论在文件系统层面上对扩展属性的实现,以及扩展属性如何在磁盘上持久存储

1. 数据结构

Ext3采纳了一些提高编码效率的良好建议,并采用了VFS通用实现,它提供了若干处理程序函数,并使用标识号来访问处理程序函数,而不是按照字符串标识,这简化了许多操作,并能够更高效地利用磁盘空间
\linux-2.6.32.63\fs\ext3\xattr.c

static struct xattr_handler *ext3_xattr_handler_map[] =
{
[EXT3_XATTR_INDEX_USER] = &ext3_xattr_user_handler,
#ifdef CONFIG_EXT3_FS_POSIX_ACL
[EXT3_XATTR_INDEX_POSIX_ACL_ACCESS] = &ext3_xattr_acl_access_handler,
[EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT] = &ext3_xattr_acl_default_handler,
#endif
[EXT3_XATTR_INDEX_TRUSTED] = &ext3_xattr_trusted_handler,
#ifdef CONFIG_EXT3_FS_SECURITY
[EXT3_XATTR_INDEX_SECURITY] = &ext3_xattr_security_handler,
#endif
};

aaarticlea/png;base64,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" alt="" />

结构描述如下

. 扩展属性所占的空间,由一个短的标识头开始,即首部
\linux-2.6.32.63\fs\ext3\xattr.h
struct ext3_xattr_header
{
/* magic number for identification 用于标识的魔数 */
__le32 h_magic; /* reference count 引用计数 */
__le32 h_refcount; /* number of disk blocks used 使用磁盘块的数目,必须总是设置为1,其他任何值都是错的 */
__le32 h_blocks; /* hash value of all attributes 所有属性的散列值 */
__le32 h_hash;
__u32 h_reserved[]; /* zero right now */
}; . 接下来是一系列数据项的列表(struct ext3_xattr_entry),每个数据项都包含了属性名称和指向属性值存储区域的一个指针,在向文件添加新的扩展属性时,列表向下增长
struct ext3_xattr_entry
{
/* length of name 名称长度 */
__u8 e_name_len; /* attribute name index 属性名索引,用于索引ext3_xattr_handler_map */
__u8 e_name_index; /* offset in disk block of value 属性值在所处磁盘块中的偏移量 */
__le16 e_value_offs; /* disk block attribute is stored on (n/i) 存储属性的磁盘块 */
__le32 e_value_block; /* size of attribute value 属性值长度 */
__le32 e_value_size; /* hash value of name and value 属性名和值的散列值 */
__le32 e_hash; /*
attribute name 属性名
各个数据项的长度不一定是相同的,因为属性名的长度是可变的,因此将属性名存储在结构末尾
*/
char e_name[];
}; . 属性值存储在扩展属性数据空间的尾部,值表与属性名称表相对增长,属性值可以按任意次序存储,通常与属性名称排序不同

Ext3扩展属性的结构可以放置在两个地方

. inode末尾的未使用空间: 只有使用了允许动态inode长度的新文件系统格式(EXT3_DYNAMIC_REV)才可能出现
. 磁盘上一个独立的数据块
//如果两个文件的扩展属性集合是相同的,那么二者可以共享同一个磁盘表示,这有助于节省一些磁盘空间

2. 实现

对不同的属性命名空间,处理程序的实现十分类似,我们以user命名空间的实现为例进行讨论,ext3_xattr_user_hanler的定义如下
\linux-2.6.32.63\fs\ext3\xattr_user.c

struct xattr_handler ext3_xattr_user_handler =
{
.prefix = XATTR_USER_PREFIX,
.list = ext3_xattr_user_list,
.get = ext3_xattr_user_get,
.set = ext3_xattr_user_set,
};

0x3: ext2中的实现

Ext2中的扩展属性的实现和Ext3的实现非常类似,但是由于Ext3中的一些特性在Ext2中是不可用的,这也是二者扩展属性的实现有所差别的原因

. 由于Ext2并不支持动态的inode长度,所以磁盘上的inode中没有足够空间存储扩展属性的数据,因此,扩展属性总是存储在一个独立的数据块中,这简化了一些函数,因为无须区分扩展属性的不同存储位置
. Ext2并不使用日志,因此所有日志相关函数的调用都是不必要的,这也使得一些只处理句柄操作的包装器变得不必要
//此外,二者的实现几乎相同,大部分函数,将前缀ext3_换成ext2_之后,都是可用的


2. 访问控制表

POSIX访问控制表(ACL)是POSIX标准定义的一种扩展,用于细化Linx的自主访问控制(DAC)模型。ACL借助扩展属性实现,修改ACL所用的方法与其他扩展属性是相同的,内核对扩展属性的内容并不感兴趣,但ACL扩展属性将集成到inode权限检查中,尽管文件系统可以自由选择用于表示扩展属性的物理格式,但内核仍然定义了用于表示访问控制表的交换结构,对于承载访问控制表的扩展属性,必须使用下列命名空间
\linux-2.6.32.63\include\linux\posix_acl_xattr.h

/* Extended attribute names */
#define POSIX_ACL_XATTR_ACCESS "system.posix_acl_access"
#define POSIX_ACL_XATTR_DEFAULT "system.posix_acl_default"

用户层getfacl、setfacl、chacl用于获取、设置和修改ACL的内容,它们使用可以操作扩展属性的标准系统调用,并不需要与内核进行非标准交互,许多其他实用程序(例如ls)也内建了对访问控制表的支持
0x1: 通用实现

用于实现ACL的通用代码包含在两个文件中

. \linux-2.6.32.63\fs\posix_acl.c
包含了分配新ACL、复制ACL、进行扩展权限检查等功能代码 . \linux-2.6.32.63\fs\xattr_acl.c
包含的函数用于在扩展属性、ACL的通用表示之间进行转换,并且转换是双向的 /*
所有通用的数据结构都定义在
\linux-2.6.32.63\include\linux\posix_acl_xattr.h
\linux-2.6.32.63\include\linux\posix_acl.h
*/

1. 数据结构

用于存储与ACL相关的所有数据的内存表示的主要数据结构定义如下
\linux-2.6.32.63\include\linux\posix_acl.h

/*
每个ACL项都包含了
1. 一个标记
2. 一个权限
3. 一个(用户/组)ID 该ACL项即定义了该ID对某文件的权限
*/
struct posix_acl_entry
{
short e_tag;
unsigned short e_perm;
unsigned int e_id;
}; //属于给定inode的所有ACL,都收集到struct posix_acl 中
struct posix_acl
{
atomic_t a_refcount;
unsigned int a_count; //由于包含所有ACL项的数组位于结构末尾,所以ACL项的最大数据除了受到扩展属性最大长度的限制之外,并无其他限制
struct posix_acl_entry a_entries[];
};

用于ACL类型、标记、权限的符号常数,由以下预处理器定义给出
\linux-2.6.32.63\include\linux\posix_acl.h

/* a_type field in acl_user_posix_entry_t */
#define ACL_TYPE_ACCESS (0x8000)
#define ACL_TYPE_DEFAULT (0x4000) /* e_tag entry in struct posix_acl_entry */
#define ACL_USER_OBJ (0x01)
#define ACL_USER (0x02)
#define ACL_GROUP_OBJ (0x04)
#define ACL_GROUP (0x08)
#define ACL_MASK (0x10)
#define ACL_OTHER (0x20) /* permissions in the e_perm field */
#define ACL_READ (0x04)
#define ACL_WRITE (0x02)
#define ACL_EXECUTE (0x01)

内核定义了另一组数据结构,用于和用户层的外部交互中ACL的扩展属性表示
\linux-2.6.32.63\include\linux\posix_acl_xattr.h

typedef struct
{
__le16 e_tag;
__le16 e_perm;
__le32 e_id;
} posix_acl_xattr_entry; typedef struct
{
__le32 a_version;
posix_acl_xattr_entry a_entries[];
} posix_acl_xattr_header;

posix_acl_from_xattr、posix_acl_to_xattr用于在两种表示之间来回转换,函数的工作是独立于底层文件系统的
2. 权限检查

对涉及访问控制表的权限检查,内核通常需要底层文件系统的支持

. 文件系统自行实现所有的权限检查,通过struct inode_operations->permission函数
. 文件系统提供一个回调函数供generic_permission使用(内核中大多数文件系统默认使用的方法)

generic_permission中使用的回调函数如下
\linux-2.6.32.63\fs\namei.c

http://www.cnblogs.com/LittleHann/p/4305892.html
//搜索:0x3: 权限检查

即使文件系统提供了进行ACL权限检查的专用函数,但各个例程通常会归结到一些技术性的工作,例如获得ACL数据,而真正的权限检查仍然会委托给内核提供的标准函数: posix_acl_permission
\linux-2.6.32.63\fs\posix_acl.c

int posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
{
const struct posix_acl_entry *pa, *pe, *mask_obj;
int found = ; //使用FOREACH_ACL_ENTRY宏来遍历所有的ACL项
FOREACH_ACL_ENTRY(pa, acl, pe)
{
switch(pa->e_tag)
{
case ACL_USER_OBJ:
/*
(May have been checked already)
对每个ACL项,都需要比较文件系统UID(FSUID),和当前进程凭据的相应部分
1. 对_OBJ类型的ACL项,需要比较inode的UID/GID
2/ 对其他类型的项,需要比较ACL项中指定的ID
*/
if (inode->i_uid == current_fsuid())
goto check_perm;
break;
case ACL_USER:
if (pa->e_id == current_fsuid())
goto mask;
break;
case ACL_GROUP_OBJ:
if (in_group_p(inode->i_gid)) {
found = ;
if ((pa->e_perm & want) == want)
goto mask;
}
break;
case ACL_GROUP:
if (in_group_p(pa->e_id)) {
found = ;
if ((pa->e_perm & want) == want)
goto mask;
}
break;
case ACL_MASK:
break;
case ACL_OTHER:
if (found)
return -EACCES;
else
goto check_perm;
default:
return -EIO;
}
}
return -EIO; //从根本上来说,授权访问权限,代码的控制流在mask标号结束,在这种情况下,仍然需要确认在授权ACL项之后没有声明ACL_MASK项,所以导致拒绝授权
mask:
for (mask_obj = pa+; mask_obj != pe; mask_obj++)
{
if (mask_obj->e_tag == ACL_MASK)
{
if ((pa->e_perm & mask_obj->e_perm & want) == want)
return ;
return -EACCES;
}
}
//下面代码确保,权限不仅仅因为适当的UID/GID而有效,而且授权ACL项也允许了所要进行的访问(读、写、执行),即是否满足主体-客体的授权关系
check_perm:
if ((pa->e_perm & want) == want)
return ;
return -EACCES;
}

0x2: ext3中的实现

我们知道,ACL基于扩展属性实现,并借助了许多通用的辅助例程,所以Ext3对ACL的实现相当简洁

1. 数据结构

Ext3的ACL的磁盘表示的格式与通用的POSIX辅助函数所需的内存非常类似
\linux-2.6.32.63\fs\ext3\acl.h

typedef struct
{
__le16 e_tag;
__le16 e_perm;
__le32 e_id;
} ext3_acl_entry; //为了节省磁盘空间,还定义了一个e_id字段的版本,该版本用于ACL列表的前四项,因为这几项不需要具体的UID/GID
typedef struct
{
__le16 e_tag;
__le16 e_perm;
} ext3_acl_entry_short;

ACL项的列表总是有一个表头

typedef struct
{
//a_version字段使得能够区分ACL实现的不同版本
__le32 a_version;
} ext3_acl_header;

Ext3 inode的内存表示增加了两个与ACL实现相关的字段
\linux-2.6.32.63\include\linux\ext3_fs_i.h
2. 磁盘和内存表示之间的转换

有两个转换函数可用于磁盘和内存表示之间的转换

. ext3_acl_to_disk: 遍历给定的posix_acl实例中的所有ACL项,将其中包含的数据从特定于CPU的格式转换为小端序格式,并指定适当的位长
. ext3_acl_from_disk: 从inode中包含的信息获取裸数据,剥去头信息,将ACL列表中每个ACL项的数据从小端序格式转换为适用于系统本机CPU的格式
//fs/ext3/acl.c

3. inode初始化

在用ext3_new_inode创建新inode时,ACL的初始化委托给ext3_init_acl
\linux-2.6.32.63\fs\ext3\acl.c

/*
* Initialize the ACLs of a new inode. Called from ext3_new_inode.
*
* dir->i_mutex: down
* inode->i_mutex: up (access to inode is still exclusive)
1. inode参数指向新的inode
2. dir表示包含inode对应文件的目录的inode,之所以需要目录信息,是因为如果目录包含了默认ACL,则其内容需要应用到新的文件,这是权限继承原则
*/
int ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir)
{
struct posix_acl *acl = NULL;
int error = ; if (!S_ISLNK(inode->i_mode))
{
if (test_opt(dir->i_sb, POSIX_ACL)) {
acl = ext3_get_acl(dir, ACL_TYPE_DEFAULT);
if (IS_ERR(acl))
return PTR_ERR(acl);
}
if (!acl)
inode->i_mode &= ~current_umask();
} //inode所在的文件系统支持ACL,而且父目录有与之关联的默认ACL
if (test_opt(inode->i_sb, POSIX_ACL) && acl)
{
struct posix_acl *clone;
mode_t mode; if (S_ISDIR(inode->i_mode))
{
//ext3_set_acl用来设置特定inode的ACL内容
error = ext3_set_acl(handle, inode, ACL_TYPE_DEFAULT, acl);
if (error)
goto cleanup;
}
//调用posix_acl_clone对默认ACL的内存表示创建一个可工作的副本
clone = posix_acl_clone(acl, GFP_NOFS);
error = -ENOMEM;
if (!clone)
goto cleanup; mode = inode->i_mode;
/*
调用posix_acl_create_masq,从inode创建进程指定的访问权限中,删除默认ACL不能授予的所有权限,这可能导致下面两种情形
1. 为符合ACL的要求,访问权限可能不变,也可能需要删除某些权限位,这种情况下,新的inode的i_mode字段,需要设置为posix_acl_create_masq计算出来的mode值
2. 除了对原来指定的访问权限进行必要的调整之外,默认ACL可能包含了一些ACL项,不能用通常的用户/组/其他方案来表示,在这种情况下,需要为新的inode创建一个ACL,包含相关的扩展权限信息
*/
error = posix_acl_create_masq(clone, &mode);
if (error >= )
{
inode->i_mode = mode;
if (error > )
{
/* This is an extended ACL */
error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
}
}
posix_acl_release(clone);
}
cleanup:
posix_acl_release(acl);
return error;
}

4. 获取ACL

给出struct inode的一个实例,ext3_get_acl可用于获取ACL的内存表示
\linux-2.6.32.63\fs\ext3\acl.c

/*
* Inode operation get_posix_acl().
*
* inode->i_mutex: don't care
1. type指定了获取ACL类型
1) ACL_TYPE_DEFAULT: 默认ACL
2) ACL_TYPE_ACCESS: 获取由于控制inode访问权限的ACL
*/
static struct posix_acl *ext3_get_acl(struct inode *inode, int type)
{
int name_index;
char *value = NULL;
struct posix_acl *acl;
int retval; if (!test_opt(inode->i_sb, POSIX_ACL))
return NULL; //调用get_cached_acl检查ACL的内存表示是否已经缓存到了ext3_inode_info->i_acl,如果已经缓存,则直接创建并返回一个副本
acl = get_cached_acl(inode, type);
if (acl != ACL_NOT_CACHED)
return acl; switch (type) {
case ACL_TYPE_ACCESS:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_ACCESS;
break;
case ACL_TYPE_DEFAULT:
name_index = EXT3_XATTR_INDEX_POSIX_ACL_DEFAULT;
break;
default:
BUG();
} //如果ACL无缓存,那么首先调用ext3_xattr_get从扩展属性子系统获取裸数据
retval = ext3_xattr_get(inode, name_index, "", NULL, );
if (retval > ) {
value = kmalloc(retval, GFP_NOFS);
if (!value)
return ERR_PTR(-ENOMEM);
retval = ext3_xattr_get(inode, name_index, "", value, retval);
}
if (retval > )
acl = ext3_acl_from_disk(value, retval);
else if (retval == -ENODATA || retval == -ENOSYS)
acl = NULL;
else
acl = ERR_PTR(retval);
kfree(value); if (!IS_ERR(acl))
set_cached_acl(inode, type, acl); return acl;
}

5. 修改ACL

在通过ext3_setattr改变文件的(通用)属性时,ext3_acl_chmod函数负责保持ACL为最新数据并维护其一致性。一般来说,用户空间通过系统调用来调用VFS层,VFS层又通过ext3_setattr来修改属性
\linux-2.6.32.63\fs\ext3\inode.c

int ext3_setattr(struct dentry *dentry, struct iattr *attr)
{
struct inode *inode = dentry->d_inode;
int error, rc = ;
const unsigned int ia_valid = attr->ia_valid; error = inode_change_ok(inode, attr);
if (error)
return error; if ((ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
(ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
handle_t *handle; /* (user+group)*(old+new) structure, inode write (sb,
* inode block, ? - but truncate inode update has it) */
handle = ext3_journal_start(inode, *(EXT3_QUOTA_INIT_BLOCKS(inode->i_sb)+
EXT3_QUOTA_DEL_BLOCKS(inode->i_sb))+);
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
goto err_out;
}
error = vfs_dq_transfer(inode, attr) ? -EDQUOT : ;
if (error) {
ext3_journal_stop(handle);
return error;
}
/* Update corresponding info in inode so that everything is in
* one transaction */
if (attr->ia_valid & ATTR_UID)
inode->i_uid = attr->ia_uid;
if (attr->ia_valid & ATTR_GID)
inode->i_gid = attr->ia_gid;
error = ext3_mark_inode_dirty(handle, inode);
ext3_journal_stop(handle);
} if (S_ISREG(inode->i_mode) &&
attr->ia_valid & ATTR_SIZE && attr->ia_size < inode->i_size) {
handle_t *handle; handle = ext3_journal_start(inode, );
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
goto err_out;
} error = ext3_orphan_add(handle, inode);
EXT3_I(inode)->i_disksize = attr->ia_size;
rc = ext3_mark_inode_dirty(handle, inode);
if (!error)
error = rc;
ext3_journal_stop(handle);
} rc = inode_setattr(inode, attr); if (!rc && (ia_valid & ATTR_MODE))
//由于在最后才调用ext3_acl_chmod,因而新的权限已经设置到inode中的访问控制部分,因而需要将指向所述struct inode实例的指针作为参数输入
rc = ext3_acl_chmod(inode); err_out:
ext3_std_error(inode->i_sb, error);
if (!error)
error = rc;
return error;
}

ext3_acl_chmod的运作逻辑如下
\linux-2.6.32.63\fs\ext3\acl.c

int ext3_acl_chmod(struct inode *inode)
{
struct posix_acl *acl, *clone;
int error; if (S_ISLNK(inode->i_mode))
return -EOPNOTSUPP;
if (!test_opt(inode->i_sb, POSIX_ACL))
return ;
//获得指向ACL数据内存表示的指针之后
acl = ext3_get_acl(inode, ACL_TYPE_ACCESS);
if (IS_ERR(acl) || !acl)
return PTR_ERR(acl);
//调用posix_acl_clone创建一个可工作的副本
clone = posix_acl_clone(acl, GFP_KERNEL);
posix_acl_release(acl);
if (!clone)
return -ENOMEM;
//主要工作委托给posix_acl_chmod_masq
error = posix_acl_chmod_masq(clone, inode->i_mode);
if (!error) {
handle_t *handle;
int retries = ; retry:
//启动事务处理
handle = ext3_journal_start(inode,
EXT3_DATA_TRANS_BLOCKS(inode->i_sb));
if (IS_ERR(handle)) {
error = PTR_ERR(handle);
ext3_std_error(inode->i_sb, error);
goto out;
}
//在获得事务句柄后,ext3_set_acl用来将修改后的ACL数据写回
error = ext3_set_acl(handle, inode, ACL_TYPE_ACCESS, clone);
//通知日志相关操作结束
ext3_journal_stop(handle);
if (error == -ENOSPC &&
ext3_should_retry_alloc(inode->i_sb, &retries))
goto retry;
}
out:
//释放ACL副本
posix_acl_release(clone);
return error;
}

aaarticlea/png;base64,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" alt="" />

更新ACL数据的一般性工作在posix_acl_chmod_masq中进行
\linux-2.6.32.63\fs\posix_acl.c

/*
* Modify the ACL for the chmod syscall.
*/
int posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
{
struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
struct posix_acl_entry *pa, *pe; /* assert(atomic_read(acl->a_refcount) == 1); */ //其中将遍历所有的ACL项
FOREACH_ACL_ENTRY(pa, acl, pe)
{
/*
属主、所在组、其他、ACL_MASK类型的ACL项都会相应更新,以反应最新的ACL数据
*/
switch(pa->e_tag)
{
case ACL_USER_OBJ:
pa->e_perm = (mode & S_IRWXU) >> ;
break; case ACL_USER:
case ACL_GROUP:
break; case ACL_GROUP_OBJ:
group_obj = pa;
break; case ACL_MASK:
mask_obj = pa;
break; case ACL_OTHER:
pa->e_perm = (mode & S_IRWXO);
break; default:
return -EIO;
}
} if (mask_obj) {
mask_obj->e_perm = (mode & S_IRWXG) >> ;
} else {
if (!group_obj)
return -EIO;
group_obj->e_perm = (mode & S_IRWXG) >> ;
} return ;
}

6. 权限检查

我们知道,内核提供了通用的权限检查函数generic_permission,其中可以集成一个特定于文件系统的处理程序,用于ACL检查,Ext3中,ext3_permission函数(在进行权限检查时,由VFS层调用)指示generic_permission将ext3_check_acl作为处理ACL相关工作的回调函数
/source/fs/ext3/acl.c

int ext3_permission(struct inode *inode, int mask, struct nameidata *nd)
{
return generic_permission(inode, mask, ext3_check_acl);
}

aaarticlea/png;base64,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" alt="" />
0x3: ext2中的实现

Ext2对ACL的实现,几乎与Ext3完全相同


3. 小结

传统上,UNIX和Linux使用自主访问控制模型来判断哪些用户可以访问给定的资源,资源一般表示为文件系统中的文件,它是一种非常粗粒度的安全手段
ACL可以向文件系统对象提供更细粒度的访问控制手段,即向每个对象附加一个显式列出访问控制规则的列表(主体-客体关系)
Linux基于扩展属性实现ACL,与从UNIX继承而来的传统模型相比,扩展属性方法能够向文件系统对象增加额外的、更复杂的属性

Copyright (c) 2015 LittleHann All rights reserved

Linux VFS Extended Attribute And Access Control Table的更多相关文章

  1. Linux访问控制列表(Access Control List,简称ACL)

    Linux访问控制列表(Access Control List,简称ACL) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.ACL概述 ACL:Access Control L ...

  2. Extensible Access Control List Framework

    Methods, systems, and products for governing access to objects on a filesystem. In one general embod ...

  3. Browser security standards via access control

    A computing system is operable to contain a security module within an operating system. This securit ...

  4. Enhancing network controls in mandatory access control computing environments

    A Mandatory Access Control (MAC) aware firewall includes an extended rule set for MAC attributes, su ...

  5. Access control differentiation in trusted computer system

    A trusted computer system that offers Linux® compatibility and supports contemporary hardware speeds ...

  6. Oracle Applications Multiple Organizations Access Control for Custom Code

    档 ID 420787.1 White Paper Oracle Applications Multiple Organizations Access Control for Custom Code ...

  7. Risk Adaptive Information Flow Based Access Control

    Systems and methods are provided to manage risk associated with access to information within a given ...

  8. SELINUX、Security Access Control Strategy && Method And Technology Research - 安全访问控制策略及其方法技术研究

    catalog . 引言 . 访问控制策略 . 访问控制方法.实现技术 . SELINUX 0. 引言 访问控制是网络安全防范和客户端安全防御的主要策略,它的主要任务是保证资源不被非法使用.保证网络/ ...

  9. 转:Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)

    什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...

随机推荐

  1. Cordova - 使用Cordova开发iOS应用实战4(调用摄像头拍照,并编辑)

    使用Cordova可以很方便的通过js代码来使用设备摄像头拍照,只需把camera插件添加进来即可. 一,添加camera插件 首先我们要在“终端”中进入工程所在的目录,然后运行如下命令: 1 cor ...

  2. Hangfire项目实践

    Hangfire项目实践分享 Hangfire项目实践分享 目录 Hangfire项目实践分享 目录 什么是Hangfire Hangfire基础 基于队列的任务处理(Fire-and-forget ...

  3. es6+react环境搭建

    工具说明 Node Koa React Webpack 项目结构 - build 客户端代码的构建文件目录 - config 项目的配置文件 - docs 项目相关的文档目录 - lib 服务端库文件 ...

  4. vbs http

    get请求 模拟发送http请求到百度Dim httpSet http = CreateObject("Msxml2.ServerXMLHTTP")http.open " ...

  5. JavaEE PO VO BO DTO POJO DAO 整理总结

    佩服能将复杂难懂的技术,抽象成简单易懂事物的人. 厌恶将简单易懂的技术,添加一堆专业术语将别人弄的头晕目眩的人. PO VO BO DTO POJO DAO 总体一览: 1.DAO[data acce ...

  6. .Net下一个类型转换神器

    引言 类型转换经常遇到,最常用的应该是string类型转换为其它基元类型,常见于http参数类型转换.Convert静态类的Convert.ChangeType()方法可以把实现IConvertibl ...

  7. (十一)外观模式详解(Service第三者插足,让action与dao分手)

    作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可. 各位好,LZ今天给各位分享一 ...

  8. DateTime.Now.ToString() 用法

    //2008年4月24日 System.DateTime.Now.ToString("D"); //2008-4-24 System.DateTime.Now.ToString(& ...

  9. Matlab中给figure添加图例(legend),标题(title)和颜色(color)

    在Matlab绘图过程中,尤其是需要将多个图绘制在相同的坐标轴中时,通常需要将不同的曲线设置成为不同的颜色.此外,为了直观,还需要给这张图标增添标题和图例.这篇文章展示了在Matlab的绘图窗口(fi ...

  10. 十天冲刺---Day8

    站立式会议 站立式会议内容总结: 燃尽图 照片 最近思考一个问题.项目是怎么进行到这一步的. 算了,这个发在明天的冲刺总结吧.. 还需继续努力,队友快回来快回来..