Quellcode durchsuchen

[Pal/{Linux,Linux-SGX,FreeBSD}] Replace stream_in & stream_out with one stream socketpair

Previously, parent and child processes communicated via two unidirectional
pipes: process.stream_in and process.stream_out. Now these pipes were replaced
with bidirectional socketpairs, so there is no need to distinguish between
read and write ends. This commit merges stream_in and steam_out FDs into one
stream FD, and simplifies corresponding code (especially SGX implementation).
Dmitrii Kuvaiskii vor 5 Jahren
Ursprung
Commit
88f7fae9f8

+ 27 - 52
Pal/src/host/FreeBSD/db_process.c

@@ -52,22 +52,16 @@ static inline int create_process_handle (PAL_HANDLE * parent,
                                          PAL_HANDLE * child)
 {
     PAL_HANDLE phdl = NULL, chdl = NULL;
-    int fds[6] = { -1, -1, -1, -1, -1, -1 };
+    int fds[4] = { -1, -1, -1, -1 };
     int socktype = SOCK_STREAM | SOCK_CLOEXEC;
     int ret;
 
     if (IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[0]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[4])))) {
+        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2])))) {
         ret = -PAL_ERROR_DENIED;
         goto out;
     }
 
-    int proc_fds[2][3] = {
-        { fds[0], fds[3], fds[4] },
-        { fds[2], fds[1], fds[5] },
-    };
-
     phdl = malloc(HANDLE_SIZE(process));
     if (!phdl) {
         ret = -PAL_ERROR_NOMEM;
@@ -75,10 +69,9 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(phdl, process);
-    phdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
-    phdl->process.stream_in   = proc_fds[0][0];
-    phdl->process.stream_out  = proc_fds[0][1];
-    phdl->process.cargo       = proc_fds[0][2];
+    phdl->hdr.flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
+    phdl->process.stream      = fds[0];
+    phdl->process.cargo       = fds[2];
     phdl->process.pid         = bsd_state.pid;
     phdl->process.nonblocking = PAL_FALSE;
 
@@ -89,10 +82,9 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(chdl, process);
-    chdl->hdr.flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
-    chdl->process.stream_in   = proc_fds[1][0];
-    chdl->process.stream_out  = proc_fds[1][1];
-    chdl->process.cargo       = proc_fds[1][2];
+    chdl->hdr.flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
+    chdl->process.stream      = fds[1];
+    chdl->process.cargo       = fds[3];
     chdl->process.pid         = 0; /* unknown yet */
     chdl->process.nonblocking = PAL_FALSE;
 
@@ -105,7 +97,7 @@ out:
             _DkObjectClose(phdl);
         if (chdl)
             _DkObjectClose(chdl);
-        for (int i = 0 ; i < 6 ; i++)
+        for (int i = 0; i < 4; i++)
             if (fds[i] != -1)
                 INLINE_SYSCALL(close, 1, fds[i]);
     }
@@ -133,8 +125,7 @@ static int child_process (void * param)
     struct proc_param * proc_param = param;
     int ret;
 
-    ret = INLINE_SYSCALL(dup2, 2, proc_param->parent->process.stream_in,
-                         PROC_INIT_FD);
+    ret = INLINE_SYSCALL(dup2, 2, proc_param->parent->process.stream, PROC_INIT_FD);
     if (IS_ERR(ret))
         goto failed;
 
@@ -272,7 +263,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args)
     /* step 4: send parameters over the process handle */
 
     ret = INLINE_SYSCALL(write, 3,
-                         child_handle->process.stream_out,
+                         child_handle->process.stream,
                          proc_args,
                          sizeof(struct proc_args) + datasz);
 
