文件保护

文件要防两类事故:人为的非法访问,以及系统故障造成的数据丢失。后者靠备份与一致性检查解决,本节只讲前者——如何确保只有被授权的用户能对文件做被授权的操作。

这一节考点集中,且有一处判断题的常见陷阱:删除一个文件,检查的不是这个文件的权限。

机制

访问类型

保护机制要区分的不是”能不能访问”,而是”能做哪种访问”。王道列出六种访问类型:读、写、执行、添加、删除、列表清单(列出文件名和文件属性)。

把”写”和”添加”分开是有意义的:日志文件通常只允许追加而不允许改写已有内容,这样即使攻击者拿到权限,也无法抹掉此前的记录。同理,“列表清单”与”读”分开,意味着一个用户可以知道某个文件存在、却读不到它的内容。

口令保护

为文件设置一个口令,用户请求访问时必须提供正确的口令。口令通常存放在该文件对应的 FCB 或索引节点中。

疑问点:口令保护的实现方式与口令的存放位置

口令保护具体怎么实现,口令存放在什么地方。

口令随文件本身走,存在文件的 FCB 或索引节点里;验证动作由操作系统完成。 用户提交口令后,系统把它与 FCB 中记录的那个值比对,一致才放行。

优点是时间开销和空间开销都很小——只多存一个字段,只多做一次比对。

缺点也正来自这个实现方式:口令以系统能读取的形式保存在系统内部。 既然操作系统要拿它来比对,它就必须是可读的,因此有权限查看系统数据结构的人(如系统管理员)能够直接看到口令。这就是教材说它”不够安全”的确切含义——不安全之处不在于口令太短,而在于它根本没有对系统保密。

加密保护

用一个密码对文件本身进行加密,写入时编码、读出时译码。

它的关键优势是:密码不需要存储在系统中。 用户每次提供密码,系统用它去解密,密码本身用完即弃。系统里既然没有存过密码,管理员也就无从窃取——这恰好补上了口令保护的那个洞。

代价是编码和译码要花费大量时间,每一次读写都要多做一遍变换。

访问控制

在每个文件的 FCB 或索引节点中增加一个访问控制表(ACL),表中记录了各个用户可以对该文件执行哪些操作。

问题在于:一个系统可能有成千上万个用户,若为每个文件都列出全部用户的权限,这张表会比文件本身还大。因此实际系统采用精简的访问列表——把用户分成三类:

  • 拥有者(Owner):创建该文件的用户。
  • 组(Group):一组需要共享该文件、具有相似权限的用户。
  • 其他(Other):系统内的所有其他用户。

每类只需三位(读 / 写 / 执行),三类共九位就能表达完整的权限。 这正是 UNIX 与 Linux 中 rwxr-xr-- 这种表示法的由来,也是它只用两个字节就能取代一张大表的原因。

访问矩阵与它的两种切分

// TODO 补一个示例表

把保护问题一般化,可以画成一张访问矩阵:行是用户(域),列是对象(文件),矩阵元素是该用户对该文件拥有的权限集合。

这张矩阵通常极其稀疏,直接存储非常浪费,因此实际系统按两个方向之一把它切开:

按列切分,得到访问控制表(ACL)——每个文件一张表,记录”哪些用户能对我做什么”。表随文件走,存在 FCB 或 inode 里。

按行切分,得到访问权限表(能力表,Capability List)——每个用户一张表,记录”我能对哪些文件做什么”。表随用户走。

两者是同一张矩阵的两种投影,能表达的信息完全相同,差别在于查询方向:想知道”谁能动这个文件”用 ACL 一目了然,想知道”这个用户能动哪些文件”则要遍历所有文件的 ACL。现实系统绝大多数选择 ACL,因为权限检查总是发生在”某用户要访问某文件”的时刻,而此时文件是已知的。

边界

目录的读、写、执行权限与文件完全不同

疑问点:访问控制在文件与目录上的不同含义

访问控制表在文件和目录上分别如何解释。

