Gramine
Last updated
Last updated
A Lib-OS is an operating system kernel that resides in userspace and behaves like a library. The primary use of a Lib-OS is to provide applications with the same benefits as virtual machines. These benefits include migration, isolation of untrusted applications, and host platform compatibility. In fact, Lib-OSes offer an advantage over virtual machines in this regard because there is no duplication of functionality between the guest (Lib-OS) and the host kernel. This makes them more lightweight than virtual machines.
Most applications will not work with SGX out of the box. For example, Intel SGX disallows system calls inside an enclave by design for security reasons. System calls require the enclave to communicate with the untrusted OS, which could potentially return malicious input. By completely disallowing system calls, applications would not be portable to SGX. A shielded layer within the enclave is required to validate and potentially reject input received from system calls. In addition, the application's dependencies, such as libraries or files on the host OS, must be mounted inside the enclave explicitly, since the host OS is not trusted.
Either the Intel SGX SDK or a Lib-OS can be used to encapsulate an application. Each has its advantages and disadvantages.
Gramine's manifest file is used to enable Gramine's features and is a user policy for enclave initialization. In addition, some important configuration options, such as the allowed resources of an enclave, are also available in the manifest. One of Gramine's features is to allow an enclave to open trusted files on the host file system. All trusted files are hashed with SHA2-256 and included in the manifest. To further protect the integrity of the manifest, it is then signed.
Gramine adds several software layers to an application's software architecture (Figure above). A trusted shielding layer, a library OS and C library, and an untrusted enclave platform adaptation layer (pal-sgx).
First, the untrusted pal-sgx is loaded and initializes the enclave by invoking the SGX drivers in the kernel. It uses the configuration options in the manifest and includes the manifest, the shielding layer, and the executables in the enclave. Next, the shielding layer loads the library OS and standard C libraries. Finally, all files included in the manifest and libraries are loaded into the enclave. When files are marked as trusted, the hash of the file is first checked against the hash in the manifest, and only loaded into the enclave if both values match. This results in trusting the shielding layer to load the correct files, but since the shielding layer is involved in the enclave initialization process, its correctness can be attested.
Most of the application's system calls don't need to reach the host OS and are handled inside the enclave by the library OS. Some system calls can't be handled by the library OS, so the shielding layer implements 36 Gramine application binary interface (ABI) functions and communicates with the untrusted pal-sgx. Since each kernel has different system calls, the pal-sgx is introduced for platform integration. It can be easily modified to meet the needs of the platform. For Linux, pal-sgx funnels the 36 ABI functions into 28 system calls and returns the response to the shielding layer. Now the shielding layer has to evaluate the response and decide if it is trustworthy or not. To do this, it defines legitimate kernel behavior and checks whether the response can damage the enclave. Most system calls are classified as safe, some as benign, and only two as unsafe. The rating depends on how easy the validation is.
Multi-process applications are also supported by Gramine. Here, Gramine is instantiated for each process, including the pal-sgx layer, and the coordination of all Gramine instances is done via TLS. A slight modification to TLS is made here by using local attestation as the authentication method.