Add parser for hostname and hosts
This commit is contained in:
parent
15932a54b6
commit
ffdd4d95a4
20
src/libos/Cargo.lock
generated
20
src/libos/Cargo.lock
generated
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Occlum"
|
||||
version = "0.27.0"
|
||||
@ -22,6 +24,7 @@ dependencies = [
|
||||
"rcore-fs-ramfs",
|
||||
"rcore-fs-sefs",
|
||||
"rcore-fs-unionfs",
|
||||
"regex",
|
||||
"resolv-conf",
|
||||
"ringbuf",
|
||||
"scroll",
|
||||
@ -518,6 +521,23 @@ dependencies = [
|
||||
"rand_core 0.3.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.1"
|
||||
source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
"sgx_tstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.12"
|
||||
source = "git+https://github.com/mesalock-linux/regex-sgx#76aef86f9836532d17764523d0fa23bb7d2e31cf"
|
||||
dependencies = [
|
||||
"sgx_tstd",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "resolv-conf"
|
||||
version = "0.7.0"
|
||||
|
@ -29,6 +29,7 @@ memoffset = "0.6.1"
|
||||
scroll = { version = "0.10.2", default-features = false }
|
||||
itertools = { version = "0.10.0", default-features = false, features = ["use_alloc"] }
|
||||
ctor = "0.1"
|
||||
regex = { git = "https://github.com/mesalock-linux/regex-sgx", default-features = false, features = ["std", "unicode", "mesalock_sgx"] }
|
||||
|
||||
[patch.'https://github.com/apache/teaclave-sgx-sdk.git']
|
||||
sgx_tstd = { path = "../../deps/rust-sgx-sdk/sgx_tstd" }
|
||||
|
@ -29,11 +29,11 @@ typedef struct itimerspec{
|
||||
struct _timespec it_value;
|
||||
} itimerspec_t;
|
||||
|
||||
// todo: more detailed description
|
||||
// The host_file_buffer struct includes /etc/resolv.conf, /etc/hosts and /etc/hostname buffer
|
||||
struct host_file_buffer {
|
||||
const char* resolv_conf_ptr;
|
||||
const char* hosts_ptr;
|
||||
const char* hostname_ptr;
|
||||
const char* resolv_conf_buf;
|
||||
const char* hosts_buf;
|
||||
const char* hostname_buf;
|
||||
};
|
||||
|
||||
#define FD_SETSIZE 1024
|
||||
|
@ -98,7 +98,7 @@ pub extern "C" fn occlum_ecall_init(
|
||||
});
|
||||
|
||||
// Parse host file
|
||||
let resolv_conf_ptr = unsafe { (*file_buffer).resolv_conf_ptr };
|
||||
let resolv_conf_ptr = unsafe { (*file_buffer).resolv_conf_buf };
|
||||
match parse_host_file(HostFile::RESOLV_CONF, resolv_conf_ptr) {
|
||||
Err(e) => {
|
||||
error!("failed to parse /etc/resolv.conf: {}", e.backtrace());
|
||||
@ -111,12 +111,13 @@ pub extern "C" fn occlum_ecall_init(
|
||||
}
|
||||
}
|
||||
|
||||
let hostname_ptr = unsafe { (*file_buffer).hostname_ptr };
|
||||
let hostname_ptr = unsafe { (*file_buffer).hostname_buf };
|
||||
match parse_host_file(HostFile::HOSTNAME, hostname_ptr) {
|
||||
Err(e) => {
|
||||
error!("failed to parse /etc/hostname: {}", e.backtrace());
|
||||
}
|
||||
Ok(hostname_str) => {
|
||||
misc::init_nodename(&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());
|
||||
@ -124,7 +125,7 @@ pub extern "C" fn occlum_ecall_init(
|
||||
}
|
||||
}
|
||||
|
||||
let hosts_ptr = unsafe { (*file_buffer).hosts_ptr };
|
||||
let hosts_ptr = unsafe { (*file_buffer).hosts_buf };
|
||||
match parse_host_file(HostFile::HOSTS, hosts_ptr) {
|
||||
Err(e) => {
|
||||
error!("failed to parse /etc/hosts: {}", e.backtrace());
|
||||
|
@ -10,4 +10,4 @@ mod uname;
|
||||
pub use self::random::{do_getrandom, get_random, RandFlags};
|
||||
pub use self::rlimit::{do_prlimit, resource_t, rlimit_t, ResourceLimits};
|
||||
pub use self::sysinfo::{do_sysinfo, sysinfo_t};
|
||||
pub use self::uname::{do_uname, utsname_t};
|
||||
pub use self::uname::{do_uname, init_nodename, utsname_t};
|
||||
|
@ -1,7 +1,5 @@
|
||||
use super::*;
|
||||
use crate::fs::{AccessMode, CreationFlags, FileMode, FsView};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::str;
|
||||
/// A sample of `struct utsname`
|
||||
/// ```
|
||||
/// sysname = Linux
|
||||
@ -26,7 +24,7 @@ pub struct utsname_t {
|
||||
|
||||
pub fn do_uname(name: &mut utsname_t) -> Result<()> {
|
||||
copy_from_cstr_to_u8_array(&SYSNAME, &mut name.sysname);
|
||||
obtain_nodename(&mut name.nodename);
|
||||
copy_from_cstr_to_u8_array(&NODENAME.read().unwrap(), &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);
|
||||
@ -36,7 +34,7 @@ pub fn do_uname(name: &mut utsname_t) -> Result<()> {
|
||||
|
||||
lazy_static! {
|
||||
static ref SYSNAME: CString = CString::new("Occlum").unwrap();
|
||||
static ref NODENAME: CString = CString::new("occlum-node").unwrap();
|
||||
static ref NODENAME: RwLock<CString> = RwLock::new(CString::new("occlum-node").unwrap());
|
||||
static ref RELEASE: CString = CString::new("0.1").unwrap();
|
||||
static ref VERSION: CString = CString::new("0.1").unwrap();
|
||||
static ref MACHINE: CString = CString::new("x86-64").unwrap();
|
||||
@ -50,31 +48,8 @@ fn copy_from_cstr_to_u8_array(src: &CStr, dst: &mut [u8]) {
|
||||
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;
|
||||
pub fn init_nodename(nodename_str: &str) {
|
||||
let nodename_cstr = CString::new(nodename_str).unwrap();
|
||||
let mut nodename = NODENAME.write().unwrap();
|
||||
*nodename = nodename_cstr;
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ 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 resolv_conf_buf: *const c_char,
|
||||
pub hosts_buf: *const c_char,
|
||||
pub hostname_buf: *const c_char,
|
||||
}
|
||||
|
||||
pub enum HostFile {
|
||||
@ -57,15 +57,22 @@ pub fn parse_host_file(host_file: HostFile, host_file_ptr: *const c_char) -> Res
|
||||
let host_file_str = str::from_utf8(host_file_bytes)
|
||||
.map_err(|_| errno!(EINVAL, "host file contains non UTF-8 characters"))?;
|
||||
|
||||
// Parse and inspect host file
|
||||
match host_file {
|
||||
HostFile::HOSTS => {
|
||||
// TODO: Parsing hosts
|
||||
}
|
||||
HostFile::HOSTNAME => {
|
||||
// TODO: Parsing hostname
|
||||
if let Err(_) = hosts_parser_util::parse_hosts_buffer(host_file_bytes) {
|
||||
return_errno!(EINVAL, "malformated host /etc/hosts");
|
||||
}
|
||||
}
|
||||
HostFile::HOSTNAME => match hosts_parser_util::parse_hostname_buffer(host_file_bytes) {
|
||||
Err(_) => {
|
||||
return_errno!(EINVAL, "malformated host /etc/hostname");
|
||||
}
|
||||
Ok(hostname_str) => {
|
||||
return Ok(hostname_str);
|
||||
}
|
||||
},
|
||||
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");
|
||||
}
|
||||
|
103
src/libos/src/util/hosts_parser_util.rs
Normal file
103
src/libos/src/util/hosts_parser_util.rs
Normal file
@ -0,0 +1,103 @@
|
||||
use super::*;
|
||||
use regex::Regex;
|
||||
use std::net::IpAddr;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
use std::str::FromStr;
|
||||
|
||||
lazy_static! {
|
||||
// The hostname regex is compliant with RFC1123
|
||||
static ref HOSTNAME_RE: Regex = Regex::new(r"^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct HostEntry {
|
||||
ip: String,
|
||||
hostname: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct Hosts {
|
||||
pub entries: Vec<HostEntry>,
|
||||
}
|
||||
|
||||
impl FromStr for HostEntry {
|
||||
type Err = error::Error;
|
||||
fn from_str(line: &str) -> Result<Self> {
|
||||
let slice: Vec<String> = line.split_whitespace().map(|s| s.to_string()).collect();
|
||||
|
||||
// check IP:
|
||||
let ip = match slice.first() {
|
||||
Some(ip) => ip,
|
||||
None => {
|
||||
return_errno!(EINVAL, "malformated ip in hosts file");
|
||||
}
|
||||
};
|
||||
|
||||
let _ip_addr: IpAddr = match ip.parse() {
|
||||
Ok(ip) => ip,
|
||||
Err(_) => {
|
||||
return_errno!(EINVAL, "malformated ip in hosts file");
|
||||
}
|
||||
};
|
||||
|
||||
let mut hostname: Vec<String> = Vec::new();
|
||||
for i in slice[1..].to_vec() {
|
||||
if !HOSTNAME_RE.is_match(&i) {
|
||||
return_errno!(EINVAL, "malformated hostname in hosts file");
|
||||
}
|
||||
hostname.push(i.to_owned());
|
||||
}
|
||||
|
||||
if hostname.is_empty() {
|
||||
return_errno!(EINVAL, "malformated hostname in hosts file");
|
||||
}
|
||||
Ok(HostEntry {
|
||||
ip: ip.to_string(),
|
||||
hostname,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_hosts_buffer(bytes: &[u8]) -> Result<Hosts> {
|
||||
let mut hosts: Hosts = Default::default();
|
||||
for (_, line) in bytes.split(|&x| x == b'\n').enumerate() {
|
||||
let line = str::from_utf8(line).unwrap();
|
||||
let line = line.trim_start();
|
||||
match line.chars().next() {
|
||||
// comment
|
||||
Some('#') => continue,
|
||||
// empty line
|
||||
None => continue,
|
||||
// valid line
|
||||
Some(_) => {}
|
||||
}
|
||||
hosts.entries.push(line.parse()?);
|
||||
}
|
||||
Ok(hosts)
|
||||
}
|
||||
|
||||
pub fn parse_hostname_buffer(bytes: &[u8]) -> Result<String> {
|
||||
let mut hostname: Vec<String> = Vec::new();
|
||||
for (_, line) in bytes.split(|&x| x == b'\n').enumerate() {
|
||||
let line = str::from_utf8(line).unwrap();
|
||||
let line = line.trim_start();
|
||||
match line.chars().next() {
|
||||
// comment
|
||||
Some('#') => continue,
|
||||
// empty line
|
||||
None => continue,
|
||||
// valid line
|
||||
Some(_) => {}
|
||||
}
|
||||
if (!HOSTNAME_RE.is_match(&line)) | (line.len() > 64) {
|
||||
return_errno!(EINVAL, "malformated hostname in /etc/hostname file");
|
||||
}
|
||||
hostname.push(line.to_owned());
|
||||
}
|
||||
|
||||
if hostname.len() != 1 {
|
||||
return_errno!(EINVAL, "malformated hostname in /etc/hostname file");
|
||||
}
|
||||
Ok(hostname[0].clone())
|
||||
}
|
@ -2,6 +2,7 @@ use super::*;
|
||||
|
||||
pub mod dirty;
|
||||
pub mod host_file_util;
|
||||
pub mod hosts_parser_util;
|
||||
pub mod log;
|
||||
pub mod mem_util;
|
||||
pub mod mpx_util;
|
||||
|
@ -93,11 +93,10 @@ 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;
|
||||
const char *resolv_conf_buf;
|
||||
const char *hosts_buf;
|
||||
const char *hostname_buf;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -165,6 +164,8 @@ int occlum_pal_kill(int pid, int sig);
|
||||
*/
|
||||
int occlum_pal_destroy(void);
|
||||
|
||||
void free_host_file_buffer(struct host_file_buffer file_buffer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -108,9 +108,9 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) {
|
||||
|
||||
int ecall_ret = 0;
|
||||
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"),
|
||||
.hostname_buf = pal_load_file_to_string("/etc/hostname"),
|
||||
.hosts_buf = pal_load_file_to_string("/etc/hosts"),
|
||||
.resolv_conf_buf = pal_load_file_to_string("/etc/resolv.conf"),
|
||||
};
|
||||
|
||||
const struct host_file_buffer *file_buffer_ptr = &file_buffer;
|
||||
@ -118,12 +118,7 @@ int occlum_pal_init(const struct occlum_pal_attr *attr) {
|
||||
sgx_status_t ecall_status = occlum_ecall_init(eid, &ecall_ret, attr->log_level,
|
||||
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;
|
||||
free_host_file_buffer(file_buffer);
|
||||
|
||||
if (ecall_status != SGX_SUCCESS) {
|
||||
const char *sgx_err = pal_get_sgx_error_msg(ecall_status);
|
||||
@ -285,6 +280,17 @@ int occlum_pal_destroy(void) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void free_host_file_buffer(struct host_file_buffer file_buffer) {
|
||||
free((void *)file_buffer.hostname_buf);
|
||||
file_buffer.hostname_buf = NULL;
|
||||
|
||||
free((void *)file_buffer.hosts_buf);
|
||||
file_buffer.hosts_buf = NULL;
|
||||
|
||||
free((void *)file_buffer.resolv_conf_buf);
|
||||
file_buffer.resolv_conf_buf = NULL;
|
||||
}
|
||||
|
||||
int pal_get_version(void) __attribute__((weak, alias ("occlum_pal_get_version")));
|
||||
|
||||
int pal_init(const struct occlum_pal_attr *attr)\
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "pal_log.h"
|
||||
|
||||
char *pal_load_file(const char *filename) {
|
||||
char *pal_load_file_to_string(const char *filename) {
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
|
||||
if (fp == NULL) {
|
||||
@ -18,7 +18,7 @@ char *pal_load_file(const char *filename) {
|
||||
return NULL;
|
||||
}
|
||||
fread(file_buffer, 1, fsize, fp);
|
||||
file_buffer[fsize] = 0;
|
||||
file_buffer[fsize] = '\0';
|
||||
fclose(fp);
|
||||
return file_buffer;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#ifndef __PAL_LOAD_FILE_H__
|
||||
#define __PAL_LOAD_FILE_H__
|
||||
|
||||
char *pal_load_file(const char *filename);
|
||||
char *pal_load_file_to_string(const char *filename);
|
||||
|
||||
#endif /* __PAL_LOAD_FILE_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user