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