From 15932a54b65faf317f3fef1277ef976988ee7f8c Mon Sep 17 00:00:00 2001 From: ClawSeven Date: Thu, 26 Aug 2021 18:54:31 +0800 Subject: [PATCH] Add hosts and hostname file --- demos/flink/flink.yaml | 5 -- demos/flink/hosts | 4 -- src/Enclave.edl | 3 +- src/libos/include/edl/occlum_edl_types.h | 7 +++ src/libos/src/entry.rs | 38 ++++++++++-- src/libos/src/fs/fs_ops/mount.rs | 18 ++++-- src/libos/src/misc/uname.rs | 34 ++++++++++- src/libos/src/util/host_file_util.rs | 77 ++++++++++++++++++++++++ src/libos/src/util/mod.rs | 2 +- src/libos/src/util/resolv_conf_util.rs | 37 ------------ src/pal/include/occlum_pal_api.h | 7 +++ src/pal/src/pal_api.c | 23 +++++-- src/pal/src/pal_load_file.c | 24 ++++++++ src/pal/src/pal_load_file.h | 6 ++ src/pal/src/pal_load_resolv_conf.c | 24 -------- src/pal/src/pal_load_resolv_conf.h | 6 -- 16 files changed, 221 insertions(+), 94 deletions(-) delete mode 100644 demos/flink/hosts create mode 100644 src/libos/src/util/host_file_util.rs delete mode 100644 src/libos/src/util/resolv_conf_util.rs create mode 100644 src/pal/src/pal_load_file.c create mode 100644 src/pal/src/pal_load_file.h delete mode 100644 src/pal/src/pal_load_resolv_conf.c delete mode 100644 src/pal/src/pal_load_resolv_conf.h diff --git a/demos/flink/flink.yaml b/demos/flink/flink.yaml index 5dc6c9b1..7d586bb1 100644 --- a/demos/flink/flink.yaml +++ b/demos/flink/flink.yaml @@ -6,11 +6,6 @@ targets: - target: /bin copy: - from: ../flink-1.10.1 - # copy hosts file - - target: /etc - copy: - - files: - - ../hosts # copy localtime - target: /etc copy: diff --git a/demos/flink/hosts b/demos/flink/hosts deleted file mode 100644 index a190adc8..00000000 --- a/demos/flink/hosts +++ /dev/null @@ -1,4 +0,0 @@ -127.0.0.1 occlum-node -127.0.0.1 localhost -::1 occlum-node -::1 localhost diff --git a/src/Enclave.edl b/src/Enclave.edl index dceee1a8..da473493 100644 --- a/src/Enclave.edl +++ b/src/Enclave.edl @@ -42,8 +42,9 @@ 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, [in, string] const char* resolv_conf_ptr); + public int occlum_ecall_init([in, string] const char* log_level, [in, string] const char* instance_dir, [in] const struct host_file_buffer* file_buffer); + /* * Create a new LibOS process to do the task specified by the given * arguments. diff --git a/src/libos/include/edl/occlum_edl_types.h b/src/libos/include/edl/occlum_edl_types.h index 72676baa..5079bdbc 100644 --- a/src/libos/include/edl/occlum_edl_types.h +++ b/src/libos/include/edl/occlum_edl_types.h @@ -29,6 +29,13 @@ typedef struct itimerspec{ struct _timespec it_value; } itimerspec_t; +// todo: more detailed description +struct host_file_buffer { + const char* resolv_conf_ptr; + const char* hosts_ptr; + const char* hostname_ptr; +}; + #define FD_SETSIZE 1024 typedef struct { unsigned long fds_bits[FD_SETSIZE / 8 / sizeof(long)]; diff --git a/src/libos/src/entry.rs b/src/libos/src/entry.rs index e37c8ace..e89e19af 100644 --- a/src/libos/src/entry.rs +++ b/src/libos/src/entry.rs @@ -11,9 +11,9 @@ use crate::process::idle_reap_zombie_children; use crate::process::{ProcessFilter, SpawnAttr}; use crate::signal::SigNum; use crate::time::up_time::init; +use crate::util::host_file_util::{host_file_buffer, parse_host_file, write_host_file, HostFile}; 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 crate::vm::USER_SPACE_VM_MANAGER; use sgx_tse::*; @@ -27,6 +27,8 @@ lazy_static! { pub static ref ENTRY_POINTS: RwLock> = RwLock::new(config::LIBOS_CONFIG.entry_points.clone()); pub static ref RESOLV_CONF_STR: RwLock> = RwLock::new(None); + pub static ref HOSTNAME_STR: RwLock> = RwLock::new(None); + pub static ref HOSTS_STR: RwLock> = RwLock::new(None); } macro_rules! ecall_errno { @@ -40,7 +42,7 @@ macro_rules! ecall_errno { pub extern "C" fn occlum_ecall_init( log_level: *const c_char, instance_dir: *const c_char, - resolv_conf_ptr: *const c_char, + file_buffer: *const host_file_buffer, ) -> i32 { if HAS_INIT.load(Ordering::SeqCst) == true { return ecall_errno!(EEXIST); @@ -95,18 +97,46 @@ pub extern "C" fn occlum_ecall_init( unsafe { backtrace::enable_backtrace(&ENCLAVE_PATH, PrintFormat::Short) }; }); - match parse_resolv_conf(resolv_conf_ptr) { + // Parse host file + let resolv_conf_ptr = unsafe { (*file_buffer).resolv_conf_ptr }; + match parse_host_file(HostFile::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() { + if let Err(e) = write_host_file(HostFile::RESOLV_CONF) { error!("failed to write /etc/resolv.conf: {}", e.backtrace()); } } } + let hostname_ptr = unsafe { (*file_buffer).hostname_ptr }; + match parse_host_file(HostFile::HOSTNAME, hostname_ptr) { + Err(e) => { + error!("failed to parse /etc/hostname: {}", e.backtrace()); + } + Ok(hostname_str) => { + *HOSTNAME_STR.write().unwrap() = Some(hostname_str); + if let Err(e) = write_host_file(HostFile::HOSTNAME) { + error!("failed to write /etc/hostname: {}", e.backtrace()); + } + } + } + + let hosts_ptr = unsafe { (*file_buffer).hosts_ptr }; + match parse_host_file(HostFile::HOSTS, hosts_ptr) { + Err(e) => { + error!("failed to parse /etc/hosts: {}", e.backtrace()); + } + Ok(hosts_str) => { + *HOSTS_STR.write().unwrap() = Some(hosts_str); + if let Err(e) = write_host_file(HostFile::HOSTS) { + error!("failed to write /etc/hosts: {}", e.backtrace()); + } + } + } + 0 } diff --git a/src/libos/src/fs/fs_ops/mount.rs b/src/libos/src/fs/fs_ops/mount.rs index b70f1321..d1ffc9d5 100644 --- a/src/libos/src/fs/fs_ops/mount.rs +++ b/src/libos/src/fs/fs_ops/mount.rs @@ -1,10 +1,9 @@ -use std::path::PathBuf; -use std::sync::Once; - use config::{parse_key, parse_mac, ConfigMount, ConfigMountFsType, ConfigMountOptions}; use rcore_fs_mountfs::MNode; +use std::path::PathBuf; +use std::sync::Once; +use util::host_file_util::{write_host_file, HostFile}; use util::mem_util::from_user; -use util::resolv_conf_util::write_resolv_conf; use super::rootfs::{mount_nonroot_fs_according_to, open_root_fs_according_to, umount_nonroot_fs}; use super::*; @@ -30,10 +29,19 @@ pub fn do_mount_rootfs( *rootfs = new_rootfs; *ENTRY_POINTS.write().unwrap() = user_config.entry_points.to_owned(); }); + // Write resolv.conf file into mounted file system - write_resolv_conf()?; + write_host_file(HostFile::RESOLV_CONF)?; *RESOLV_CONF_STR.write().unwrap() = None; + // Write hostname file into mounted file system + write_host_file(HostFile::HOSTNAME)?; + *HOSTNAME_STR.write().unwrap() = None; + + // Write hosts file into mounted file system + write_host_file(HostFile::HOSTS)?; + *HOSTS_STR.write().unwrap() = None; + Ok(()) } diff --git a/src/libos/src/misc/uname.rs b/src/libos/src/misc/uname.rs index ee99451f..0dd1ad8b 100644 --- a/src/libos/src/misc/uname.rs +++ b/src/libos/src/misc/uname.rs @@ -1,6 +1,7 @@ use super::*; +use crate::fs::{AccessMode, CreationFlags, FileMode, FsView}; use std::ffi::{CStr, CString}; - +use std::str; /// A sample of `struct utsname` /// ``` /// sysname = Linux @@ -25,7 +26,7 @@ pub struct utsname_t { pub fn do_uname(name: &mut utsname_t) -> Result<()> { copy_from_cstr_to_u8_array(&SYSNAME, &mut name.sysname); - copy_from_cstr_to_u8_array(&NODENAME, &mut name.nodename); + obtain_nodename(&mut name.nodename); copy_from_cstr_to_u8_array(&RELEASE, &mut name.release); copy_from_cstr_to_u8_array(&VERSION, &mut name.version); copy_from_cstr_to_u8_array(&MACHINE, &mut name.machine); @@ -48,3 +49,32 @@ fn copy_from_cstr_to_u8_array(src: &CStr, dst: &mut [u8]) { dst[..len].copy_from_slice(&src[..len]); dst[len] = 0; } + +fn obtain_nodename(dst: &mut [u8]) { + const HOSTNAME_PATH: &'static str = "/etc/hostname"; + + let fs_view = FsView::new(); + + let hostname_file = match fs_view.open_file( + HOSTNAME_PATH, + AccessMode::O_RDONLY as u32, + FileMode::from_bits(0o666).unwrap(), + ) { + Ok(file) => file, + Err(e) => { + // If failed to open hostname file, use "occlum-node" nodename. + error!("failed to open /etc/hostname: {}", e.backtrace()); + copy_from_cstr_to_u8_array(&NODENAME, dst); + return; + } + }; + + let mut nodename: [u8; 65] = [0; 65]; + hostname_file.read(&mut nodename); + + // The \n need to be eliminated. + let nodename_string = str::from_utf8(&nodename).unwrap().replace("\n", ""); + let len = nodename_string.len(); + dst[..len].copy_from_slice(&nodename_string.into_bytes()); + dst[len] = 0; +} diff --git a/src/libos/src/util/host_file_util.rs b/src/libos/src/util/host_file_util.rs new file mode 100644 index 00000000..d9190be8 --- /dev/null +++ b/src/libos/src/util/host_file_util.rs @@ -0,0 +1,77 @@ +use super::*; +use crate::fs::{AccessMode, CreationFlags, FileMode, FsView}; +use resolv_conf::*; +use std::ffi::CStr; +use std::str; + +#[repr(C)] +pub struct host_file_buffer { + pub resolv_conf_ptr: *const c_char, + pub hosts_ptr: *const c_char, + pub hostname_ptr: *const c_char, +} + +pub enum HostFile { + HOSTS, + HOSTNAME, + RESOLV_CONF, +} + +pub fn write_host_file(host_file: HostFile) -> Result<()> { + let file_path: &str = match host_file { + HostFile::HOSTS => "/etc/hosts", + HostFile::HOSTNAME => "/etc/hostname", + HostFile::RESOLV_CONF => "/etc/resolv.conf", + _ => return_errno!(EINVAL, "Unsupported host file"), + }; + + let fs_view = FsView::new(); + // overwrite host file if existed in Occlum fs + let enclave_file = fs_view.open_file( + file_path, + AccessMode::O_RDWR as u32 | CreationFlags::O_CREAT.bits() | CreationFlags::O_TRUNC.bits(), + FileMode::from_bits(0o666).unwrap(), + )?; + + let host_file_str = match host_file { + HostFile::HOSTS => HOSTS_STR.read().unwrap(), + HostFile::HOSTNAME => HOSTNAME_STR.read().unwrap(), + HostFile::RESOLV_CONF => RESOLV_CONF_STR.read().unwrap(), + _ => return_errno!(EINVAL, "Unsupported host file"), + }; + + match &*host_file_str { + Some(str) => { + enclave_file.write(str.as_bytes()); + } + None => { + warn!("The host file: {:?} does not exist", file_path); + } + } + Ok(()) +} + +pub fn parse_host_file(host_file: HostFile, host_file_ptr: *const c_char) -> Result { + // Read host file + let host_file_bytes = unsafe { CStr::from_ptr(host_file_ptr).to_bytes() }; + let host_file_str = str::from_utf8(host_file_bytes) + .map_err(|_| errno!(EINVAL, "host file contains non UTF-8 characters"))?; + + match host_file { + HostFile::HOSTS => { + // TODO: Parsing hosts + } + HostFile::HOSTNAME => { + // TODO: Parsing hostname + } + HostFile::RESOLV_CONF => { + // Parse and inspect host file + if let Err(_) = resolv_conf::Config::parse(host_file_bytes) { + return_errno!(EINVAL, "malformated host /etc/resolv.conf"); + } + } + _ => return_errno!(EINVAL, "Unsupported host file"), + }; + + Ok(host_file_str.to_string()) +} diff --git a/src/libos/src/util/mod.rs b/src/libos/src/util/mod.rs index 8f6b5404..4a4e3c68 100644 --- a/src/libos/src/util/mod.rs +++ b/src/libos/src/util/mod.rs @@ -1,9 +1,9 @@ use super::*; pub mod dirty; +pub mod host_file_util; pub mod log; pub mod mem_util; pub mod mpx_util; -pub mod resolv_conf_util; pub mod sgx; pub mod sync; diff --git a/src/libos/src/util/resolv_conf_util.rs b/src/libos/src/util/resolv_conf_util.rs deleted file mode 100644 index 999be775..00000000 --- a/src/libos/src/util/resolv_conf_util.rs +++ /dev/null @@ -1,37 +0,0 @@ -use super::*; -use crate::fs::{AccessMode, CreationFlags, FileMode, 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(), - FileMode::from_bits(0o666).unwrap(), - )?; - 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 { - // 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()) -} diff --git a/src/pal/include/occlum_pal_api.h b/src/pal/include/occlum_pal_api.h index 22d80f8e..dfbece25 100644 --- a/src/pal/include/occlum_pal_api.h +++ b/src/pal/include/occlum_pal_api.h @@ -93,6 +93,13 @@ struct occlum_pal_create_process_args { int *pid; }; +// todo: more detailed description +struct host_file_buffer { + const char *resolv_conf_ptr; + const char *hosts_ptr; + const char *hostname_ptr; +}; + /* * The struct which consists of arguments needed by occlum_pal_exec */ diff --git a/src/pal/src/pal_api.c b/src/pal/src/pal_api.c index d2e35504..6b8ea9de 100644 --- a/src/pal/src/pal_api.c +++ b/src/pal/src/pal_api.c @@ -2,7 +2,7 @@ #include "Enclave_u.h" #include "pal_enclave.h" #include "pal_error.h" -#include "pal_load_resolv_conf.h" +#include "pal_load_file.h" #include "pal_interrupt_thread.h" #include "pal_log.h" #include "pal_sig_handler.h" @@ -107,11 +107,24 @@ 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(); + struct host_file_buffer file_buffer = { + .hostname_ptr = pal_load_file("/etc/hostname"), + .hosts_ptr = pal_load_file("/etc/hosts"), + .resolv_conf_ptr = pal_load_file("/etc/resolv.conf"), + }; + + const struct host_file_buffer *file_buffer_ptr = &file_buffer; + sgx_status_t ecall_status = occlum_ecall_init(eid, &ecall_ret, attr->log_level, - resolved_path, resolv_conf_ptr); - free((void *)resolv_conf_ptr); - resolv_conf_ptr = NULL; + resolved_path, file_buffer_ptr); + + free((void *)file_buffer.hostname_ptr); + file_buffer.hostname_ptr = NULL; + free((void *)file_buffer.hosts_ptr); + file_buffer.hosts_ptr = NULL; + free((void *)file_buffer.resolv_conf_ptr); + file_buffer.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); diff --git a/src/pal/src/pal_load_file.c b/src/pal/src/pal_load_file.c new file mode 100644 index 00000000..941e0a22 --- /dev/null +++ b/src/pal/src/pal_load_file.c @@ -0,0 +1,24 @@ +#include +#include +#include "pal_log.h" + +char *pal_load_file(const char *filename) { + FILE *fp = fopen(filename, "rb"); + + if (fp == NULL) { + PAL_WARN("Warning: Failed to open file: %s", filename); + return NULL; + } + fseek(fp, 0, SEEK_END); + long fsize = ftell(fp); + fseek(fp, 0, SEEK_SET); + char *file_buffer = malloc(fsize + 1); + if (file_buffer == NULL) { + PAL_WARN("Warning: Failed to malloc buffer for file: %s", filename); + return NULL; + } + fread(file_buffer, 1, fsize, fp); + file_buffer[fsize] = 0; + fclose(fp); + return file_buffer; +} diff --git a/src/pal/src/pal_load_file.h b/src/pal/src/pal_load_file.h new file mode 100644 index 00000000..467c5083 --- /dev/null +++ b/src/pal/src/pal_load_file.h @@ -0,0 +1,6 @@ +#ifndef __PAL_LOAD_FILE_H__ +#define __PAL_LOAD_FILE_H__ + +char *pal_load_file(const char *filename); + +#endif /* __PAL_LOAD_FILE_H__ */ diff --git a/src/pal/src/pal_load_resolv_conf.c b/src/pal/src/pal_load_resolv_conf.c deleted file mode 100644 index 2b9f1019..00000000 --- a/src/pal/src/pal_load_resolv_conf.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include -#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; -} diff --git a/src/pal/src/pal_load_resolv_conf.h b/src/pal/src/pal_load_resolv_conf.h deleted file mode 100644 index 9501223b..00000000 --- a/src/pal/src/pal_load_resolv_conf.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __PAL_LOAD_RESOLV_CONF_H__ -#define __PAL_LOAD_RESOLV_CONF_H__ - -char *pal_load_resolv_conf(void); - -#endif /* __PAL_LOAD_RESOLV_CONF_H__ */