diff --git a/LibOS/shim/src/sys/shim_ioctl.c b/LibOS/shim/src/sys/shim_ioctl.c index 57aef669..9bbdcc9b 100644 --- a/LibOS/shim/src/sys/shim_ioctl.c +++ b/LibOS/shim/src/sys/shim_ioctl.c @@ -41,7 +41,7 @@ #define TERM_DEFAULT_CFLAG (B38400 | CS8 | CREAD) #define TERM_DEFAULT_LFLAG (ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN) -static int ioctl_termios(struct shim_handle* hdl, unsigned int cmd, unsigned long arg) { +static int ioctl_termios(int fd, struct shim_handle* hdl, unsigned int cmd, unsigned long arg) { if (hdl->type != TYPE_FILE || hdl->info.file.type != FILE_TTY) return -ENOTTY; @@ -58,14 +58,21 @@ static int ioctl_termios(struct shim_handle* hdl, unsigned int cmd, unsigned lon return -EINVAL; case TCGETS: { -#if 0 - struct termios * termios = (struct termios *) arg; + /* proactively set termios, it doesn't hurt */ + struct termios* termios = (struct termios*)arg; termios->c_iflag = TERM_DEFAULT_IFLAG; termios->c_oflag = TERM_DEFAULT_OFLAG; termios->c_cflag = TERM_DEFAULT_CFLAG; termios->c_lflag = TERM_DEFAULT_LFLAG; - return 0; -#endif + + if (fd == STDOUT_FILENO) { + /* special case: Glibc wants to know whether STDOUT is TTY (app writes to terminal) + * or non-TTY (app writes to pipe/file); Graphene buffers this info in PAL's + * is_stdout_tty field */ + if (PAL_CB(is_stdout_tty)) + return 0; + } + return -EINVAL; } @@ -346,7 +353,7 @@ int shim_do_ioctl(int fd, unsigned long cmd, unsigned long arg) { case TIOCSETD: case TIOCGETD: case TCSBRKP: - ret = ioctl_termios(hdl, cmd, arg); + ret = ioctl_termios(fd, hdl, cmd, arg); break; case FIONBIO: if (hdl->fs && hdl->fs->fs_ops && hdl->fs->fs_ops->setflags) @@ -374,7 +381,7 @@ int shim_do_ioctl(int fd, unsigned long cmd, unsigned long arg) { case TIOCSERGETLSR: case TIOCSERGETMULTI: case TIOCSERSETMULTI: - ret = ioctl_termios(hdl, cmd, arg); + ret = ioctl_termios(fd, hdl, cmd, arg); break; case FDCLRPRM: diff --git a/Pal/include/pal/pal.h b/Pal/include/pal/pal.h index 6d75a77c..4dd3b99f 100644 --- a/Pal/include/pal/pal.h +++ b/Pal/include/pal/pal.h @@ -341,6 +341,11 @@ typedef struct PAL_CONTROL_ { PAL_CPU_INFO cpu_info; /*!< CPU information (only required ones) */ PAL_MEM_INFO mem_info; /*!< memory information (only required ones) */ + + /* + * Misc + */ + PAL_BOL is_stdout_tty; /*!< STDOUT is TTY (app prints to term) or non-TTY (to pipe/file) */ } PAL_CONTROL; #define pal_control (*pal_control_addr()) diff --git a/Pal/src/db_main.c b/Pal/src/db_main.c index 4a5de106..adf35730 100644 --- a/Pal/src/db_main.c +++ b/Pal/src/db_main.c @@ -395,6 +395,7 @@ noreturn void pal_main ( __pal_control.host_type = XSTRINGIFY(HOST_TYPE); __pal_control.process_id = _DkGetProcessId(); __pal_control.host_id = _DkGetHostId(); + __pal_control.is_stdout_tty = _DkIsStdoutTty(); __pal_control.manifest_handle = manifest_handle; __pal_control.executable = exec_uri; __pal_control.parent_process = parent_process; diff --git a/Pal/src/host/Linux-SGX/db_main.c b/Pal/src/host/Linux-SGX/db_main.c index c5809a3d..3084f20e 100644 --- a/Pal/src/host/Linux-SGX/db_main.c +++ b/Pal/src/host/Linux-SGX/db_main.c @@ -82,6 +82,11 @@ PAL_NUM _DkGetHostId (void) return 0; } +PAL_BOL _DkIsStdoutTty(void) { + /* is_stdout_tty is initialized in untrusted runtime during enclave creation and buffered */ + return pal_sec.is_stdout_tty; +} + #include "elf-x86_64.h" #include "dynamic_link.h" #include @@ -272,6 +277,7 @@ void pal_linux_main(char * uptr_args, uint64_t args_size, COPY_ARRAY(pal_sec.pipe_prefix, sec_info.pipe_prefix); pal_sec.qe_targetinfo = sec_info.qe_targetinfo; + pal_sec.is_stdout_tty = sec_info.is_stdout_tty; #ifdef DEBUG pal_sec.in_gdb = sec_info.in_gdb; #endif diff --git a/Pal/src/host/Linux-SGX/pal_security.h b/Pal/src/host/Linux-SGX/pal_security.h index 22e13373..de9938a8 100644 --- a/Pal/src/host/Linux-SGX/pal_security.h +++ b/Pal/src/host/Linux-SGX/pal_security.h @@ -52,6 +52,9 @@ struct pal_sec { /* Need to pass in the number of cores */ PAL_NUM num_cpus; + /* STDOUT is TTY (app prints to term) or non-TTY (app prints to pipe/file) */ + PAL_BOL is_stdout_tty; + #ifdef DEBUG PAL_BOL in_gdb; #endif diff --git a/Pal/src/host/Linux-SGX/sgx_main.c b/Pal/src/host/Linux-SGX/sgx_main.c index dc1125a0..5959e4d3 100644 --- a/Pal/src/host/Linux-SGX/sgx_main.c +++ b/Pal/src/host/Linux-SGX/sgx_main.c @@ -10,16 +10,17 @@ #include "sgx_internal.h" #include "sgx_tls.h" +#include #include +#include #include +#include #include #include #include -#include -#include - #include #include +#include size_t g_page_size = PRESET_PAGESIZE; @@ -789,6 +790,15 @@ static int load_enclave (struct pal_enclave * enclave, } #endif + struct termios term; + ret = INLINE_SYSCALL(ioctl, 3, STDOUT_FILENO, TCGETS, &term); + if (IS_ERR(ret)) { + /* mark STDOUT as not TTY (app writes to pipe/file); Glibc considers it fully-buffered */ + pal_sec->is_stdout_tty = false; + } + /* mark STDOUT as TTY (app writes to terminal); Glibc considers it line-buffered */ + pal_sec->is_stdout_tty = true; + enclave->manifest = manifest_fd; ret = load_manifest(enclave->manifest, &enclave->config); diff --git a/Pal/src/host/Linux/db_main.c b/Pal/src/host/Linux/db_main.c index 299d0761..e457be42 100644 --- a/Pal/src/host/Linux/db_main.c +++ b/Pal/src/host/Linux/db_main.c @@ -37,6 +37,7 @@ #include #include #include +#include /* At the begining of entry point, rsp starts at argc, then argvs, envps and auxvs. Here we store rsp to rdi, so it will not be @@ -188,6 +189,18 @@ PAL_NUM _DkGetHostId (void) return 0; } +PAL_BOL _DkIsStdoutTty(void) { + struct termios term; + int ret = INLINE_SYSCALL(ioctl, 3, STDOUT_FILENO, TCGETS, &term); + if (IS_ERR(ret)) { + /* mark STDOUT as not TTY (app writes to pipe/file); Glibc considers it fully-buffered */ + return false; + } + + /* mark STDOUT as TTY (app writes to terminal); Glibc considers it line-buffered */ + return true; +} + #include "dynamic_link.h" void setup_pal_map (struct link_map * map); diff --git a/Pal/src/host/Skeleton/db_main.c b/Pal/src/host/Skeleton/db_main.c index 73c48335..b760504a 100644 --- a/Pal/src/host/Skeleton/db_main.c +++ b/Pal/src/host/Skeleton/db_main.c @@ -56,6 +56,12 @@ PAL_NUM _DkGetHostId (void) return 0; } +PAL_BOL _DkIsStdoutTty(void) { + /* mark STDOUT as not TTY (app writes to pipe/file); Glibc considers it fully-buffered */ + return false; +} + +int _DkGetCPUInfo (PAL_CPU_INFO * ci) int _DkGetCPUInfo (PAL_CPU_INFO * ci) { /* needs to be implemented */ diff --git a/Pal/src/pal_internal.h b/Pal/src/pal_internal.h index e6c39427..b785e243 100644 --- a/Pal/src/pal_internal.h +++ b/Pal/src/pal_internal.h @@ -219,6 +219,7 @@ void _DkGetAvailableUserAddressRange (PAL_PTR * start, PAL_PTR * end, PAL_PTR * bool _DkCheckMemoryMappable (const void * addr, size_t size); PAL_NUM _DkGetProcessId (void); PAL_NUM _DkGetHostId (void); +PAL_BOL _DkIsStdoutTty(void); unsigned long _DkMemoryQuota (void); unsigned long _DkMemoryAvailableQuota (void); // Returns 0 on success, negative PAL code on failure