Add resolv-conf parser

This commit is contained in:
ClawSeven 2021-07-19 17:40:20 +08:00 committed by Zongmin.Gu
parent 1acfec6b12
commit d35d98d551
19 changed files with 239 additions and 6 deletions

3
.gitmodules vendored

@ -22,3 +22,6 @@
[submodule "deps/ringbuf"]
path = deps/ringbuf
url = https://github.com/agerasev/ringbuf.git
[submodule "deps/resolv-conf"]
path = deps/resolv-conf
url = https://github.com/tailhook/resolv-conf.git

@ -35,6 +35,7 @@ submodule: githooks
@# Try to apply the patches. If failed, check if the patches are already applied
cd deps/serde-json-sgx && git apply ../serde-json-sgx.patch >/dev/null 2>&1 || git apply ../serde-json-sgx.patch -R --check
cd deps/ringbuf && git apply ../ringbuf.patch >/dev/null 2>&1 || git apply ../ringbuf.patch -R --check
cd deps/resolv-conf && git apply ../resolv-conf.patch >/dev/null 2>&1 || git apply ../resolv-conf.patch -R --check
@# Enclaves used by tools are running in simulation mode by default to run faster.
@rm -rf build build_sim

@ -24,7 +24,6 @@ then
fi
mkdir -p image/etc
cp /etc/resolv.conf image/etc
cp ../greeter_client image/bin
cp $INSTALL_DIR/lib/libprotobuf.so.3.10.0.0 image/lib
cp $INSTALL_DIR/lib/libcares.so.2 image/lib

@ -23,7 +23,6 @@ then
fi
mkdir -p image/etc
cp /etc/resolv.conf image/etc
cp ../greeter_server image/bin
cp $INSTALL_DIR/lib/libprotobuf.so.3.10.0.0 image/lib
cp $INSTALL_DIR/lib/libcares.so.2 image/lib

1
deps/resolv-conf vendored Submodule

@ -0,0 +1 @@
Subproject commit c0752810e748d496c2df161a2a90c3c229b65531

80
deps/resolv-conf.patch vendored Normal file

@ -0,0 +1,80 @@
From 9faee3943a31e359e76c5dfce23918c35fd8f317 Mon Sep 17 00:00:00 2001
From: ClawSeven <zehuan97@gmail.com>
Date: Fri, 9 Jul 2021 13:28:42 +0800
Subject: [PATCH] Transplant resolv-conf into sgx-world
---
Cargo.toml | 3 ++-
src/config.rs | 2 ++
src/grammar.rs | 1 +
src/ip.rs | 1 +
src/lib.rs | 3 +++
5 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/Cargo.toml b/Cargo.toml
index 0022252..617e319 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,7 +14,8 @@ version = "0.7.0"
authors = ["paul@colomiets.name"]
[dependencies]
-quick-error = "1.0.0"
+quick-error = { git = "https://github.com/mesalock-linux/quick-error-sgx.git" }
+sgx_tstd = { git = "https://github.com/apache/teaclave-sgx-sdk.git" }
hostname = { version = "^0.3", optional = true }
[features]
diff --git a/src/config.rs b/src/config.rs
index b6b6460..8389064 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -3,6 +3,8 @@ use std::iter::{IntoIterator, Iterator};
use std::slice::Iter;
use {grammar, Network, ParseError, ScopedIp};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
+use std::vec::Vec;
+use std::string::String;
const NAMESERVER_LIMIT:usize = 3;
const SEARCH_LIMIT:usize = 6;
diff --git a/src/grammar.rs b/src/grammar.rs
index 9a274a8..be85081 100644
--- a/src/grammar.rs
+++ b/src/grammar.rs
@@ -1,5 +1,6 @@
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::{Utf8Error, from_utf8};
+use std::string::ToString;
use {AddrParseError, Config, Network, Lookup, Family};
diff --git a/src/ip.rs b/src/ip.rs
index c9cfa59..4b4bca2 100644
--- a/src/ip.rs
+++ b/src/ip.rs
@@ -2,6 +2,7 @@ use std::error::Error;
use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
+use std::string::{String, ToString};
/// A network, that is an IP address and a mask
#[derive(Clone, Debug, PartialEq, Eq)]
diff --git a/src/lib.rs b/src/lib.rs
index a55a9d7..094a35a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -91,6 +91,9 @@
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
+#![no_std]
+#[macro_use]
+extern crate sgx_tstd as std;
#[macro_use]
extern crate quick_error;
#[cfg(feature = "system")]
--
2.17.1

