Multics supported an extension of the privileged mode idea via an access control mechanism based on a ring structure. In that system, the hardware supported not two modes (kernel and user) per process, but up to 64. The access rights of a process changed when it executed not only kernel procedures, but also ordinary procedures stored in users' segments.
Each mode was called a ring, and was associated with a set of access rights. The rings in the system were hierarchically arranged: the innermost ring had the most power and the outermost ring the least. In general the access rights associated with ring i were a superset of the access rights of ring i+1.
In Multics, each object is accessed via a segment, and each segment was associated with one of the rings. A segment description contained an entry that defined the ring number. In addition, it contained three access bits to control reading, writing, and execution. With each process a current-ring-number counter was associated, which determined the current access rights of the process. A process executing in ring i could read and write a segment in ring j, j >= i, but could not read or write a segment in ring j, j < i. It could, however, execute a segment in any ring, when its current-ring-number were changed to that of the executed segment.
Here is a use of the rings facility, assuming there are four rings.
the most powerful mode, would be devoted to the kernel.
could contain the mail program, which needs to be able to create files in arbitrary directories.
could contain a grading program used to evaluate student programs, and ring 3 could contain the student programs.
This scheme, as stated above, is unsatisfactory for two reasons: First, a process in an outer ring should not be able to execute any instruction in an inner ring. In particular a user process should not be able to execute any instruction in the kernel, which is kept in ring 0. Instead, it should be able to execute an inner segment at certain special entry points. Second, every segment in an inner ring should not be executable by all the outermost rings. For instance student programs, in our example, should not be able to call the grading program.
To overcome these drawbacks, Multics supports a modification of the scheme outlined above. It stores in a segment descriptor, instead of a single ring number, the the following fields:
Access bracket: A pair of integers, b1 and b2, such that b1 <= b2.
Limit: An integer b3, such that b3 >= b2.
List of gates: The entry points (gates) at which the segments may be called.
If a process executing in ring i tried to execute a segment with access bracket ( b1, b2), then the call was allowed if b1 <= i <= b2, and the current ring number of the process remained i. Otherwise, a trap to the kernel occurred and the situation was handled as follows:
If i <= b1, then the call was allowed to occur and the current-ring-no of the process was changed to b1. Thus the access rights of the process are reduced. If parameters are passed to which refer to segments in a ring lower than b1, then these segments were copied into an area accessible in ring b1.
If i > b2, then the call was allowed to occur only if i <= b3, and the call had been directed to one of the designated entry points in the list-of-gates. If the call was successful, the current-ring-no of the process was changed to b2. This scheme allowed processes with limited access rights to call procedures in lower rings with more access rights, but only in a carefully controlled manner.
Regarding R/W, these rules imply that a process with ring i that tries to R/W a segment with access bracket ( b1, b2), is allowed to do so if i <= b2.
Now, in our example, the kernel would be associated with the access bracket (0, 0), limit 3, and the list of gates containing entry points of the system calls and the grading program could be associated with the access bracket (1, 1), and the limit 1.
The Multics scheme still had the disadvantage that ring (hierarchical)
structure did not allow enforcement of the need-to-know principle.
If an object was to be accessible in ring i,
but not in j,
then it was necessary that i < j.
But this meant that every object accessible in ring j was
accessible in ring i.