@@ -388,8 +379,7 @@ noreturn void _DkProcessExit (int exitcode)
 static int proc_read (PAL_HANDLE handle, int offset, int count,
                           void * buffer)
 {
-    int bytes = INLINE_SYSCALL(read, 3, handle->process.stream_in, buffer,
-                               count);
+    int bytes = INLINE_SYSCALL(read, 3, handle->process.stream, buffer, count);
 
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
@@ -407,13 +397,12 @@ static int proc_read (PAL_HANDLE handle, int offset, int count,
 static int proc_write (PAL_HANDLE handle, int offset, int count,
                        const void * buffer)
 {
-    int bytes = INLINE_SYSCALL(write, 3, handle->process.stream_out, buffer,
-                               count);
+    int bytes = INLINE_SYSCALL(write, 3, handle->process.stream, buffer, count);
 
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
             case EWOULDBLOCK:
-                handle->hdr.flags &= ~WRITABLE(1);
+                handle->hdr.flags &= ~WRITABLE(0);
                 return-PAL_ERROR_TRYAGAIN;
             case EINTR:
                 return -PAL_ERROR_INTERRUPTED;
@@ -422,23 +411,18 @@ static int proc_write (PAL_HANDLE handle, int offset, int count,
         }
 
     if (bytes == count)
-        handle->hdr.flags |= WRITABLE(1);
+        handle->hdr.flags |= WRITABLE(0);
     else
-        handle->hdr.flags &= ~WRITABLE(1);
+        handle->hdr.flags &= ~WRITABLE(0);
 
     return bytes;
 }
 
 static int proc_close (PAL_HANDLE handle)
 {
-    if (handle->process.stream_in != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (handle->process.stream_out != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
+    if (handle->process.stream != PAL_IDX_POISON) {
+        INLINE_SYSCALL(close, 1, handle->process.stream);
+        handle->process.stream = PAL_IDX_POISON;
     }
 
     if (handle->process.cargo != PAL_IDX_POISON) {
@@ -466,17 +450,8 @@ static int proc_delete (PAL_HANDLE handle, int access)
             return -PAL_ERROR_INVAL;
     }
 
-    if (access != PAL_DELETE_WR &&
-        handle->process.stream_in != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (access != PAL_DELETE_RD &&
-        handle->process.stream_out != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
-    }
+    if (handle->process.stream != PAL_IDX_POISON)
+        INLINE_SYSCALL(shutdown, 2, handle->process.stream, shutdown);
 
     if (handle->process.cargo != PAL_IDX_POISON)
         INLINE_SYSCALL(shutdown, 2, handle->process.cargo, shutdown);
@@ -488,18 +463,18 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
     int ret, val;
 
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
-    ret = INLINE_SYSCALL(ioctl, 3, handle->process.stream_in, FIONREAD, &val);
+    ret = INLINE_SYSCALL(ioctl, 3, handle->process.stream, FIONREAD, &val);
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
     attr->handle_type  = pal_type_process;
     attr->nonblocking  = handle->process.nonblocking;
-    attr->disconnected = handle->hdr.flags & (ERROR(0)|ERROR(1));
+    attr->disconnected = handle->hdr.flags & ERROR(0);
     attr->readable     = !!val;
-    attr->writable     = handle->hdr.flags & WRITABLE(1);
+    attr->writable     = handle->hdr.flags & WRITABLE(0);
     attr->runnable     = PAL_FALSE;
     attr->pending_size = val;
 
@@ -508,12 +483,12 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 
 static int proc_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
     int ret;
     if (attr->nonblocking != handle->process.nonblocking) {
-        ret = INLINE_SYSCALL(fcntl, 3, handle->process.stream_in, F_SETFL,
+        ret = INLINE_SYSCALL(fcntl, 3, handle->process.stream, F_SETFL,
                              handle->process.nonblocking ? O_NONBLOCK : 0);
 
         if (IS_ERR(ret))

+ 1 - 1
Pal/src/host/FreeBSD/db_streams.c

@@ -284,7 +284,7 @@ int _DkSendHandle (PAL_HANDLE hdl, PAL_HANDLE cargo)
     int fds[MAX_FDS];
     int nfds = 0;
     for (int i = 0 ; i < MAX_FDS ; i++)
-        if (cargo->hdr.flags & (RFD(i)|WFD(1))) {
+        if (cargo->hdr.flags & (RFD(i)|WFD(i))) {
             hdl_hdr.fds |= 1U << i;
             fds[nfds++] = cargo->hdr.fds[i];
         }

+ 1 - 1
Pal/src/host/FreeBSD/pal_host.h

@@ -126,7 +126,7 @@ typedef union pal_handle
 
     struct {
         PAL_HDR hdr;
-        PAL_IDX stream_in, stream_out;
+        PAL_IDX stream;
         PAL_IDX cargo;
         PAL_IDX pid;
         PAL_BOL nonblocking;

+ 3 - 1
Pal/src/host/Linux-SGX/db_main.c

@@ -262,7 +262,9 @@ void pal_linux_main(char * uptr_args, uint64_t args_size,
     COPY_ARRAY(pal_sec.manifest_name, sec_info.manifest_name);
     pal_sec.manifest_name[sizeof(pal_sec.manifest_name) - 1] = '\0';
 
-    COPY_ARRAY(pal_sec.proc_fds, sec_info.proc_fds);
+    pal_sec.stream_fd = sec_info.stream_fd;
+    pal_sec.cargo_fd  = sec_info.cargo_fd;
+
     COPY_ARRAY(pal_sec.pipe_prefix, sec_info.pipe_prefix);
     pal_sec.aesm_targetinfo = sec_info.aesm_targetinfo;
     pal_sec.mcast_port = sec_info.mcast_port;

+ 26 - 41
Pal/src/host/Linux-SGX/db_process.c

@@ -252,24 +252,24 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args)
         return -PAL_ERROR_INVAL;
 
     unsigned int child_pid;
-    int proc_fds[3];
+    int stream_fd;
+    int cargo_fd;
     int nargs = 0, ret;
 
     if (args)
         for (const char ** a = args ; *a ; a++)
             nargs++;
 
-    ret = ocall_create_process(uri, nargs, args, proc_fds, &child_pid);
+    ret = ocall_create_process(uri, nargs, args, &stream_fd, &cargo_fd, &child_pid);
     if (ret < 0)
         return ret;
 
     PAL_HANDLE child = malloc(HANDLE_SIZE(process));
     SET_HANDLE_TYPE(child, process);
-    HANDLE_HDR(child)->flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
-    child->process.stream_in  = proc_fds[0];
-    child->process.stream_out = proc_fds[1];
-    child->process.cargo      = proc_fds[2];
-    child->process.pid = child_pid;
+    HANDLE_HDR(child)->flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
+    child->process.stream      = stream_fd;
+    child->process.cargo       = cargo_fd;
+    child->process.pid         = child_pid;
     child->process.nonblocking = PAL_FALSE;
 
     ret = _DkStreamKeyExchange(child, &child->process.session_key);
@@ -314,11 +314,10 @@ int init_child_process (PAL_HANDLE * parent_handle)
 {
     PAL_HANDLE parent = malloc(HANDLE_SIZE(process));
     SET_HANDLE_TYPE(parent, process);
-    HANDLE_HDR(parent)->flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
+    HANDLE_HDR(parent)->flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
 
-    parent->process.stream_in  = pal_sec.proc_fds[0];
-    parent->process.stream_out = pal_sec.proc_fds[1];
-    parent->process.cargo      = pal_sec.proc_fds[2];
+    parent->process.stream     = pal_sec.stream_fd;
+    parent->process.cargo      = pal_sec.cargo_fd;
     parent->process.pid        = pal_sec.ppid;
     parent->process.nonblocking = PAL_FALSE;
 
@@ -364,7 +363,7 @@ static int64_t proc_read (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (count >= (1ULL << (sizeof(unsigned int) * 8)))
         return -PAL_ERROR_INVAL;
 
-    int bytes = ocall_read(handle->process.stream_in, buffer, count);
+    int bytes = ocall_read(handle->process.stream, buffer, count);
     return IS_ERR(bytes) ? unix_to_pal_error(ERRNO(bytes)) : bytes;
 }
 
@@ -377,33 +376,28 @@ static int64_t proc_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (count >= (1ULL << (sizeof(unsigned int) * 8)))
         return -PAL_ERROR_INVAL;
 
-    int bytes = ocall_write(handle->process.stream_out, buffer, count);
+    int bytes = ocall_write(handle->process.stream, buffer, count);
 
     if (IS_ERR(bytes)) {
         bytes = unix_to_pal_error(ERRNO(bytes));
         if (bytes == -PAL_ERROR_TRYAGAIN)
-            HANDLE_HDR(handle)->flags &= ~WRITABLE(1);
+            HANDLE_HDR(handle)->flags &= ~WRITABLE(0);
         return bytes;
     }
 
     if ((uint64_t)bytes == count)
-        HANDLE_HDR(handle)->flags |= WRITABLE(1);
+        HANDLE_HDR(handle)->flags |= WRITABLE(0);
     else
-        HANDLE_HDR(handle)->flags &= ~WRITABLE(1);
+        HANDLE_HDR(handle)->flags &= ~WRITABLE(0);
 
     return bytes;
 }
 
 static int proc_close (PAL_HANDLE handle)
 {
-    if (handle->process.stream_in != PAL_IDX_POISON) {
-        ocall_close(handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (handle->process.stream_out != PAL_IDX_POISON) {
-        ocall_close(handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
+    if (handle->process.stream != PAL_IDX_POISON) {
+        ocall_close(handle->process.stream);
+        handle->process.stream = PAL_IDX_POISON;
     }
 
     if (handle->process.cargo != PAL_IDX_POISON) {
@@ -431,17 +425,8 @@ static int proc_delete (PAL_HANDLE handle, int access)
             return -PAL_ERROR_INVAL;
     }
 
-    if (access != PAL_DELETE_WR &&
-        handle->process.stream_in != PAL_IDX_POISON) {
-        ocall_close(handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (access != PAL_DELETE_RD &&
-        handle->process.stream_out != PAL_IDX_POISON) {
-        ocall_close(handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
-    }
+    if (handle->process.stream != PAL_IDX_POISON)
+        ocall_shutdown(handle->process.stream, shutdown);
 
     if (handle->process.cargo != PAL_IDX_POISON)
         ocall_shutdown(handle->process.cargo, shutdown);
@@ -451,29 +436,29 @@ static int proc_delete (PAL_HANDLE handle, int access)
 
 static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
-    int ret = ocall_fionread(handle->process.stream_in);
+    int ret = ocall_fionread(handle->process.stream);
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
     memset(attr, 0, sizeof(PAL_STREAM_ATTR));
     attr->pending_size = ret;
-    attr->disconnected = HANDLE_HDR(handle)->flags & (ERROR(0)|ERROR(1));
+    attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
     attr->readable = (attr->pending_size > 0);
-    attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(1);
+    attr->writable = HANDLE_HDR(handle)->flags & WRITABLE(0);
     attr->nonblocking = handle->process.nonblocking;
     return 0;
 }
 
 static int proc_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
     if (attr->nonblocking != handle->process.nonblocking) {
-        int ret = ocall_fsetnonblock(handle->process.stream_in,
+        int ret = ocall_fsetnonblock(handle->process.stream,
                                      handle->process.nonblocking);
         if (IS_ERR(ret))
             return unix_to_pal_error(ERRNO(ret));

+ 1 - 1
Pal/src/host/Linux-SGX/db_streams.c

@@ -267,7 +267,7 @@ int _DkSendHandle(PAL_HANDLE hdl, PAL_HANDLE cargo) {
     unsigned int fds[MAX_FDS];
     unsigned int nfds = 0;
     for (int i = 0; i < MAX_FDS; i++)
-        if (HANDLE_HDR(cargo)->flags & (RFD(i) | WFD(1))) {
+        if (HANDLE_HDR(cargo)->flags & (RFD(i) | WFD(i))) {
             hdl_hdr.fds |= 1U << i;
             fds[nfds++] = cargo->generic.fds[i];
         }

+ 6 - 5
Pal/src/host/Linux-SGX/enclave_ocalls.c

@@ -472,8 +472,8 @@ int ocall_clone_thread (void)
     return sgx_ocall(OCALL_CLONE_THREAD, dummy);
 }
 
-int ocall_create_process(const char* uri, int nargs, const char** args, int procfds[3],
-                         unsigned int* pid) {
+int ocall_create_process(const char* uri, int nargs, const char** args, int* stream_fd,
+                         int* cargo_fd, unsigned int* pid) {
     int retval = 0;
     int ulen = uri ? strlen(uri) + 1 : 0;
     ms_ocall_create_process_t * ms;
@@ -506,9 +506,10 @@ int ocall_create_process(const char* uri, int nargs, const char** args, int proc
     if (!retval) {
         if (pid)
             *pid = ms->ms_pid;
-        procfds[0] = ms->ms_proc_fds[0];
-        procfds[1] = ms->ms_proc_fds[1];
-        procfds[2] = ms->ms_proc_fds[2];
+        if (stream_fd)
+            *stream_fd = ms->ms_stream_fd;
+        if (cargo_fd)
+            *cargo_fd = ms->ms_cargo_fd;
     }
 
     sgx_reset_ustack();

+ 2 - 2
Pal/src/host/Linux-SGX/enclave_ocalls.h

@@ -74,8 +74,8 @@ int ocall_resume_thread (void * tcs);
 
 int ocall_clone_thread (void);
 
-int ocall_create_process(const char* uri, int nargs, const char** args, int procfds[3],
-                         unsigned int* pid);
+int ocall_create_process(const char* uri, int nargs, const char** args, int* stream_fd,
+                         int* cargo_fd, unsigned int* pid);
 
 int ocall_futex(int* uaddr, int op, int val, int64_t timeout_us);
 

+ 2 - 1
Pal/src/host/Linux-SGX/ocall_types.h

@@ -154,7 +154,8 @@ typedef struct {
 typedef struct {
     unsigned int ms_pid;
     const char * ms_uri;
-    int ms_proc_fds[3];
+    int ms_stream_fd;
+    int ms_cargo_fd;
     int ms_nargs;
     const char * ms_args[];
 } ms_ocall_create_process_t;

+ 1 - 1
Pal/src/host/Linux-SGX/pal_host.h

@@ -150,7 +150,7 @@ typedef struct pal_handle
         } sock;
 
         struct {
-            PAL_IDX stream_in, stream_out;
+            PAL_IDX stream;
             PAL_IDX cargo;
             PAL_IDX pid;
             PAL_BOL nonblocking;

+ 1 - 1
Pal/src/host/Linux-SGX/pal_linux.h

@@ -192,7 +192,7 @@ extern struct pal_enclave_config {
 
 #else
 
-int sgx_create_process(const char* uri, int nargs, const char** args, int* retfds);
+int sgx_create_process(const char* uri, int nargs, const char** args, int* stream_fd, int* cargo_fd);
 
 #ifdef DEBUG
 # ifndef SIGCHLD

+ 3 - 2
Pal/src/host/Linux-SGX/pal_security.h

@@ -43,8 +43,9 @@ struct pal_sec {
 
     PAL_SEC_STR     manifest_name;
 
-    /* need three proc fds if it has a parent */
-    PAL_IDX         proc_fds[3];
+    /* child's stream and cargo FDs created and sent over by parent */
+    PAL_IDX         stream_fd;
+    PAL_IDX         cargo_fd;
 
     /* additional information */
     PAL_SEC_STR     pipe_prefix;

+ 2 - 1
Pal/src/host/Linux-SGX/sgx_enclave.c

@@ -232,7 +232,8 @@ static int sgx_ocall_create_process(void * pms)
 {
     ms_ocall_create_process_t * ms = (ms_ocall_create_process_t *) pms;
     ODEBUG(OCALL_CREATE_PROCESS, ms);
-    int ret = sgx_create_process(ms->ms_uri, ms->ms_nargs, ms->ms_args, ms->ms_proc_fds);
+    int ret = sgx_create_process(ms->ms_uri, ms->ms_nargs, ms->ms_args,
+                                 &ms->ms_stream_fd, &ms->ms_cargo_fd);
     if (ret < 0)
         return ret;
     ms->ms_pid = ret;

+ 32 - 45
Pal/src/host/Linux-SGX/sgx_process.c

@@ -41,7 +41,8 @@ struct proc_args {
     PAL_SEC_STR     exec_name;
     unsigned int    instance_id;
     unsigned int    parent_process_id;
-    unsigned int    proc_fds[3];
+    int             stream_fd;
+    int             cargo_fd;
     PAL_SEC_STR     pipe_prefix;
     unsigned int    mcast_port;
 };
@@ -58,17 +59,16 @@ struct proc_args {
  * future compiler.
  */
 static int __attribute_noinline
-vfork_exec(int pipe_input, int proc_fds[3], const char** argv)
-{
+vfork_exec(int child_stream, int parent_stream, int parent_cargo, const char** argv) {
     int ret = ARCH_VFORK();
     if (ret)
         return ret;
 
-    /* child */
-    for (int i = 0 ; i < 3 ; i++)
-        INLINE_SYSCALL(close, 1, proc_fds[i]);
+    /* child: close parent's FDs, rewire child stream to init FD, and execve */
+    INLINE_SYSCALL(close, 1, parent_stream);
+    INLINE_SYSCALL(close, 1, parent_cargo);
 
-    ret = INLINE_SYSCALL(dup2, 2, pipe_input, PROC_INIT_FD);
+    ret = INLINE_SYSCALL(dup2, 2, child_stream, PROC_INIT_FD);
     if (!IS_ERR(ret)) {
         extern char** environ;
         ret = INLINE_SYSCALL(execve, 3, PAL_LOADER, argv, environ);
@@ -80,24 +80,18 @@ vfork_exec(int pipe_input, int proc_fds[3], const char** argv)
     return 0;
 }
 
-int sgx_create_process(const char* uri, int nargs, const char** args, int * retfds) {
+int sgx_create_process(const char* uri, int nargs, const char** args, int* stream_fd, int* cargo_fd) {
     int ret, rete, child;
-    int fds[6] = { -1, -1, -1, -1, -1, -1 };
+    int fds[4] = { -1, -1, -1, -1 };
 
     if (!uri || !strstartswith_static(uri, "file:"))
         return -EINVAL;
 
     int socktype = SOCK_STREAM;
     if (IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[0]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[4]))))
+        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2]))))
         goto out;
 
-    int proc_fds[2][3] = {
-        { fds[0], fds[3], fds[4] },
-        { fds[2], fds[1], fds[5] },
-    };
-
     const char ** argv = __alloca(sizeof(const char *) * (nargs + 2));
     argv[0] = PAL_LOADER;
     memcpy(argv + 1, args, sizeof(const char *) * nargs);
@@ -112,10 +106,11 @@ int sgx_create_process(const char* uri, int nargs, const char** args, int * retf
         goto out;
     }
 
-    ret = vfork_exec(proc_fds[0][0], proc_fds[1], argv);
+    ret = vfork_exec(/*child_stream=*/fds[0], /*parent_stream=*/fds[1], /*parent_cargo=*/fds[3], argv);
     if (IS_ERR(ret))
         goto out;
 
+    /* parent continues here */
     child = ret;
 
     /* children unblock async signals by sgx_signal_setup() */
@@ -125,32 +120,26 @@ int sgx_create_process(const char* uri, int nargs, const char** args, int * retf
         goto out;
     }
 
-    for (int i = 0 ; i < 3 ; i++)
-        INLINE_SYSCALL(close, 1, proc_fds[0][i]);
-
-    int pipe_in = proc_fds[1][0], pipe_out = proc_fds[1][1];
+    INLINE_SYSCALL(close, 1, fds[0]); /* child stream */
+    INLINE_SYSCALL(close, 1, fds[2]); /* child cargo */
 
     struct pal_sec * pal_sec = &pal_enclave.pal_sec;
     struct proc_args proc_args;
     memcpy(proc_args.exec_name, uri, sizeof(PAL_SEC_STR));
-    proc_args.instance_id   = pal_sec->instance_id;
+    proc_args.instance_id       = pal_sec->instance_id;
     proc_args.parent_process_id = pal_sec->pid;
-    proc_args.proc_fds[0] = proc_fds[0][0];
-    proc_args.proc_fds[1] = proc_fds[0][1];
-    proc_args.proc_fds[2] = proc_fds[0][2];
+    proc_args.stream_fd         = fds[0];
+    proc_args.cargo_fd          = fds[2];
     memcpy(proc_args.pipe_prefix, pal_sec->pipe_prefix, sizeof(PAL_SEC_STR));
     proc_args.mcast_port = pal_sec->mcast_port;
 
-    ret = INLINE_SYSCALL(write, 3, pipe_out, &proc_args,
-                         sizeof(struct proc_args));
-
+    ret = INLINE_SYSCALL(write, 3, fds[1], &proc_args, sizeof(struct proc_args));
     if (IS_ERR(ret) || (size_t)ret < sizeof(struct proc_args)) {
         ret = -EPERM;
         goto out;
     }
 
-    ret = INLINE_SYSCALL(read, 3, pipe_in, &rete, sizeof(int));
-
+    ret = INLINE_SYSCALL(read, 3, fds[1], &rete, sizeof(int));
     if (IS_ERR(ret) || (size_t)ret < sizeof(int)) {
         ret = -EPERM;
         goto out;
@@ -161,15 +150,18 @@ int sgx_create_process(const char* uri, int nargs, const char** args, int * retf
         goto out;
     }
 
-    for (int i = 0 ; i < 3 ; i++) {
-        INLINE_SYSCALL(fcntl, 3, proc_fds[1][i], F_SETFD, FD_CLOEXEC);
-        retfds[i] = proc_fds[1][i];
-    }
+    INLINE_SYSCALL(fcntl, 3, fds[1], F_SETFD, FD_CLOEXEC);
+    INLINE_SYSCALL(fcntl, 3, fds[3], F_SETFD, FD_CLOEXEC);
+
+    if (stream_fd)
+        *stream_fd = fds[1];
+    if (cargo_fd)
+        *cargo_fd = fds[3];
 
     ret = child;
 out:
     if (IS_ERR(ret)) {
-        for (int i = 0 ; i < 6 ; i++)
+        for (int i = 0; i < 4; i++)
             if (fds[i] >= 0)
                 INLINE_SYSCALL(close, 1, fds[i]);
     }
@@ -181,28 +173,23 @@ int sgx_init_child_process (struct pal_sec * pal_sec)
 {
     struct proc_args proc_args;
 
-    int ret = INLINE_SYSCALL(read, 3, PROC_INIT_FD, &proc_args,
-                             sizeof(struct proc_args));
-
+    int ret = INLINE_SYSCALL(read, 3, PROC_INIT_FD, &proc_args, sizeof(struct proc_args));
     if (IS_ERR(ret)) {
         if (ERRNO(ret) == EBADF)
             return 0;
-
         return ret;
     }
 
     int child_status = 0;
-    ret = INLINE_SYSCALL(write, 3, proc_args.proc_fds[1], &child_status,
-                         sizeof(int));
+    ret = INLINE_SYSCALL(write, 3, PROC_INIT_FD, &child_status, sizeof(int));
     if (IS_ERR(ret))
         return ret;
 
     memcpy(pal_sec->exec_name, proc_args.exec_name, sizeof(PAL_SEC_STR));
     pal_sec->instance_id   = proc_args.instance_id;
-    pal_sec->ppid        = proc_args.parent_process_id;
-    pal_sec->proc_fds[0] = proc_args.proc_fds[0];
-    pal_sec->proc_fds[1] = proc_args.proc_fds[1];
-    pal_sec->proc_fds[2] = proc_args.proc_fds[2];
+    pal_sec->ppid          = proc_args.parent_process_id;
+    pal_sec->stream_fd     = proc_args.stream_fd;
+    pal_sec->cargo_fd      = proc_args.cargo_fd;
     memcpy(pal_sec->pipe_prefix, proc_args.pipe_prefix, sizeof(PAL_SEC_STR));
     pal_sec->mcast_port  = proc_args.mcast_port;
 

+ 27 - 52
Pal/src/host/Linux/db_process.c

@@ -51,22 +51,16 @@ static inline int create_process_handle (PAL_HANDLE * parent,
                                          PAL_HANDLE * child)
 {
     PAL_HANDLE phdl = NULL, chdl = NULL;
-    int fds[6] = { -1, -1, -1, -1, -1, -1 };
+    int fds[4] = { -1, -1, -1, -1 };
     int socktype = SOCK_STREAM | SOCK_CLOEXEC;
     int ret;
 
     if (IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[0]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2]))) ||
-        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[4])))) {
+        IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, socktype, 0, &fds[2])))) {
         ret = -PAL_ERROR_DENIED;
         goto out;
     }
 
-    int proc_fds[2][3] = {
-        { fds[0], fds[3], fds[4] },
-        { fds[2], fds[1], fds[5] },
-    };
-
     phdl = malloc(HANDLE_SIZE(process));
     if (!phdl) {
         ret = -PAL_ERROR_NOMEM;
@@ -74,10 +68,9 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(phdl, process);
-    HANDLE_HDR(phdl)->flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
-    phdl->process.stream_in   = proc_fds[0][0];
-    phdl->process.stream_out  = proc_fds[0][1];
-    phdl->process.cargo       = proc_fds[0][2];
+    HANDLE_HDR(phdl)->flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
+    phdl->process.stream      = fds[0];
+    phdl->process.cargo       = fds[2];
     phdl->process.pid         = linux_state.pid;
     phdl->process.nonblocking = PAL_FALSE;
 
@@ -88,10 +81,9 @@ static inline int create_process_handle (PAL_HANDLE * parent,
     }
 
     SET_HANDLE_TYPE(chdl, process);
-    HANDLE_HDR(chdl)->flags |= RFD(0)|WFD(1)|RFD(2)|WFD(2)|WRITABLE(1)|WRITABLE(2);
-    chdl->process.stream_in   = proc_fds[1][0];
-    chdl->process.stream_out  = proc_fds[1][1];
-    chdl->process.cargo       = proc_fds[1][2];
+    HANDLE_HDR(chdl)->flags |= RFD(0)|WFD(0)|RFD(1)|WFD(1)|WRITABLE(0)|WRITABLE(1);
+    chdl->process.stream      = fds[1];
+    chdl->process.cargo       = fds[3];
     chdl->process.pid         = 0; /* unknown yet */
     chdl->process.nonblocking = PAL_FALSE;
 
@@ -104,7 +96,7 @@ out:
             _DkObjectClose(phdl);
         if (chdl)
             _DkObjectClose(chdl);
-        for (int i = 0 ; i < 6 ; i++)
+        for (int i = 0; i < 4; i++)
             if (fds[i] != -1)
                 INLINE_SYSCALL(close, 1, fds[i]);
     }
@@ -151,8 +143,7 @@ child_process (struct proc_param * proc_param)
         return ret;
 
     /* child */
-    ret = INLINE_SYSCALL(dup2, 2, proc_param->parent->process.stream_in,
-                         PROC_INIT_FD);
+    ret = INLINE_SYSCALL(dup2, 2, proc_param->parent->process.stream, PROC_INIT_FD);
     if (IS_ERR(ret))
         goto failed;
 
@@ -320,7 +311,7 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args)
     /* step 4: send parameters over the process handle */
 
     ret = INLINE_SYSCALL(write, 3,
-                         child_handle->process.stream_out,
+                         child_handle->process.stream,
                          proc_args,
                          sizeof(struct proc_args) + datasz);
 
@@ -446,8 +437,7 @@ static int64_t proc_read (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (offset)
         return -PAL_ERROR_INVAL;
 
-    int64_t bytes = INLINE_SYSCALL(read, 3, handle->process.stream_in, buffer,
-                                   count);
+    int64_t bytes = INLINE_SYSCALL(read, 3, handle->process.stream, buffer, count);
 
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
@@ -468,13 +458,12 @@ static int64_t proc_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     if (offset)
         return -PAL_ERROR_INVAL;
 
-    int64_t bytes = INLINE_SYSCALL(write, 3, handle->process.stream_out, buffer,
-                                   count);
+    int64_t bytes = INLINE_SYSCALL(write, 3, handle->process.stream, buffer, count);
 
     if (IS_ERR(bytes))
         switch(ERRNO(bytes)) {
             case EWOULDBLOCK:
-                HANDLE_HDR(handle)->flags &= ~WRITABLE(1);
+                HANDLE_HDR(handle)->flags &= ~WRITABLE(0);
                 return -PAL_ERROR_TRYAGAIN;
             case EINTR:
                 return -PAL_ERROR_INTERRUPTED;
@@ -484,23 +473,18 @@ static int64_t proc_write (PAL_HANDLE handle, uint64_t offset, uint64_t count,
 
     assert(!IS_ERR(bytes));
     if ((size_t)bytes == count)
-        HANDLE_HDR(handle)->flags |= WRITABLE(1);
+        HANDLE_HDR(handle)->flags |= WRITABLE(0);
     else
-        HANDLE_HDR(handle)->flags &= ~WRITABLE(1);
+        HANDLE_HDR(handle)->flags &= ~WRITABLE(0);
 
     return bytes;
 }
 
 static int proc_close (PAL_HANDLE handle)
 {
-    if (handle->process.stream_in != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (handle->process.stream_out != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
+    if (handle->process.stream != PAL_IDX_POISON) {
+        INLINE_SYSCALL(close, 1, handle->process.stream);
+        handle->process.stream = PAL_IDX_POISON;
     }
 
     if (handle->process.cargo != PAL_IDX_POISON) {
@@ -528,17 +512,8 @@ static int proc_delete (PAL_HANDLE handle, int access)
             return -PAL_ERROR_INVAL;
     }
 
-    if (access != PAL_DELETE_WR &&
-        handle->process.stream_in != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_in);
-        handle->process.stream_in = PAL_IDX_POISON;
-    }
-
-    if (access != PAL_DELETE_RD &&
-        handle->process.stream_out != PAL_IDX_POISON) {
-        INLINE_SYSCALL(close, 1, handle->process.stream_out);
-        handle->process.stream_out = PAL_IDX_POISON;
-    }
+    if (handle->process.stream != PAL_IDX_POISON)
+        INLINE_SYSCALL(shutdown, 2, handle->process.stream, shutdown);
 
     if (handle->process.cargo != PAL_IDX_POISON)
         INLINE_SYSCALL(shutdown, 2, handle->process.cargo, shutdown);
@@ -554,18 +529,18 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
     int ret, val;
 
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
-    ret = INLINE_SYSCALL(ioctl, 3, handle->process.stream_in, FIONREAD, &val);
+    ret = INLINE_SYSCALL(ioctl, 3, handle->process.stream, FIONREAD, &val);
     if (IS_ERR(ret))
         return unix_to_pal_error(ERRNO(ret));
 
     attr->handle_type  = pal_type_process;
     attr->nonblocking  = handle->process.nonblocking;
-    attr->disconnected = HANDLE_HDR(handle)->flags & (ERROR(0)|ERROR(1));
+    attr->disconnected = HANDLE_HDR(handle)->flags & ERROR(0);
     attr->readable     = !!val;
-    attr->writable     = HANDLE_HDR(handle)->flags & WRITABLE(1);
+    attr->writable     = HANDLE_HDR(handle)->flags & WRITABLE(0);
     attr->runnable     = PAL_FALSE;
     attr->pending_size = val;
 
@@ -574,12 +549,12 @@ static int proc_attrquerybyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 
 static int proc_attrsetbyhdl (PAL_HANDLE handle, PAL_STREAM_ATTR * attr)
 {
-    if (handle->process.stream_in == PAL_IDX_POISON)
+    if (handle->process.stream == PAL_IDX_POISON)
         return -PAL_ERROR_BADHANDLE;
 
     int ret;
     if (attr->nonblocking != handle->process.nonblocking) {
-        ret = INLINE_SYSCALL(fcntl, 3, handle->process.stream_in, F_SETFL,
+        ret = INLINE_SYSCALL(fcntl, 3, handle->process.stream, F_SETFL,
                              handle->process.nonblocking ? O_NONBLOCK : 0);
 
         if (IS_ERR(ret))

+ 1 - 1
Pal/src/host/Linux/db_streams.c

@@ -279,7 +279,7 @@ int _DkSendHandle(PAL_HANDLE hdl, PAL_HANDLE cargo) {
     int fds[MAX_FDS];
     int nfds = 0;
     for (int i = 0; i < MAX_FDS; i++)
-        if (HANDLE_HDR(cargo)->flags & (RFD(i) | WFD(1))) {
+        if (HANDLE_HDR(cargo)->flags & (RFD(i) | WFD(i))) {
             hdl_hdr.fds |= 1U << i;
             fds[nfds++] = cargo->generic.fds[i];
         }

+ 1 - 1
Pal/src/host/Linux/pal_host.h

@@ -135,7 +135,7 @@ typedef struct pal_handle
         } sock;
 
         struct {
-            PAL_IDX stream_in, stream_out;
+            PAL_IDX stream;
             PAL_IDX cargo;
             PAL_IDX pid;
             PAL_BOL nonblocking;