acl源码分析(一)

2021SC@SDUSC 

        先简单说一下Linux的文件权限,在Linux下,一个文件的操作对象可以分为三类:user,group,other,文件的权限也有三种:read,write,execute。那么对于user和group来说,他们有文件的rwx三种权限,而other的权限为0。这就是UGO权限,它最大的缺点是无法为额外的用户设置合适的权限。

        ACL(Access Control List)是访问控制列表,在Linux中用于设定用户针对文件的权限,它是对UGO权限管理的补充。ACL可以对额外的某个用户或用户组设置权限,即不只有文件的user和group可以访问该文件,可以解决UGO无法解决的情况。举个例子,在UGO权限下,一个文件有一个user和一个group,他们有文件的rwx权限,此外的其他人都是无权限的,此时有一个人需要该文件的r权限,但又不属于该文件的group,就需要ACL专门为此用户设置权限。如果没有ACL 的话,只能将该用户加入group或other中,那么在group中用户会得到额外的权限,在other中又需要给予other这个群体中所有用户同等的权限,这种设定是很不合理的。

        在posix标准里,一个acl结构体定义如下
                typedef struct {
                        __le16   e_tag;
                        __le16   e_perm;
                        __le32   e_id;
                } posix_acl_xattr_entry;

         e_tag即Entry tag type 有以下六种类型:

                ACL_USER_OBJ:相当于user的权限

                ACL_USER:是ACL定义的其他用户的权限

                ACL_GROUP_OBJ:相当于group的权限

                ACL_GROUP:是ACL定义的其他用户组的权限

                ACL_MASK:定义了ACL_USER,ACL_GROUP_OBJ和ACL_GROUP的最大权限,即如果mask存在,那么获取的权限的值为mask的值,而非group或user的实际权限,可能mask为rwx,group为rw。

                ACL_OTHER:相当于other的权限

        e_perm代表权限,就是rwx三种权限。

        e_id标识唯一的用户或用户组,并且只有ACL_USER和ACL_GROUP有值,因为只有这两个tag是定义了额外的用户权限。

        简单地来说ACL就是可以设置特定用户或者用户组对于一个文件或目录的操作权限,分为Access ACL和Default ACL,分别对文件和目录进行操作,Default ACL是指对于一个目录进行Default ACL设置,并且在此目录下建立的文件都将继承此目录的ACL。关于ACL需要掌握的命令也只有三个: getfacl, setfacl, chacl。getfacl命令是用来读取文件的ACL;setfacl是用来设定文件的ACL;chacl是用来改变文件和目录的Access ACL和Default ACL。

        那么先分析acl.h文件,ext2_acl_entry是ext2文件系统的acl结构体,遵循posix标准,ext2_acl_entry_short则取消了e_id。ext2_acl_header则只有版本号。
                typedef struct {
                    __le16        e_tag;
                    __le16        e_perm;
                    __le32        e_id;
                } ext2_acl_entry;
                typedef struct {
                    __le16        e_tag;
                    __le16        e_perm;
                } ext2_acl_entry_short;

                typedef struct {

                        __le32 a_version;

                 } ext2_acl_header;

        以下函数能根据acl项目的数目获得ext2的acl大小,因为共有六种e_tag,如果count<=4,那么 必然是ACL_USER_OBJ、ACL_GROUP_OBJ、ACL_MASK、ACL_OTHER中的几个,即是没有e_id字段,那么只需要ext2_acl_header的大小ext2_acl_header的大小加上count乘ext2_acl_entry_short的大小;否则ext2_acl_header的大小需要加上4个ext2_acl_entry_short的大小和(count-4)个ext2_acl_entry的大小。

               static inline size_t ext2_acl_size(int count)
               {
                    if (count <= 4) {
                        return sizeof(ext2_acl_header) +
                               count * sizeof(ext2_acl_entry_short);
                    } else {
                        return sizeof(ext2_acl_header) +
                              4 * sizeof(ext2_acl_entry_short) +
                               (count - 4) * sizeof(ext2_acl_entry);
                    }
                }

        以下函数能根据acl大小获得ext2的acl项目的数目,是上面函数的逆推。分析算法,如上一个函数所示,每个size都有一个ext2_acl_header,那么size先减去ext2_acl_header的大小,此时有两种情况,一是count<=4,一是count>4,区分方法就是size减去4*ext2_acl_entry_short,小于0说明count<=4,那么count计算方法就是上面函数的倒推了。

                static inline int ext2_acl_count(size_t size)
                {
                    ssize_t s;
                    size -= sizeof(ext2_acl_header);
                    s = size - 4 * sizeof(ext2_acl_entry_short);
                    if (s < 0) {
                        if (size % sizeof(ext2_acl_entry_short))
                            return -1;
                        return size / sizeof(ext2_acl_entry_short);
                    } else {
                        if (s % sizeof(ext2_acl_entry))
                            return -1;
                        return s / sizeof(ext2_acl_entry) + 4;
                    }
                }

        下面是一段if else 的结构,是关于ACL的一些config,如果定义了CONFIG_EXT2_FS_POSIX_ACL,就采用第一段配置,否则用第二段。

                #ifdef CONFIG_EXT2_FS_POSIX_ACL
                /* Value for inode->u.ext2_i.i_acl and inode->u.ext2_i.i_default_acl
                   if the ACL has not been cached */
                #define EXT2_ACL_NOT_CACHED ((void *)-1)
                /* acl.c */
                extern int ext2_permission (struct inode *, int, struct nameidata *);
                extern int ext2_acl_chmod (struct inode *);
                extern int ext2_init_acl (struct inode *, struct inode *);
                #else
                #include <linux/sched.h>
                #define ext2_permission NULL
                #define ext2_get_acl    NULL
                #define ext2_set_acl    NULL
                static inline int
                ext2_acl_chmod (struct inode *inode)
                {
                    return 0;
                }
                static inline int ext2_init_acl (struct inode *inode, struct inode *dir)
                {
                    return 0;
                }
                #endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值