IPC Operations

Table: Performance of IPC in Flask relative to the base Fluke system. A ``Null'' IPC actually transfers a minimal message, 8 bytes in the current implementation. In Fluke , the tests use the standard Fluke IPC interfaces in a system configured with no Flask enforcement mechanisms. Absolute times are shown in this column as a basis for comparison. Naive runs the same tests on the Flask microkernel. In client identification, the tests have been modified to use the Flask-specific server-side IPC interface to obtain the SID of the client on every call. Client impersonation uses the client-side IPC interface to specify an effective SID for every call.
Flask
Fluke naive client client
message size (μs) identification impersonation
``Null'' 13.5 +2% +9% +6%
16-byte 15.0 +2% +4% +6%
128-byte 15.8 +1% +2% +5%
1k-byte 21.9 +2% +2% +4%
4k-byte 42.9 +1% +1% +2%
8k-byte 78.5 +1% +5% +1%
64k-byte 503 +0% +6% +0%

This section presents performance measurements for IPC operations under various message sizes and also measures the impact of caching within the microkernel. Table 2 presents timings for a variety of client-server IPC microbenchmarks for the base Fluke microkernel and under different scenarios in the Flask system. The tests measure cross-domain transfer of varying amounts of data, from client to server and back again.

For all of the tests performed on Flask in Table 2, the required permissions are available in the access vector cache at the location identified by a ``hint'' within the port reference structure. While we have provided the data structures to allow for fast queries of previously computed security decisions, we have not done any specific code optimization to speed up the execution. Therefore it was encouraging to find that the addition of these data structures alone is sufficient to almost completely eliminate any measurable impact of the permission checks.

The most interesting case in Table 2 is the naive column, because it represents the most common form of IPC in the Flask system. Along this path there is only a single Connect permission check. The results show a worst-case 2% (∼50 machine cycle) performance hit. As would be expected, the relative effect of the single access check diminishes as the size of the data transfer increases and memory copy costs become the dominating factor. The client identification column has a larger than expected impact due to the fact that, in the current implementation, the client SID is passed across the interface to the server in a register normally used for data transfer. This forces an extra memory copy (particularly obvious in the Null IPC test). The significant effect on large data transfers is unexpected and needs to be investigated. The client impersonation column shows the impact of checking both the Connect and SpecifyClient permissions.

Table: Marginal cost of security decisions in Flask. The first two columns repeat data from Table 2, identifying the relative cost of Flask when the required permission is found in the access vector cache (AVC) using the hint. The third column is the time required when the hint was incorrect but the permission was still found in the AVC. The trivSS column is the time required when the permission is not found in the AVC, and a ``trivial'' security server, which immediately returns an access ruling with all permissions granted, is used. The realSS column is the time required when the permission is not found in the AVC and an access ruling is computed by our prototype security server.
Flask
using using calling calling
Fluke hint cache trivSS realSS
``Null'' 13.5 μs 13.8 μs 14.4 μs 43.4 μs 82.5 μs
+2% +7% +221% +511%

The effect of not finding the permission through the hint is shown in Table 3, which presents the relative costs of retrieving a security decision from the cache and from the security server. The operation being performed is the most sensitive of the IPC operations, round trip of transfer of a ``null'' message between a client and a server and is consequently representative of the worst case.

The cache column shows that the use of the hint is significant in that it reduces the overhead from 7% to 2%. The trivSS column shows a more than tripling of the time required in the base Fluke case. The IPC interaction between the microkernel and security server requires transfer of 20 bytes of data to the security server (along with the client SID) and return of 20 bytes. Since the permission for this IPC interaction is found using the hint, we see from Table 2 that over half of the additional overhead is due to the IPC. The remainder of the overhead is due to the identification of the request for a security decision, construction of the security server request in the kernel, and the unmarshaling and marshaling of parameters in the security server itself. The additional overhead in the realSS column compared to the previous case is the time required to compute a security decision within our prototype security server. Though no attempt has been made to optimize the security server computations, this result points out that the access vector cache can potentially be important regardless of whether interactions with the security server require an IPC interaction.