@ -42,7 +42,7 @@ enclave {
* EEXIST - The LibOS has already been initialized.
* EINVAL - The value of an argument are invalid.
*/
public int occlum_ecall_init([in, string] const char* log_level, [in, string] const char* instance_dir);
public int occlum_ecall_init([in, string] const char* log_level, [in, string] const char* instance_dir, [in, string] const char* resolv_conf_ptr);
/*
* Create a new LibOS process to do the task specified by the given

@ -22,6 +22,7 @@ rcore-fs-ramfs = { path = "../../deps/sefs/rcore-fs-ramfs" }
rcore-fs-mountfs = { path = "../../deps/sefs/rcore-fs-mountfs" }
rcore-fs-unionfs = { path = "../../deps/sefs/rcore-fs-unionfs" }
rcore-fs-devfs = { path = "../../deps/sefs/rcore-fs-devfs" }
resolv-conf = { path = "../../deps/resolv-conf" }
serde = { path = "../../deps/serde-sgx/serde", features = ["derive"] }
serde_json = { path = "../../deps/serde-json-sgx" }
memoffset = "0.6.1"

@ -12,6 +12,7 @@ use crate::signal::SigNum;
use crate::time::up_time::init;
use crate::util::log::LevelFilter;
use crate::util::mem_util::from_untrusted::*;
use crate::util::resolv_conf_util::{parse_resolv_conf, write_resolv_conf};
use crate::util::sgx::allow_debug as sgx_allow_debug;
use sgx_tse::*;
@ -23,6 +24,7 @@ lazy_static! {
static ref HAS_INIT: AtomicBool = AtomicBool::new(false);
pub static ref ENTRY_POINTS: RwLock<Vec<PathBuf>> =
RwLock::new(config::LIBOS_CONFIG.entry_points.clone());
pub static ref RESOLV_CONF_STR: RwLock<Option<String>> = RwLock::new(None);
}
macro_rules! ecall_errno {
@ -33,7 +35,11 @@ macro_rules! ecall_errno {
}
#[no_mangle]
pub extern "C" fn occlum_ecall_init(log_level: *const c_char, instance_dir: *const c_char) -> i32 {
pub extern "C" fn occlum_ecall_init(
log_level: *const c_char,
instance_dir: *const c_char,
resolv_conf_ptr: *const c_char,
) -> i32 {
if HAS_INIT.load(Ordering::SeqCst) == true {
return ecall_errno!(EEXIST);
}
@ -87,6 +93,18 @@ pub extern "C" fn occlum_ecall_init(log_level: *const c_char, instance_dir: *con
unsafe { backtrace::enable_backtrace(&ENCLAVE_PATH, PrintFormat::Short) };
});
match parse_resolv_conf(resolv_conf_ptr) {
Err(e) => {
error!("failed to parse /etc/resolv.conf: {}", e.backtrace());
}
Ok(resolv_conf_str) => {
*RESOLV_CONF_STR.write().unwrap() = Some(resolv_conf_str);
if let Err(e) = write_resolv_conf() {
error!("failed to write /etc/resolv.conf: {}", e.backtrace());
}
}
}
0
}

@ -1,4 +1,5 @@
use std::sync::Once;
use util::resolv_conf_util::write_resolv_conf;
use super::rootfs::{mount_nonroot_fs_according_to, open_root_fs_according_to};
use super::*;
@ -27,5 +28,9 @@ pub fn do_mount_rootfs(
*root_inode = new_root_inode;
*ENTRY_POINTS.write().unwrap() = user_config.entry_points.to_owned();
});
// Write resolv.conf file into mounted file system
write_resolv_conf()?;
*RESOLV_CONF_STR.write().unwrap() = None;
Ok(())
}

@ -53,6 +53,7 @@ extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate memoffset;
extern crate resolv_conf;
use sgx_trts::libc;
use sgx_types::*;

@ -5,5 +5,6 @@ pub mod log;
pub mod mem_util;
pub mod mpx_util;
pub mod random;
pub mod resolv_conf_util;
pub mod sgx;
pub mod sync;

@ -0,0 +1,37 @@
use super::*;
use crate::fs::{AccessMode, CreationFlags, FsView};
use resolv_conf::*;
use std::ffi::CStr;
use std::str;
pub fn write_resolv_conf() -> Result<()> {
const RESOLV_CONF_PATH: &'static str = "/etc/resolv.conf";
let fs_view = FsView::new();
// overwrite /etc/resolv.conf if existed
let resolv_conf_file = fs_view.open_file(
RESOLV_CONF_PATH,
AccessMode::O_RDWR as u32 | CreationFlags::O_CREAT.bits() | CreationFlags::O_TRUNC.bits(),
0o666,
)?;
let resolv_conf_str = RESOLV_CONF_STR.read().unwrap();
match &*resolv_conf_str {
Some(str) => {
resolv_conf_file.write(str.as_bytes());
}
None => {}
}
Ok(())
}
pub fn parse_resolv_conf(resolv_conf_ptr: *const c_char) -> Result<String> {
// Read resolv.conf file from host
let resolv_conf_bytes = unsafe { CStr::from_ptr(resolv_conf_ptr).to_bytes() };
let resolv_conf_str = str::from_utf8(resolv_conf_bytes)
.map_err(|_| errno!(EINVAL, "/etc/resolv.conf contains non UTF-8 characters"))?;
// Parse and inspect resolv.conf file
if let Err(_) = resolv_conf::Config::parse(resolv_conf_bytes) {
return_errno!(EINVAL, "malformated host /etc/resolv.conf");
}
Ok(resolv_conf_str.to_string())
}

@ -2,6 +2,7 @@
#include "Enclave_u.h"
#include "pal_enclave.h"
#include "pal_error.h"
#include "pal_load_resolv_conf.h"
#include "pal_interrupt_thread.h"
#include "pal_log.h"
#include "pal_sig_handler.h"
@ -103,8 +104,11 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) {
eid = pal_get_enclave_id();
int ecall_ret = 0;
const char *resolv_conf_ptr = pal_load_resolv_conf();
sgx_status_t ecall_status = occlum_ecall_init(eid, &ecall_ret, attr->log_level,
resolved_path);
resolved_path, resolv_conf_ptr);
free((void *)resolv_conf_ptr);
resolv_conf_ptr = NULL;
if (ecall_status != SGX_SUCCESS) {
const char *sgx_err = pal_get_sgx_error_msg(ecall_status);
PAL_ERROR("Failed to do ECall with error code 0x%x: %s", ecall_status, sgx_err);

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#include "pal_log.h"
char *pal_load_resolv_conf(void) {
FILE *fp = fopen("/etc/resolv.conf", "rb");
if (fp == NULL) {
PAL_WARN("Warning: Failed to open /etc/resolv.conf file");
return NULL;
}
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *resolv_conf_buffer = malloc(fsize + 1);
if (resolv_conf_buffer == NULL) {
PAL_WARN("Warning: Failed to malloc for /etc/resolv.conf buffer");
return NULL;
}
fread(resolv_conf_buffer, 1, fsize, fp);
resolv_conf_buffer[fsize] = 0;
fclose(fp);
return resolv_conf_buffer;
}

@ -0,0 +1,6 @@
#ifndef __PAL_LOAD_RESOLV_CONF_H__
#define __PAL_LOAD_RESOLV_CONF_H__
char *pal_load_resolv_conf(void);
#endif /* __PAL_LOAD_RESOLV_CONF_H__ */

@ -16,7 +16,7 @@ FAIL_LOG = $(BUILD_DIR)/test/.fail
TEST_DEPS := client data_sink naughty_child
# Tests: need to be compiled and run by test-% target
TESTS ?= env empty hello_world malloc mmap file fs_perms getpid spawn sched pipe time timerfd \
truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info rlimit \
truncate readdir mkdir open stat link symlink chmod chown tls pthread system_info resolv_conf rlimit \
server server_epoll unix_socket cout hostfs cpuid rdtsc device sleep exit_group \
ioctl fcntl eventfd emulate_syscall access signal sysinfo prctl rename procfs wait \
spawn_attribute exec statfs

@ -0,0 +1,5 @@
include ../test_common.mk
EXTRA_C_FLAGS :=
EXTRA_LINK_FLAGS :=
BIN_ARGS :=

48
test/resolv_conf/main.c Normal file

@ -0,0 +1,48 @@
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
// ============================================================================
// Helper functions
// ============================================================================
char *read_resolv_conf(void) {
FILE *fp = fopen("/etc/resolv.conf", "rb");
fseek(fp, 0, SEEK_END);
long fsize = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *resolv_conf_buffer = malloc(fsize + 1);
if (resolv_conf_buffer == NULL) {
printf("ERROR: Failed to malloc for /etc/resolv.conf buffer");
return NULL;
}
fread(resolv_conf_buffer, 1, fsize, fp);
fclose(fp);
return resolv_conf_buffer;
}
// ============================================================================
// Test cases for resolv.conf file
// ============================================================================
int test_resolv_conf() {
char *buffer = read_resolv_conf();
if (buffer == NULL) {
THROW_ERROR("failed to read resolv.conf");
}
printf("%s", buffer);
free(buffer);
buffer = NULL;
return 0;
}
static test_case_t test_cases[] = {
TEST_CASE(test_resolv_conf),
};
// ============================================================================
// Test suite main
// ============================================================================
int main() {
return test_suite_run(test_cases, ARRAY_SIZE(test_cases));
}