预计阅读本页时间:-
9.3.3 权能
另一种切分图9-6矩阵的方法是按行存储。在使用这种方法的时候,与每个进程关联的是可访问的对象列表,以及每个对象上可执行操作的指示。这一栏叫做权能字列表(capability list或C-list),而且每个单独的项目叫做权能字(Dennis和Van Horn,1966;Fabry,1974)。一个3进程集和它们的权能字列表如图9-9所示。

每一个权能字赋予所有者针对特定对象的权限。如在图9-9中,用户A所拥有的进程可以读文件F1和F2。一个权能字通常包含了文件(或者更一般的情况下是一个对象)的标识符和用于不同权限的位图。在类似UNIX的系统中,文件标识符可能是i节点号。权能字列表本身也是对象,也可以从其他权能字列表处指定,这样就有助于共享子域。
很明显权能字列表必须防止用户进行篡改。已知的保护方法有三种。第一种方法需要建立带标记的体系结构(tagged architecture),在这种硬件设计中,每个内存字节必须拥有额外的位(或标记)来判断该字节是否包含了权限字。标记位不能被算术、比较或相似的指令使用,它仅可以被在核心态下运行的程序修改(如操作系统)。人们已经构造了带标记体系结构的计算机,并可以稳定地运行(Feustal,1972)。IBM AS/400就是一个公认的例子。
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
第二种方法是在操作系统里保存权能字列表。随后根据权能字在列表中的位置引用权能字。某个进程也许会说:“从权能字2所指向的文件中读取1KB”。这种寻址方法有些类似UNIX里的文件描述符。Hydra(Wulf等人,1974)采用的就是这种方法。
第三种方法是把权能字列表放在用户空间里,并用加密方法进行管理,这样用户就不能篡改它们。这种方法特别适合分布式操作系统,并可按下述的方式工作。当客户进程发送消息到远程服务器(如一台文件服务器)时,请求为自己创建一个对象时,服务器会在创建对象的同时创建一条长随机码作为校验字段附在该对象上。文件服务器为对象预留了槽口,以便存放校验字段和磁盘扇区地址等。在UNIX术语中,校验字段被存放在服务器的i节点中。校验字段不会返回用户,也决不会被放在网络上。服务器会生成并回送给用户如图9-10格式的权能字。

返回给用户的权能字包括服务器的标识符、对象号(服务器列表索引,主要是i-node码)以及以位图形式存放的权限。对一个新建的对象来说,所有的权限位都是处于打开状态的,这显然是因为该对象的拥有者有权限对该对象做任何事情。最后的字段包含了对象、权限以及校验字段。校验字段运行在通过密码体制保护的单向函数f上,我们已经讨论过这种函数。
当用户想访问对象时,首先要把权能字作为发送请求的一部分传送到服务器。然后服务器提取对象编号并通过服务器列表索引找到对象。再计算f(对象,权限,校验)。前两个参数来自于权能字本身,而第三个参数来自于服务器表。如果计算值符合权能字的第四个字段,请求就被接受,否则被拒绝。如果用户想要访问其他人的对象,他就不能伪造第四个域的值,因为他不知道校验字段,所以请求将被拒绝。
用户可以要求服务器建立一个较弱的权能字,如只读访问。服务器首先检查权能字的合法性,检查成功则计算f(对象,新的权限,校验)并产生新的权能字放入第四个字段中。请注意原来的校验值仍在使用,因为其他较强的权能字仍然需要该校验值。
新的权能字被被发送回请求进程。现在用户可以在消息中附加该权能字发送到朋友处。如果朋友打开了应该被关闭的权限位,服务器就会在使用权限字时检测到,因为f的值与错误的权限位不能对应。既然朋友不知道真正的校验字段,他就不能伪造与错误的权限位相对应的权能字。这种方法最早是由Amoeba系统开发的,后被广泛使用(Tanenbaum等人,1990)。
除了特定的与对象相关的权限(如读和执行操作)外,权能字中(包括在核心态和密码保护模式下)通常包含一些可用于所有对象的普通权限。这些普通权限有:
1)复制权能字:为同一个对象创建新的权能字。
2)复制对象:用新的权能字创建对象的副本。
3)移除权能字:从权能字列表中删去登录项;不影响对象。
4)销毁对象:永久性地移除对象和权能字。
最后值得说明的是,在核心管理的权能子系统中,撤回对对象的访问是十分困难的。系统很难为任意对象找到它所有显著的权能字并撤回,因为它们存储在磁盘各处的权能字列表中。一种办法是把每个权能字指向间接的对象,而不是对象本身。再把间接对象指向真正的对象,这样系统就能打断连接关系使权能字无效。(当指向间接对象的权能字后来出现在系统中时,用户将发现间接对象指向的是一个空的对象。)
在Amoeba系统结构中,撤回权能字是十分容易的。要做的仅仅是改变存放在对象里的校验字段。只要改变一次就可以使所有的失效。但是没有一种机制可以有选择性地撤回权能字,如,仅撤回John的许可权,但不撤回任何其他人的。这一缺陷也被认为是权限系统的一个主要问题。
另一个主要问题是确保合法权能字的拥有者不会给他最好的朋友1000个副本。采用核心管理权能字的模式,如Hydra系统,这个问题得到解决。但在如Amoeba这样的分布式系统中却无法解决这个问题。
另一方面,权能字非常漂亮地解决了移动代码的沙盒问题。当外来程序开始运行时,给出的权能字列表里只包含了机器所有者想要给的权能,如在屏幕上进行写操作以及在刚创建的临时目录里读写文件的权利。如果移动代码被放进了自己的只拥有这些有限权能的进程中,就无法访问其他任何资源,相当于被有效地限制在了沙盒里。这种方法不需要修改代码,也不需要解释性执行。当运行的代码拥有所需的最少访问权时,符合了最小特权规则,这也是建立安全操作系统的方针。