Linux VFS Extended Attribute And Access Control Table
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的更多相关文章
- Linux访问控制列表(Access Control List,简称ACL)
Linux访问控制列表(Access Control List,简称ACL) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.ACL概述 ACL:Access Control L ...
- Extensible Access Control List Framework
Methods, systems, and products for governing access to objects on a filesystem. In one general embod ...
- Browser security standards via access control
A computing system is operable to contain a security module within an operating system. This securit ...
- 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 ...
- Access control differentiation in trusted computer system
A trusted computer system that offers Linux® compatibility and supports contemporary hardware speeds ...
- Oracle Applications Multiple Organizations Access Control for Custom Code
档 ID 420787.1 White Paper Oracle Applications Multiple Organizations Access Control for Custom Code ...
- Risk Adaptive Information Flow Based Access Control
Systems and methods are provided to manage risk associated with access to information within a given ...
- SELINUX、Security Access Control Strategy && Method And Technology Research - 安全访问控制策略及其方法技术研究
catalog . 引言 . 访问控制策略 . 访问控制方法.实现技术 . SELINUX 0. 引言 访问控制是网络安全防范和客户端安全防御的主要策略,它的主要任务是保证资源不被非法使用.保证网络/ ...
- 转:Oracle R12 多组织访问的控制 - MOAC(Multi-Org Access Control)
什么是MOAC MOAC(Multi-Org Access Control)为多组织访问控制,是Oracle EBS R12的重要新功能,它可以实现在一个Responsibility下对多个Opera ...
随机推荐
- XMLHTTPRequest/Ajax请求 和普通请求的区别
Ajax请求头会多一个x-requested-with参数,值为XMLHttpRequest 详情:http://blog.csdn.net/zhangdaiscott/article/details ...
- java 中的异步回调
异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...
- java:利用xpath删除xml中的空节点
原始xml内容: <data> <a> </a> <b>b1</b> <awb> <awbpre>123</a ...
- Android -- ViewDragHelper
ViewDragHelper SlidingPaneLayout和DrawerLayout,现在这俩个类被广泛的运用,其实研究他们的源码你会发现这两个类都运用了ViewDragHelper来处理拖动. ...
- Java 的世界,我不懂:奇葩的 json 序列化
先上张图,代表我心中的十万头草泥马: 写这么长的代码,头回见数组和单个实体共用同一个 json 节点的! 恐怕只有 java 社区的大牛B 才能做出这等事.. 由 Apache 发布: http:// ...
- 求height数组
procedure getheight; var i,po1,po2:longint; begin to len do begin ; po1:=i;po2:=sa[rank[i]-]; while ...
- 通过Ajax实现增删改查
项目链接:https://github.com/shuai7boy/Ajax_CRUD 简要截图:
- js 技巧和细节
1. if中的各种变量返回值 一个值为 true 或者 false 的表达式.如果需要,非 Boolean 表达式也可以被转换为 Boolean 值,但是要遵循下列规则: 所有的对象都被当作 true ...
- swift 学习(一)基础知识 (基本数据类型,操作符,流控制,集合)
xcode 中调用API帮助 1.查看简单信息,选中后 按键 control +左键单击 或者按 右侧属性栏 里的帮助按钮 2.完整API,选中后 按键 control +左键双击 3.查看类.函数 ...
- java判断request请求是手机还是pc终端
/** * 判断请求是否手机端 * @param req * @return */ public static boolean isMobile(HttpServletRequest req) { U ...