同样是 r、w、x 三个字母,作用在目录上时含义与作用在文件上时毫无关系。 记住目录也是一种文件,它的内容是目录项表,三个权限的含义就都能推出来:

目录的 r(读)= 能读出这张目录项表,即能列出目录中有哪些文件名。 没有 r 就无法执行 ls。

目录的 w(写)= 能修改这张目录项表,即能在该目录中创建、删除、重命名文件。

目录的 x(执行)= 能”穿过”这个目录去访问它里面的东西。 路径解析每经过一级目录,都要检查这一级的 x 权限;没有 x,即使知道里面某个文件的完整路径也进不去。

由此得到本节最重要的一条结论,也是判断题最爱设的陷阱:

能否删除一个文件,取决于其所在目录的 w 权限,与该文件自身的权限无关。

理由是纯粹机械的:删除文件的动作是”把父目录里的那个目录项抹掉”(见 4.1.3),改的是目录文件的内容,而不是被删文件的内容。所以系统检查的自然是对目录的写权限。

这条结论的两个反直觉推论都要记住:一个自己没有任何权限的文件,只要对它所在的目录有写权限,就能删掉它;反过来,一个自己拥有完全权限(rwx)的文件,若对其所在目录没有写权限,就删不掉。

同理,创建文件和重命名文件也都是在改目录,检查的都是父目录的权限——而且因为要先”进入”那个目录才能改它,实际需要的是父目录的 w 加 x 两项。

口令保护与加密保护的分界

两者常被并列,但防的其实不是同一类对手:

口令保护防的是”其他普通用户”,它假定操作系统是可信的。加密保护连操作系统本身都不信任——文件在磁盘上就是密文,即使整块磁盘被人拿走、即使管理员翻遍系统数据结构,也拿不到明文。

判断依据只有一条:密码存不存在系统里。 存了就是口令保护,没存就是加密保护。这个判据同时解释了两者的优缺点——存了所以快、所以不安全;没存所以安全、所以每次都要重新做变换。

保护与共享是一对矛盾

文件保护要限制访问,文件共享要放开访问,两者天然对立。精简的访问列表正是这对矛盾的折中产物:Owner 位保护、Group 位共享、Other 位兜底,用三档粒度同时满足两个方向的需求。

若粒度再粗(只有”能”与”不能”),就无法共享;若粒度再细(逐用户列举),表又大到不可用。 三档是工程上取得的平衡点。

对照速查

访问类型六种
读、写、执行、添加、删除、列表清单
保护方法密码存哪优点缺点
口令保护FCB / 索引节点中时间、空间开销都小口令对系统不保密,不够安全
加密保护不存储保密性强编码译码耗时
访问控制ACL 在 FCB / 索引节点中粒度灵活表可能过大,故用精简形式
访问矩阵的两种切分一张表属于谁回答什么问题
访问控制表 ACL(按列)每个文件一张哪些用户能动这个文件
访问权限表 / 能力表(按行)每个用户一张这个用户能动哪些文件
权限作用在文件上作用在目录上
r读文件内容能 ls,列出文件名
w改文件内容能在其中创建 / 删除 / 重命名文件
x执行该文件能穿过它进入下级路径
操作检查谁的权限
读 / 写文件内容文件自身
删除文件父目录的 w
创建文件父目录的 w + x
沿路径访问途经每一级目录的 x

考点

  • 六种访问类型,注意**“添加”与”写”分开**、“列表清单”与”读”分开
  • 口令存在 FCB / 索引节点中,因此对系统不保密——这是它不安全的确切原因
  • 加密保护的密码不存储在系统中,这是它与口令保护的唯一判据
  • 精简访问列表 = Owner / Group / Other × rwx,共九位
  • ACL 按列切分(每文件一张),能力表按行切分(每用户一张)
  • 目录的 r/w/x 含义与文件完全不同
  • 删除文件看父目录的 w,与文件自身权限无关(高频陷阱)

链接