A Hardware Architecture for Implementing Protection Rings Schroeder and Saltzer Protection rings * protection rings are a generalization of the user/supervisor bit found in most processors * instead of just two possible "protection modes", there can be many (Multics uses 8) * lower-numbered rings have more privilieges than higher-numbered rings (ring 0 is the most privileged) * Multics segment descriptor words contain indications of the highest-numbered rings that are allowed to read, or to write the segment (these are called the read/write brackets) * the execute bracket does not usually extend all the way down to ring 0, unlike the read and write brackets; in this way the low rings of the system can be protected against accidentally running code written by an unpriviliged user: the lowest ring that can execute a segment is the highest ring that can write to it, and the highest ring that can execute a segment is the highest ring that can read it Changing rings * segments can list "entry points" that are callable from higher-numbered rings, as well as a "gate extention", which is the highest ring number that can call entry points in this segment * if another segment running in a ring higher than the execute bracket, but within the gate extension, calls an entry point of a segment, control is transferred and the process starts to run in the highest ring of the execute bracket * changing to a higher ring can be accomplished by executing a "change ring and jump" instruction; the segment containing the destination of the jump must be executable in the new ring * some issues with procedure calls that cross rings to become more privileged: o the less-privileged caller must not be able to interfere with the stack of the more-privileged callee; this is ensured by giving each process one stack segment for each ring; the processor automatically uses the right stack segment for the current ring o the caller should not be allowed to pass argument pointers that point to data that the callee can reference, but the caller can't; when the callee reads the data, its permissions are temporarily lowered to those of the caller when accessing the parameter data o the callee must return to the appropriate ring; the processor assures this by keeping track of the ring the process was in when it did the call * calling less-privileged routines is much harder; Multics emulates this with software instead of implementing it in hardware Hardware help * in addition to the segment and offset, registers contain a ring field, indicating what ring is supposed to dereference the register; programs can not write to this register directly, but instead, the hardware fills it in when the register is written * the ring field is usually filled in with the ring number of the process that writes the register, but there are some exceptions: on an indirect reference, the ring field of the value that is eventually loaded is filled in with the higher of the current ring number and the ring field of the indirect pointer; this implements the lowering of permissions for reading arguments passed from a less-privilieged caller * see the flowcharts in the paper for far too much detail