Linux上的Posix访问控制链表
时间:2010-09-05 来源:sujinxiu-linux
上一篇博客我们提到传统的UGO的限制以及日继细腻化的安全需求导致了ACLs的产生。我们知道文件系统控制链表已经在几个类unix操作系统中实现了。那么具体他们是怎么实现的了?
说到ACLs,不得不提到的是EAs。linux和很多其他的类unix操作系统一个更普遍的机制叫做EAs。在这些系统里面,ACL称为EAs(Extended Attributes)。扩展属性是和文件系统对象有关的名称和值,类似于进程的环境变量。EA系统调用作为一个用户空间和内核空间接口来将扩展属性的名称和值在用户和内核地址空间相互拷贝。Linux attr手册包含了EAs在linux里面更完整的描述。
那么EAs是如何实现的了?在文件系统层面,最明显的也是最直接的实现EA的方式是对于每个文件系统对象创建一个另外的有扩展属性的路径。对于每一个扩展属性创建一个有属性名称和属性值的文件。因为在大多数文件系统中,分配另外的目录需要一个或者几个文件请求几个硬盘块。如此的一个简单的实现方式是需要花很多空间的。他将不会运作得非常好,因为需要很多时间去访问磁盘。因此,大多数文件系统用不同的机制存储EA。
那么我们传统的EXT2和EXT3文件系统中的EAs是什么样子的了?
由于历史原因,每个inode有一个i_file_acl域。如果它不为0,则它包含与ea相关的inode的文件系统块的编号。这个块包括有与EA有关的inode的名称和属性。一个inode节点的所有EA必须在相同的EA磁盘块上。
为了提高效率,多个有着相同的EA的inodes可能会指向同一个EA块。指向一个EA块的inode的数目由EA块的相关的一个计数跟踪。EA块共享对于用户时透明的。EXT3用一个LRU链表保存了最近常访问的EA块,还有一个表索引用来记录块的编号。另外的是块内容的校验码。块与一个新的inode有相同数据的块直至块相关计数到达上限1024后才能被重新使用。这就限制了对于一个单独的磁盘块损坏的情况发生。当一个inode指向一个共享的EA块时,那个inode的EA改变了,一个写时复制机制就会产生作用了。除非另外一个cached EA 块已经有相同的属性但是正在被使用。一个inode的EAs必须放在同一个磁盘块中。
如果EA对于inode之间是独一无二的,那么共享是不存在的,花在检查潜在的共享是浪费时间的。如果每个inode都有一个独一无二的EA集合,每个EA集合存储在一个单独的磁盘块上面,这将会需要很多slack空间。极端的是需要存储每个inode的独一无二的EA。幸运的是对于很多普通的工作路线,EA共享机制是很有效的。
限制比较少的可选的设计已经提出了,但是很难实现。目前还没有实现。我们来看看其他的一些文件系统是怎么做的。
JFS在文件系统的一段连续的块空间存储一个inode的EAs。扩展属性的名称和值是连续存储的。如果整个EAs足够小,则可以直接将存储到它所属于的inode里面。JFS没有实现共享。它没有EXT2中的EAs存储在一个磁盘块的限制。
XFS存储机制比较细致。小的存储到inode里面,再大些的存储到B+树的leaf blocks中,更大的存储到完全B+树中。尽管很少需要,但是大量的EAs可以有效的被存储。在创建文件系统时,XFS可配置的inode大小。最小256 bytes,也是默认的,最大的是文件系统块的一个半。最小的时候,inode太小没有办法保存acl,所以他们会另外才存储。如果inode的大小改变了,acl将会存储到inode中。由于inodes和ACLs经常会在一个很短的时间内访问,这导致了快速访问检查。但是依然浪费了磁盘空间。XFS也没有实现共享机制。
REISERFS 支持文件的尾连接,意味着几个文件可以共享相同的磁盘块来存储数据。这使得文件系统对于小文件非常有效,花费了比较少的cpu时间。由于REISERFS很擅长处理小文件,EAs可以直接利用这个机制。对于有EAs的任意一个文件,一个目录这个特别的目录在文件系统的namespace是隐藏的。在inode的特殊目录下,每个EA都已一个单独的文件存储。这个文件的名称等于属性的名称,文件的内容是属性的值。REISERFS没有实现共享机制。但是很有可能会马上实现。
一个有趣的设计讨论是:ACLs是如何在用户空间以及内核空间传递,如何在内核空间,如何在虚拟文件系统和具体的底层文件层之间传递的。我们知道系统调用是在用户空间与内核空间的唯一接口。FREEBSD,SOLARIS有ACL有单独的系统调用,而LINUX是没有acl相关的系统调用。linux里面,acl在内核和用户空间以EAs相互传递。这减少了系统接口,但是具体的操作还是一样的。尽管ACL系统调用提供了一个更明确的系统接口,但EA接口更容易适应未来的要求。例如在ACLs中用户和组的非数字标识符。
在FreeBSD中使用另外的ACL系统调用是因为有的文件系统支持EAs但是不支持ACLs。有的文件系统支持ACLs但不支持EAs。所以EAs被处理为单纯的二进制文件。EAs和ACLs仅仅是在文件系统内有关系。
linux设计的想法是提供对一个文件系统的所有的元数据统一的接口。不同类别的属性用名称来识别,存储为系统对象例如ACL。文件系统没有实现ACLs但是实现了EAs。可能很容易通过EAs控制ACLs,在应用层这经常不是这样:EA系统调用是linux特有的,这些应用不会是可移植的。其他的系统支持相似的EA机制,但是却是不同系统调用接口。那些想以可移植的方式使用POSIX.1 ACLs的应用者,希望使用libacl library,可以实现基于 上一篇博客我们提到传统的UGO的限制以及日继细腻化的安全需求导致了ACLs的产生。我们知道文件系统控制链表已经在几个类unix操作系统中实现了。 那么具体他们是怎么实现的了?
说到ACLs,不得不提到的是EAs。linux和很多其他的类unix操作系统一个更普遍的机制叫做EAs。在这些系统里面,ACL称为 EAs(Extended Attributes)。扩展属性是和文件系统对象有关的名称和值,类似于进程的环境变量。EA系统调用作为一个用户空间和内核空间接口来将扩展属性的名 称和值在用户和内核地址空间相互拷贝。Linux attr手册包含了EAs在linux里面更完整的描述。
那么EAs是如何实现的了?在文件系统层面,最明显的也是最直接的实现EA的方式是对于每个文件系统对象创建一个另外的有扩展属性的路径。对于每一个扩展 属性创建一个有属性名称和属性值的文件。因为在大多数文件系统中,分配另外的目录需要一个或者几个文件请求几个硬盘块。如此的一个简单的实现方式是需要花 很多空间的。他将不会运作得非常好,因为需要很多时间去访问磁盘。因此,大多数文件系统用不同的机制存储EA。
那么我们传统的EXT2和EXT3文件系统中的EAs是什么样子的了?
由于历史原因,每个inode有一个i_file_acl域。如果它不为0,则它包含与ea相关的inode的文件系统块的编号。这个块包括有与EA有 关的inode的名称和属性。一个inode节点的所有EA必须在相同的EA磁盘块上。
为了提高效率,多个有着相同的EA的inodes可能会指向同一个EA块。指向一个EA块的inode的数目由EA块的相关的一个计数跟踪。EA块共享 对于用户时透明的。EXT3用一个LRU链表保存了最近常访问的EA块,还有一个表索引用来记录块的编号。另外的是块内容的校验码。块与一个新的 inode有相同数据的块直至块相关计数到达上限1024后才能被重新使用。这就限制了对于一个单独的磁盘块损坏的情况发生。当一个inode指向一个共 享的EA块时,那个inode的EA改变了,一个写时复制机制就会产生作用了。除非另外一个cached EA 块已经有相同的属性但是正在被使用。一个inode的EAs必须放在同一个磁盘块中。
如果EA对于inode之间是独一无二的,那么共享是不存在的,花在检查潜在的共享是浪费时间的。如果每个inode都有一个独一无二的EA集合,每个 EA集合存储在一个单独的磁盘块上面,这将会需要很多slack空间。极端的是需要存储每个inode的独一无二的EA。幸运的是对于很多普通的工作路 线,EA共享机制是很有效的。
限制比较少的可选的设计已经提出了,但是很难实现。目前还没有实现。我们来看看其他的一些文件系统是怎么做的。
JFS在文件系统的一段连续的块空间存储一个inode的EAs。扩展属性的名称和值是连续存储的。如果整个EAs足够小,则可以直接将存储到它所属于 的inode里面。JFS没有实现共享。它没有EXT2中的EAs存储在一个磁盘块的限制。
XFS存储机制比较细致。小的存储到inode里面,再大些的存储到B+树的leaf blocks中,更大的存储到完全B+树中。尽管很少需要,但是大量的EAs可以有效的被存储。在创建文件系统时,XFS可配置的inode大小。最小 256 bytes,也是默认的,最大的是文件系统块的一个半。最小的时候,inode太小没有办法保存acl,所以他们会另外才存储。如果inode的大小改变 了,acl将会存储到inode中。由于inodes和ACLs经常会在一个很短的时间内访问,这导致了快速访问检查。但是依然浪费了磁盘空间。XFS也 没有实现共享机制。
REISERFS 支持文件的尾连接,意味着几个文件可以共享相同的磁盘块来存储数据。这使得文件系统对于小文件非常有效,花费了比较少的cpu时间。由于REISERFS 很擅长处理小文件,EAs可以直接利用这个机制。对于有EAs的任意一个文件,一个目录这个特别的目录在文件系统的namespace是隐藏的。在 inode的特殊目录下,每个EA都已一个单独的文件存储。这个文件的名称等于属性的名称,文件的内容是属性的值。REISERFS没有实现共享机制。但 是很有可能会马上实现。
一个有趣的设计讨论是:ACLs是如何在用户空间以及内核空间传递,如何在内核空间,如何在虚拟文件系统和具体的底层文件层之间传递的。我们知道系统调 用是在用户空间与内核空间的唯一接口。FREEBSD,SOLARIS有ACL有单独的系统调用,而LINUX是没有acl相关的系统调用。linux里 面,acl在内核和用户空间以EAs相互传递。这减少了系统接口,但是具体的操作还是一样的。尽管ACL系统调用提供了一个更明确的系统接口,但EA接口 更容易适应未来的要求。例如在ACLs中用户和组的非数字标识符。
在FreeBSD中使用另外的ACL系统调用是因为有的文件系统支持EAs但是不支持ACLs。有的文件系统支持ACLs但不支持EAs。所以EAs被 处理为单纯的二进制文件。EAs和ACLs仅仅是在文件系统内有关系。
linux设计的想法是提供对一个文件系统的所有的元数据统一的接口。不同类别的属性用名称来识别,存储为系统对象例如ACL。文件系统没有实现ACLs 但是实现了EAs。可能很容易通过EAs控制ACLs,在应用层这经常不是这样:EA系统调用是linux特有的,这些应用不会是可移植的。其他的系统支 持相似的EA机制,但是却是不同系统调用接口。希望那些想以可移植的方式使用POSIX.1 ACLs的应用者能够使用libacl library,实现基于 POSIX.1e draft 17的ACL特有的函数。
下面来谈一下ACL的访问检查。访问检查在整个有namespace根到文件的路径都在进行。所以acl访问检查是有效的这点很重要。为了避免频繁的查找acl属性和从处理器相关的属 性转换到处理器独立的属性,EXT2等文件系统实现了缓存处理器独立的属性。这个已经加到一个普通的文件系统缓存机制里去。使用的页面缓存,缓冲区缓存或 者两个。XFS不使用这个另外的缓冲层。acl中有很多项是很难管理的。因此比较理智的是使用好groups,而不是茫目增大acl的项。
关于ACLs在机制方面就研究这么多。下面一篇博客我们来探讨一下ACLs的两个命令的具体实现过程。
说到ACLs,不得不提到的是EAs。linux和很多其他的类unix操作系统一个更普遍的机制叫做EAs。在这些系统里面,ACL称为EAs(Extended Attributes)。扩展属性是和文件系统对象有关的名称和值,类似于进程的环境变量。EA系统调用作为一个用户空间和内核空间接口来将扩展属性的名称和值在用户和内核地址空间相互拷贝。Linux attr手册包含了EAs在linux里面更完整的描述。
那么EAs是如何实现的了?在文件系统层面,最明显的也是最直接的实现EA的方式是对于每个文件系统对象创建一个另外的有扩展属性的路径。对于每一个扩展属性创建一个有属性名称和属性值的文件。因为在大多数文件系统中,分配另外的目录需要一个或者几个文件请求几个硬盘块。如此的一个简单的实现方式是需要花很多空间的。他将不会运作得非常好,因为需要很多时间去访问磁盘。因此,大多数文件系统用不同的机制存储EA。
那么我们传统的EXT2和EXT3文件系统中的EAs是什么样子的了?
由于历史原因,每个inode有一个i_file_acl域。如果它不为0,则它包含与ea相关的inode的文件系统块的编号。这个块包括有与EA有关的inode的名称和属性。一个inode节点的所有EA必须在相同的EA磁盘块上。
为了提高效率,多个有着相同的EA的inodes可能会指向同一个EA块。指向一个EA块的inode的数目由EA块的相关的一个计数跟踪。EA块共享对于用户时透明的。EXT3用一个LRU链表保存了最近常访问的EA块,还有一个表索引用来记录块的编号。另外的是块内容的校验码。块与一个新的inode有相同数据的块直至块相关计数到达上限1024后才能被重新使用。这就限制了对于一个单独的磁盘块损坏的情况发生。当一个inode指向一个共享的EA块时,那个inode的EA改变了,一个写时复制机制就会产生作用了。除非另外一个cached EA 块已经有相同的属性但是正在被使用。一个inode的EAs必须放在同一个磁盘块中。
如果EA对于inode之间是独一无二的,那么共享是不存在的,花在检查潜在的共享是浪费时间的。如果每个inode都有一个独一无二的EA集合,每个EA集合存储在一个单独的磁盘块上面,这将会需要很多slack空间。极端的是需要存储每个inode的独一无二的EA。幸运的是对于很多普通的工作路线,EA共享机制是很有效的。
限制比较少的可选的设计已经提出了,但是很难实现。目前还没有实现。我们来看看其他的一些文件系统是怎么做的。
JFS在文件系统的一段连续的块空间存储一个inode的EAs。扩展属性的名称和值是连续存储的。如果整个EAs足够小,则可以直接将存储到它所属于的inode里面。JFS没有实现共享。它没有EXT2中的EAs存储在一个磁盘块的限制。
XFS存储机制比较细致。小的存储到inode里面,再大些的存储到B+树的leaf blocks中,更大的存储到完全B+树中。尽管很少需要,但是大量的EAs可以有效的被存储。在创建文件系统时,XFS可配置的inode大小。最小256 bytes,也是默认的,最大的是文件系统块的一个半。最小的时候,inode太小没有办法保存acl,所以他们会另外才存储。如果inode的大小改变了,acl将会存储到inode中。由于inodes和ACLs经常会在一个很短的时间内访问,这导致了快速访问检查。但是依然浪费了磁盘空间。XFS也没有实现共享机制。
REISERFS 支持文件的尾连接,意味着几个文件可以共享相同的磁盘块来存储数据。这使得文件系统对于小文件非常有效,花费了比较少的cpu时间。由于REISERFS很擅长处理小文件,EAs可以直接利用这个机制。对于有EAs的任意一个文件,一个目录这个特别的目录在文件系统的namespace是隐藏的。在inode的特殊目录下,每个EA都已一个单独的文件存储。这个文件的名称等于属性的名称,文件的内容是属性的值。REISERFS没有实现共享机制。但是很有可能会马上实现。
一个有趣的设计讨论是:ACLs是如何在用户空间以及内核空间传递,如何在内核空间,如何在虚拟文件系统和具体的底层文件层之间传递的。我们知道系统调用是在用户空间与内核空间的唯一接口。FREEBSD,SOLARIS有ACL有单独的系统调用,而LINUX是没有acl相关的系统调用。linux里面,acl在内核和用户空间以EAs相互传递。这减少了系统接口,但是具体的操作还是一样的。尽管ACL系统调用提供了一个更明确的系统接口,但EA接口更容易适应未来的要求。例如在ACLs中用户和组的非数字标识符。
在FreeBSD中使用另外的ACL系统调用是因为有的文件系统支持EAs但是不支持ACLs。有的文件系统支持ACLs但不支持EAs。所以EAs被处理为单纯的二进制文件。EAs和ACLs仅仅是在文件系统内有关系。
linux设计的想法是提供对一个文件系统的所有的元数据统一的接口。不同类别的属性用名称来识别,存储为系统对象例如ACL。文件系统没有实现ACLs但是实现了EAs。可能很容易通过EAs控制ACLs,在应用层这经常不是这样:EA系统调用是linux特有的,这些应用不会是可移植的。其他的系统支持相似的EA机制,但是却是不同系统调用接口。那些想以可移植的方式使用POSIX.1 ACLs的应用者,希望使用libacl library,可以实现基于 上一篇博客我们提到传统的UGO的限制以及日继细腻化的安全需求导致了ACLs的产生。我们知道文件系统控制链表已经在几个类unix操作系统中实现了。 那么具体他们是怎么实现的了?
说到ACLs,不得不提到的是EAs。linux和很多其他的类unix操作系统一个更普遍的机制叫做EAs。在这些系统里面,ACL称为 EAs(Extended Attributes)。扩展属性是和文件系统对象有关的名称和值,类似于进程的环境变量。EA系统调用作为一个用户空间和内核空间接口来将扩展属性的名 称和值在用户和内核地址空间相互拷贝。Linux attr手册包含了EAs在linux里面更完整的描述。
那么EAs是如何实现的了?在文件系统层面,最明显的也是最直接的实现EA的方式是对于每个文件系统对象创建一个另外的有扩展属性的路径。对于每一个扩展 属性创建一个有属性名称和属性值的文件。因为在大多数文件系统中,分配另外的目录需要一个或者几个文件请求几个硬盘块。如此的一个简单的实现方式是需要花 很多空间的。他将不会运作得非常好,因为需要很多时间去访问磁盘。因此,大多数文件系统用不同的机制存储EA。
那么我们传统的EXT2和EXT3文件系统中的EAs是什么样子的了?
由于历史原因,每个inode有一个i_file_acl域。如果它不为0,则它包含与ea相关的inode的文件系统块的编号。这个块包括有与EA有 关的inode的名称和属性。一个inode节点的所有EA必须在相同的EA磁盘块上。
为了提高效率,多个有着相同的EA的inodes可能会指向同一个EA块。指向一个EA块的inode的数目由EA块的相关的一个计数跟踪。EA块共享 对于用户时透明的。EXT3用一个LRU链表保存了最近常访问的EA块,还有一个表索引用来记录块的编号。另外的是块内容的校验码。块与一个新的 inode有相同数据的块直至块相关计数到达上限1024后才能被重新使用。这就限制了对于一个单独的磁盘块损坏的情况发生。当一个inode指向一个共 享的EA块时,那个inode的EA改变了,一个写时复制机制就会产生作用了。除非另外一个cached EA 块已经有相同的属性但是正在被使用。一个inode的EAs必须放在同一个磁盘块中。
如果EA对于inode之间是独一无二的,那么共享是不存在的,花在检查潜在的共享是浪费时间的。如果每个inode都有一个独一无二的EA集合,每个 EA集合存储在一个单独的磁盘块上面,这将会需要很多slack空间。极端的是需要存储每个inode的独一无二的EA。幸运的是对于很多普通的工作路 线,EA共享机制是很有效的。
限制比较少的可选的设计已经提出了,但是很难实现。目前还没有实现。我们来看看其他的一些文件系统是怎么做的。
JFS在文件系统的一段连续的块空间存储一个inode的EAs。扩展属性的名称和值是连续存储的。如果整个EAs足够小,则可以直接将存储到它所属于 的inode里面。JFS没有实现共享。它没有EXT2中的EAs存储在一个磁盘块的限制。
XFS存储机制比较细致。小的存储到inode里面,再大些的存储到B+树的leaf blocks中,更大的存储到完全B+树中。尽管很少需要,但是大量的EAs可以有效的被存储。在创建文件系统时,XFS可配置的inode大小。最小 256 bytes,也是默认的,最大的是文件系统块的一个半。最小的时候,inode太小没有办法保存acl,所以他们会另外才存储。如果inode的大小改变 了,acl将会存储到inode中。由于inodes和ACLs经常会在一个很短的时间内访问,这导致了快速访问检查。但是依然浪费了磁盘空间。XFS也 没有实现共享机制。
REISERFS 支持文件的尾连接,意味着几个文件可以共享相同的磁盘块来存储数据。这使得文件系统对于小文件非常有效,花费了比较少的cpu时间。由于REISERFS 很擅长处理小文件,EAs可以直接利用这个机制。对于有EAs的任意一个文件,一个目录这个特别的目录在文件系统的namespace是隐藏的。在 inode的特殊目录下,每个EA都已一个单独的文件存储。这个文件的名称等于属性的名称,文件的内容是属性的值。REISERFS没有实现共享机制。但 是很有可能会马上实现。
一个有趣的设计讨论是:ACLs是如何在用户空间以及内核空间传递,如何在内核空间,如何在虚拟文件系统和具体的底层文件层之间传递的。我们知道系统调 用是在用户空间与内核空间的唯一接口。FREEBSD,SOLARIS有ACL有单独的系统调用,而LINUX是没有acl相关的系统调用。linux里 面,acl在内核和用户空间以EAs相互传递。这减少了系统接口,但是具体的操作还是一样的。尽管ACL系统调用提供了一个更明确的系统接口,但EA接口 更容易适应未来的要求。例如在ACLs中用户和组的非数字标识符。
在FreeBSD中使用另外的ACL系统调用是因为有的文件系统支持EAs但是不支持ACLs。有的文件系统支持ACLs但不支持EAs。所以EAs被 处理为单纯的二进制文件。EAs和ACLs仅仅是在文件系统内有关系。
linux设计的想法是提供对一个文件系统的所有的元数据统一的接口。不同类别的属性用名称来识别,存储为系统对象例如ACL。文件系统没有实现ACLs 但是实现了EAs。可能很容易通过EAs控制ACLs,在应用层这经常不是这样:EA系统调用是linux特有的,这些应用不会是可移植的。其他的系统支 持相似的EA机制,但是却是不同系统调用接口。希望那些想以可移植的方式使用POSIX.1 ACLs的应用者能够使用libacl library,实现基于 POSIX.1e draft 17的ACL特有的函数。
下面来谈一下ACL的访问检查。访问检查在整个有namespace根到文件的路径都在进行。所以acl访问检查是有效的这点很重要。为了避免频繁的查找acl属性和从处理器相关的属 性转换到处理器独立的属性,EXT2等文件系统实现了缓存处理器独立的属性。这个已经加到一个普通的文件系统缓存机制里去。使用的页面缓存,缓冲区缓存或 者两个。XFS不使用这个另外的缓冲层。acl中有很多项是很难管理的。因此比较理智的是使用好groups,而不是茫目增大acl的项。
关于ACLs在机制方面就研究这么多。下面一篇博客我们来探讨一下ACLs的两个命令的具体实现过程。
相关阅读 更多 +