The virtual machine concept, which is designed to prevent programs from accessing anything outside their own virtual machine, is very far removed from the Stella ideal of providing mechanisms for simple, safe and efficient communications between software. The virtual machine concept of system security was originally designed for multi-user systems where the most important function of the operating system was to protect users from hostile intrusions by other users. Not only has thirty years of experience has shown that this protection is more notional than real, for most modern systems this superficial type of protection is no longer of any utility.
Embedded systems do not have any users at all and so there is no possibility of intrusion. Workstations are increasingly "personal" computers and so there is only ever one user. Database servers do not, in principle, have any users and so there should be no possibility of intrusion. The weak point in the security of modern networks is not within each computer, but in the links between the computers. In some ways the virtual machine concept is more dangerous than no security at all: its hostility to applications programs gives an illusion of security and diverts attention from the real weaknesses of the system.
The basic Stella security concepts concern the interactions between tasks accessing a common address space (whether the tasks are on a single processor or multiple processors sharing memory). Where tasks do not share an address space (tasks on separate machines co-operating via a network, for example) addressing faults or deliberate attempts by one task to access outside its own resources cannot affect the other tasks.
There are three main sources of problems that can affect the security of the system.
Competition for shared resources is a possibility in any system where there is more than one task. This is, therefore, a fairly general problem. The operating system's role in handling the problems arising from programming errors or reconfiguration, however, depends on the domain.
In Stella, these operations are performed by proprietary INTSAFE (intrinsically safe) asynchronous mechanisms which cannot give rise to any problems of competition. The data structures and access code are designed for asynchronous access by two or more tasks (on the same or different processors) without requiring any intrusive protection mechanisms.
This asynchronous approach to handling asynchronous communications is not only natural and efficient, but also it eliminates any possibility of system failure due to deadlocks.
Naturally, as the Stella design principles are, above all, pragmatic, INTSAFE mechanisms are not used for all intertask competition. Some versions of Stella have an operating system call mechanism that disables interrupts for a few instructions. In theory, this could be replaced by an INTSAFE mechanism but this would, in practice, degrade the overall interrupt response.
The simplest solution is to restrict resource allocation to low priority tasks: higher priority tasks are not affected by the lower priority atomic operations but cannot allocate resources themselves. Tasks are thus divided into two groups: asynchronous tasks (usually all interrupt servers) and scheduled tasks (usually all applications programs). This approach provides the best compromise between simplicity, response and efficiency for most "real world" systems.
An intermediate solution provided by Stella is to maintain the division into scheduled and asynchronous tasks, but to guarantee that the applications program scheduler is never disabled for more than a pre-specified time. All operations at the operating system level (including the scheduler itself) which execute for more than the specified time are pre_emptible. The internal limit on the size of atomic operations is pre-set to 25 "instructions": this degrades the overall system efficiency by about 10%.
Stella also provides a rather academic solution that removes the distinction between interrupt servers and other tasks. This allows interrupt servers to access the whole range of operating system facilities. The penalty is that response to the first interrupt server of a burst may be delayed by up to 25 "instructions". Although this is better than most "state of the art" real-time systems, it represents a major degradation in the performance of a Stella system.
Stella also provides direct support for transactions. This eliminates one of the major requirements for mutual exclusion (file locks) in applications programs.
All these measures cost time and some depend on the provision of specific hardware.
The operating system cannot guarantee that the call is correct. For example, it cannot determine whether a memory allocation request specifies the "correct" amount of memory. The operating system can, however, ensure that erroneous calls do not crash the system.
Stella provides 4 levels of operating system call protection.
Reduced | There are no checks on allocation sizes, priorities, etc., but only valid operations are performed. |
Normal | Negative allocations and other gross errors are rejected. |
High | The pointer and data structure checks are more rigorous. |
Paranoid | There are operating system data structure integrity checks on every operating system call - this is normally only used for testing. |
In addition, the operating system data structure integrity checks used by paranoid operating system calls are available as direct calls which may, therefore, be used from a periodic scheduled task (to check the integrity once a second, for example).
Some operating systems identify entities, such as tasks or IO channels, by an index into a table or by the address of the entity. This provides very little protection against removal of an entity. A task holding the table index or address of the entity may then try to access an entity that no longer exists. Some operating systems reduce the risks by using a compound ID incorporating a table index and a check key or tag. This is slightly better.
Entities in Stella are, however, identified by an entity identification structure. This structure (typically 16 bytes) provides a much higher level of protection not only against unexpected removal of entities, but also against programming errors. It also has the merit of being more efficient than a compound ID. An entity identification structure is only a unique identifier for entities in the same memory space (the same hardware). Special entity identification structures are used to keep a record of remote entities (those on other computers).
Stella allows tasks to access other entities directly without passing through the operating system. This is a highly efficient approach that is frequently used illicitly by programs executing under other operating systems where it causes serious problems when an entity is removed.
Stella, however, not only provides a clean mechanism for locating entities, it also provides protection against spurious memory accesses resulting from the unexpected removal of an entity. The operating system call to locate an entity registers the use of that entity by the "user". If an entity is "in use" when it is removed, then the entity becomes unavailable for new "users" but the remove operation does not take effect until last of the "users" is removed or releases the entity.