文件保护
文件要防两类事故:人为的非法访问,以及系统故障造成的数据丢失。后者靠备份与一致性检查解决,本节只讲前者——如何确保只有被授权的用户能对文件做被授权的操作。
这一节考点集中,且有一处判断题的常见陷阱:删除一个文件,检查的不是这个文件的权限。
机制
访问类型
保护机制要区分的不是”能不能访问”,而是”能做哪种访问”。王道列出六种访问类型:读、写、执行、添加、删除、列表清单(列出文件名和文件属性)。
把”写”和”添加”分开是有意义的:日志文件通常只允许追加而不允许改写已有内容,这样即使攻击者拿到权限,也无法抹掉此前的记录。同理,“列表清单”与”读”分开,意味着一个用户可以知道某个文件存在、却读不到它的内容。
口令保护
为文件设置一个口令,用户请求访问时必须提供正确的口令。口令通常存放在该文件对应的 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,与文件自身权限无关(高频陷阱)
链接
- 🏠 返回总览:操作系统第 4 章:文件管理总览
- ⬅️ 上一节:4.1.5 文件的物理结构
- ➡️ 下一节:4.2.1 目录的基本概念
- 🔗 保护与共享的对立,见 4.2.5 文件共享
- 📖 名词库:第 4 章名词库