Skip to content

Commit

Permalink
[LibOS,PAL] Introduce extra runtime configuration (currently only 're…
Browse files Browse the repository at this point in the history
…solv.conf')

To accomplish this, Gramine obtains information from the host, sanitizes it,
and stores it in the global PAL state. Later, LibOS uses it to create
a pseudo file (using pseudofs filesystem).

Signed-off-by: Mariusz Zaborski <[email protected]>
  • Loading branch information
oshogbo committed Sep 18, 2022
1 parent a8e3414 commit f6f7f5c
Show file tree
Hide file tree
Showing 32 changed files with 1,060 additions and 30 deletions.
5 changes: 3 additions & 2 deletions CI-Examples/python/python.manifest.template
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ fs.mounts = [
{ type = "tmpfs", path = "/tmp" },
]

sys.stack.size = "2M"
sys.enable_extra_runtime_domain_names_conf = true

sgx.debug = true
sgx.nonpie_binary = true
sgx.enclave_size = "512M"
sys.stack.size = "2M"
sgx.thread_num = 32

sgx.remote_attestation = "{{ ra_type }}"
Expand Down Expand Up @@ -53,5 +55,4 @@ sgx.allowed_files = [
"file:/etc/passwd",
"file:/etc/gai.conf",
"file:/etc/host.conf",
"file:/etc/resolv.conf",
]
3 changes: 2 additions & 1 deletion CI-Examples/ra-tls-mbedtls/client.manifest.template
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ fs.mounts = [
{ path = "/client", uri = "file:client" },
]

sys.enable_extra_runtime_domain_names_conf = true

sgx.debug = true
sgx.enclave_size = "512M"
sgx.thread_num = 4
Expand All @@ -39,7 +41,6 @@ sgx.trusted_files = [
sgx.allowed_files = [
"file:/etc/nsswitch.conf",
"file:/etc/host.conf",
"file:/etc/resolv.conf",
"file:/etc/ethers",
"file:/etc/hosts",
"file:/etc/group",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ fs.mounts = [
{ path = "/ca.crt", uri = "file:../ssl/ca.crt" },
]

sys.enable_extra_runtime_domain_names_conf = true

sgx.enclave_size = "512M"
sgx.debug = true

Expand All @@ -42,5 +44,4 @@ sgx.allowed_files = [
"file:/etc/group",
"file:/etc/passwd",
"file:/etc/gai.conf",
"file:/etc/resolv.conf",
]
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ fs.mounts = [
{ path = "/ca.crt", uri = "file:../ssl/ca.crt" },
]

sys.enable_extra_runtime_domain_names_conf = true

sgx.enclave_size = "512M"
sgx.debug = true

Expand All @@ -46,5 +48,4 @@ sgx.allowed_files = [
"file:/etc/group",
"file:/etc/passwd",
"file:/etc/gai.conf",
"file:/etc/resolv.conf",
]
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ fs.mounts = [
{ path = "/files/", uri = "file:enc_files/", type = "encrypted" },
]

sys.enable_extra_runtime_domain_names_conf = true

sgx.enclave_size = "512M"
sgx.debug = true

Expand All @@ -48,5 +50,4 @@ sgx.allowed_files = [
"file:/etc/group",
"file:/etc/passwd",
"file:/etc/gai.conf",
"file:/etc/resolv.conf",
]
34 changes: 34 additions & 0 deletions Documentation/manifest-syntax.rst
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,40 @@ source.
that encryption key provisioning currently happens after setting up
arguments.
Domain names configuration
^^^^^^^^^^^^^^^^^^^^^^^^^^

::

sys.enable_extra_runtime_domain_names_conf = [true|false]
(Default: false)

This option will generate following extra runtime files:

- ``/etc/resolv.conf``
Supported keywords:

- ``nameserver``
- ``search``
- ``options`` (``inet6`` | ``rotate``)

Unsupported keywords and malformed lines are ignored, and invalid values are
reported as an error.

This functionality is achieved by taking the host's configuration via various
APIs and reading the host's configuration files. In the case of Linux PAL,
most information comes from the host's ``/etc``. The gathered information is
used to create ``/etc`` files inside Gramine's file system, or change Gramine
process configuration. For security-enforcing modes (such as SGX), Gramine
additionally sanitizes the information gathered from the host.

Note that Gramine supports only a subset of the configuration.
Refer to the list of supported keywords.

This option takes precedence over ``fs.mounts``.
This means that etc files provided via ``fs.mounts`` will be overridden with
the ones added via this option.

Environment variables
^^^^^^^^^^^^^^^^^^^^^

Expand Down
1 change: 1 addition & 0 deletions common/include/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ int tolower(int c);
int toupper(int c);
int isalpha(int c);
int isdigit(int c);
int isxdigit(int c);
int isalnum(int c);

char* strchr(const char* s, int c);
Expand Down
4 changes: 4 additions & 0 deletions common/src/string/ctype.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ int isdigit(int c) {
return (unsigned)c - '0' < 10;
}

int isxdigit(int c) {
return isdigit(c) || (unsigned)tolower(c) - 'a' < 6;
}

int isalnum(int c) {
return isalpha(c) || isdigit(c);
}
1 change: 1 addition & 0 deletions libos/include/libos_fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@ extern struct libos_dentry* g_dentry_root;
int init_fs(void);
int init_mount_root(void);
int init_mount(void);
int mount_etcfs(void);

/* file system operations */

Expand Down
3 changes: 3 additions & 0 deletions libos/include/libos_fs_pseudo.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,6 @@ int sys_print_as_ranges(char* buf, size_t buf_size, size_t count,
int sys_print_as_bitmask(char* buf, size_t buf_size, size_t count,
bool (*is_present)(size_t ind, const void* arg),
const void* callback_arg);

/* etcfs */
int init_etcfs(void);
157 changes: 157 additions & 0 deletions libos/src/fs/etc/fs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2022 Intel Corporation
* Mariusz Zaborski <[email protected]>
*/

/*
* This file contains the implementation of `etc` FS.
* LibOS assumes that contents of all data obtained from host were already sanitized.
*/

#include "libos_checkpoint.h"
#include "libos_fs.h"
#include "libos_fs_pseudo.h"

#define OPTION_INET6 "options inet6\n"
#define OPTION_ROTATE "options rotate\n"

static int put_string(char** buf, size_t* bufsize, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
int ret = vsnprintf(*buf, *bufsize, fmt, ap);
va_end(ap);
if (ret < 0)
return ret;
if ((size_t)ret >= *bufsize)
return -EOVERFLOW;
*bufsize -= ret;
*buf += ret;

return 0;
}

static int provide_etc_resolv_conf(struct libos_dentry* dent, char** out_data, size_t* out_size) {
__UNUSED(dent);

size_t size = 0;

/* Estimate the size of buffer: */
/* nameservers - let's assume all entries will be IPv6 plus a new line */
size += g_pal_public_state->dns_host.nsaddr_list_count
* (strlen("nameserver ") + MAX_IPV6_ADDR_LEN + 1);
/* search - let's assume maximum length of entries, plus a new line and white spaces */
size += strlen("search");
size += g_pal_public_state->dns_host.dn_search_count * (PAL_HOSTNAME_MAX + 1);
size += 1;
/* and let's add some space for each option */
size += (g_pal_public_state->dns_host.inet6 ? strlen(OPTION_INET6) : 0) +
(g_pal_public_state->dns_host.rotate ? strlen(OPTION_ROTATE) : 0);
/* make space for terminating character */
size += 1;

char* data = malloc(size);
if (!data)
return -ENOMEM;
memset(data, 0, size);

/* Generate data: */
size_t space_left = size;
char* ptr = data;
int ret;
for (size_t i = 0; i < g_pal_public_state->dns_host.nsaddr_list_count; i++) {
if (!g_pal_public_state->dns_host.nsaddr_list[i].is_ipv6) {
uint32_t addr = g_pal_public_state->dns_host.nsaddr_list[i].ipv4;
ret = put_string(&ptr, &space_left, "nameserver %u.%u.%u.%u\n",
(addr & 0xFF000000) >> 24, (addr & 0x00FF0000) >> 16,
(addr & 0x0000FF00) >> 8, (addr & 0x000000FF));
} else {
uint16_t* addrv6 = g_pal_public_state->dns_host.nsaddr_list[i].ipv6;
ret = put_string(&ptr, &space_left, "nameserver %x:%x:%x:%x:%x:%x:%x:%x\n",
addrv6[0], addrv6[1], addrv6[2], addrv6[3], addrv6[4], addrv6[5],
addrv6[6], addrv6[7]);
}
if (ret < 0)
goto out;
}

if (g_pal_public_state->dns_host.dn_search_count > 0) {
ret = put_string(&ptr, &space_left, "search");
if (ret < 0)
goto out;
for (size_t i = 0; i < g_pal_public_state->dns_host.dn_search_count; i++) {
ret = put_string(&ptr, &space_left, " %s", g_pal_public_state->dns_host.dn_search[i]);
if (ret < 0)
goto out;
}
ret = put_string(&ptr, &space_left, "\n");
if (ret < 0)
goto out;
}
if (g_pal_public_state->dns_host.inet6) {
ret = put_string(&ptr, &space_left, OPTION_INET6);
if (ret < 0)
goto out;
}
if (g_pal_public_state->dns_host.rotate) {
ret = put_string(&ptr, &space_left, OPTION_ROTATE);
if (ret < 0)
goto out;
}

/* Use the string (without null terminator) as file data */
size_t finalsize = strlen(data);
char* finalbuf = malloc(finalsize);
if (!finalbuf) {
ret = -ENOMEM;
goto out;
}
assert(finalsize < size);
memcpy(finalbuf, data, finalsize);

*out_data = finalbuf;
*out_size = finalsize;

ret = 0;
out:
free(data);
return ret;
}

int init_etcfs(void) {
pseudo_add_str(NULL, "emulated-etc-resolv-conf", &provide_etc_resolv_conf);
return 0;
}

int mount_etcfs(void) {
if (!g_pal_public_state->extra_runtime_domain_names_conf)
return 0;

return mount_fs(&(struct libos_mount_params){
.type = "pseudo",
.path = "/etc/resolv.conf",
.uri = "emulated-etc-resolv-conf",
});
}

BEGIN_CP_FUNC(etc_info) {
__UNUSED(size);
__UNUSED(obj);
__UNUSED(objp);

/* Propagate DNS configuration */
size_t off = ADD_CP_OFFSET(sizeof(g_pal_public_state->dns_host));
struct dns_host* new_dns_host = (struct dns_host*)(base + off);
memcpy(new_dns_host, &g_pal_public_state->dns_host, sizeof(g_pal_public_state->dns_host));

ADD_CP_FUNC_ENTRY(off);
}
END_CP_FUNC(etc_info)

BEGIN_RS_FUNC(etc_info) {
__UNUSED(offset);
__UNUSED(rebase);

const struct dns_host* dns_host = (const struct dns_host*)(base + GET_CP_FUNC_ENTRY());
memcpy(&g_pal_public_state->dns_host, dns_host, sizeof(g_pal_public_state->dns_host));
}
END_RS_FUNC(etc_info)
7 changes: 6 additions & 1 deletion libos/src/fs/libos_fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ int init_fs(void) {
if ((ret = init_sysfs()) < 0)
goto err;

if ((ret = init_etcfs()) < 0)
goto err;

return 0;

err:
Expand Down Expand Up @@ -650,7 +653,9 @@ int init_mount(void) {
}
/* Otherwise `cwd` is already initialized. */

return 0;
/* The mount_etcfs takes precedence over user's fs.mounts, and because of that,
* it has to be called at the end. */
return mount_etcfs();
}

struct libos_fs* find_fs(const char* name) {
Expand Down
1 change: 1 addition & 0 deletions libos/src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ libos_sources = files(
'fs/chroot/fs.c',
'fs/dev/attestation.c',
'fs/dev/fs.c',
'fs/etc/fs.c',
'fs/eventfd/fs.c',
'fs/libos_dcache.c',
'fs/libos_fs.c',
Expand Down
1 change: 1 addition & 0 deletions libos/src/sys/libos_clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ static BEGIN_MIGRATION_DEF(fork, struct libos_process* process_description,
DEFINE_MIGRATE(brk, NULL, 0);
DEFINE_MIGRATE(loaded_elf_objects, NULL, 0);
DEFINE_MIGRATE(topo_info, NULL, 0);
DEFINE_MIGRATE(etc_info, NULL, 0);
#ifdef DEBUG
DEFINE_MIGRATE(gdb_map, NULL, 0);
#endif
Expand Down
10 changes: 10 additions & 0 deletions pal/include/host/linux-common/etc_host_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2022 Intel Corporation
* Mariusz Zaborski <[email protected]>
*/

#pragma once

#include "pal.h"

int parse_resolv_conf(struct pal_dns_host_conf* conf);
13 changes: 13 additions & 0 deletions pal/include/host/linux-common/etc_host_info_internal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2022 Intel Corporation
* Mariusz Zaborski <[email protected]>
*/

/*
* This file contains a list of external functions for which Gramine has unit tests.
*/

#pragma once

bool parse_ip_addr_ipv4(const char** pptr, uint32_t* out_addr);
bool parse_ip_addr_ipv6(const char** pptr, uint16_t out_addr[static 8]);
Loading

0 comments on commit f6f7f5c

Please sign in to comment.