All of the capability systems that I have seen use capabilities constructed of bits. Some, like Keykos, largely conceal the bits from the holders of capabilities. Keykos lets a few programs see those bits but even those programs cannot turn such bits into a capability. Those few programs able to see the bits do so via a closely held special primitive capability (Keybits in the case of Keykos) to which they send the capability whose bits they need.
For other systems, such as password systems, knowing the capability’s bits suffices to wield the capability. Knowing the bits is to hold the capability. Authority is limited by restricting knowledge of the bits, and conveyed by transmitting them.
Among the systems that hide the bits from capability holders, there is another difference. IBM’s System 38 devoted a hardware bit in memory in each 16 memory bit word to mark a location as holding part of a capability. Capabilities were 64 bits long and intermixed with other user data in memory but “hidden” by the extra bit in memory so as to make the bits therein unreadable and unmodifiable by “user code”. The System 38 was not the first to protect capabilities amidst user data but it may have been the last. IBM’s AS/400 is in some sense a descendent of the System 38. (It is now the iSeries and now System i.) The 38 provided a language called “MI” (Machine Interface) that, like Java byte codes, was translated before execution. The translator was trusted but not enough to dispense with the hardware to protect the capability bits.
Systems with special hardware support for capabilities generally arranged for special software to be able to read and write the bits of capabilities. The Plessey 250 would simultaneously map into a trusted program’s space, the same physical memory segment as a capability segment and also as a data segment.
Susan Rajunas said of Keykos: “If it not in a slot, it is not a capability”. Nodes carry all the capabilities in Keykos, 16 slots per node.
In this note we call capabilities whose bits are concealed, abstracted capabilities. The Password-Capability System system is the only system I know that has proposed a coherent non-abstracted scheme that supports confinement, and I am not sure how complete that design is. I do not now recall how it works. Most current capability systems use abstracted capabilities. There are simple philosophical reasons to abstract the bits, but deeper and complex engineering reasons as well.
Here are some ramifications of non-abstracted capabilities:
The mechanics of capability security stem fundamentally from the inability of programs to produce bits and then use them as capabilities. The C program statement “(int *)0 = 42;” is an example of what capability systems, such as Java and Keykos, prevent. When programs can do this then no object in the space is safe from any other.
The dangers of disclosing the bits within capabilities to the holders of those capabilities is more obscure. “(int)&j” as a C expression does not endanger other programs. It may, however cause the program in which it occurs to behave erratically. C programmers do not generally expect deterministic environments but it is possible to provide program environments where programs will replay exactly even against the wishes of the programmer. While this is a valuable tool, there are rare legitimate requirements to avoid replay. Programs with such requirements must make extraordinary arrangements with the provider of their environment.
Java allows the expression “(new int).toString()” which produces undocumented and variable values. This seems to be counter to the Java principle that programs in the core language produce predictable results that are exactly the same across implementations. Java still prevents the conversion of data to capabilities (references) and thus maintains security. In the terms of this note I would call Java a capability system that abstracts capabilities (object references) but still reveals their bits.