Add hosts and hostname file

This commit is contained in:
ClawSeven 2021-08-26 18:54:31 +08:00 committed by Zongmin.Gu
parent 3e15eb059c
commit 15932a54b6
16 changed files with 221 additions and 94 deletions

@ -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:

@ -1,4 +0,0 @@
127.0.0.1 occlum-node
127.0.0.1 localhost
::1 occlum-node
::1 localhost

@ -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.

@ -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)];

@ -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<Vec<PathBuf>> =
RwLock::new(config::LIBOS_CONFIG.entry_points.clone());
pub static ref RESOLV_CONF_STR: RwLock<Option<String>> = RwLock::new(None);
pub static ref HOSTNAME_STR: RwLock<Option<String>> = RwLock::new(None);
pub static ref HOSTS_STR: RwLock<Option<String>> = 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
}

@ -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(())
}

@ -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;
}

@ -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<String> {
// 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())
}

@ -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;

@ -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<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())
}

@ -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
*/

@ -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);

@ -0,0 +1,24 @@
#include <stdio.h>
#include <stdlib.h>
#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;
}

@ -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__ */

@ -1,24 +0,0 @@
#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;
}

@ -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__ */