Browse Source

[Pal/Linux-SGX] Propagate exact error code from OCALL

Before, on many execution paths after failed OCALL, the returned
PAL error was hardcoded. This patch removes these hardcoded errors
and propagates the original error code from OCALL.
Isaku Yamahata 5 years ago
parent
commit
144dee3d6b

+ 3 - 3
Pal/src/host/Linux-SGX/db_files.c

@@ -76,7 +76,7 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri,
                 "This file is not trusted or allowed.\n", hdl->file.realpath,
                 PAL_STRERROR(-ret));
         free(hdl);
-        return -PAL_ERROR_DENIED;
+        return ret;
     }
 
     hdl->file.stubs = (PAL_PTR) stubs;
@@ -114,7 +114,7 @@ static int64_t file_read (PAL_HANDLE handle, uint64_t offset, uint64_t count,
     ret = ocall_map_untrusted(handle->file.fd, map_start,
                               map_end - map_start, PROT_READ, &umem);
     if (IS_ERR(ret))
-        return -PAL_ERROR_DENIED;
+        return unix_to_pal_error(ERRNO(ret));
 
     if (stubs) {
         ret = copy_and_verify_trusted_file(handle->file.realpath, umem,
@@ -145,7 +145,7 @@ static int64_t file_write(PAL_HANDLE handle, uint64_t offset, uint64_t count,
     ret = ocall_map_untrusted(handle->file.fd, map_start,
                               map_end - map_start, PROT_WRITE, &umem);
     if (IS_ERR(ret))
-        return -PAL_ERROR_DENIED;
+        return unix_to_pal_error(ERRNO(ret));
 
     if (offset + count > handle->file.total) {
         ocall_ftruncate(handle->file.fd, offset + count);

+ 2 - 2
Pal/src/host/Linux-SGX/db_pipes.c

@@ -76,7 +76,7 @@ static int pipe_listen (PAL_HANDLE * handle, PAL_NUM pipeid, int options)
                             (struct sockaddr *) &addr, &addrlen,
                             &sock_options);
     if (IS_ERR(ret))
-        return -PAL_ERROR_DENIED;
+        return unix_to_pal_error(ERRNO(ret));
 
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipe));
     SET_HANDLE_TYPE(hdl, pipesrv);
@@ -149,7 +149,7 @@ static int pipe_private (PAL_HANDLE * handle, int options)
 
     ret = ocall_socketpair(AF_UNIX, type, 0, fds);
     if (IS_ERR(ret))
-        return -PAL_ERROR_DENIED;
+        return unix_to_pal_error(ERRNO(ret));
 
     PAL_HANDLE hdl = malloc(HANDLE_SIZE(pipeprv));
     SET_HANDLE_TYPE(hdl, pipeprv);

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

@@ -356,7 +356,7 @@ static int tcp_listen (PAL_HANDLE * handle, char * uri, int options)
                             bind_addr, &bind_addrlen,
                             &sock_options);
     if (IS_ERR(ret))
-        return -PAL_ERROR_DENIED;
+        return unix_to_pal_error(ERRNO(ret));
 
     *handle = socket_create_handle(pal_type_tcpsrv, ret, options,
                                    bind_addr, bind_addrlen, NULL, 0,

+ 14 - 13
Pal/src/host/Linux-SGX/db_streams.c

@@ -296,7 +296,7 @@ int _DkSendHandle (PAL_HANDLE hdl, PAL_HANDLE cargo)
                              fds, nfds);
 
     free(hdl_data);
-    return IS_ERR(ret) ? -PAL_ERROR_DENIED : 0;
+    return IS_ERR(ret) ? unix_to_pal_error(ERRNO(ret)) : 0;
 }
 
 /* _DkRecvHandle for internal use. Receive and return a PAL_HANDLE over the
@@ -321,23 +321,24 @@ int _DkReceiveHandle(PAL_HANDLE hdl, PAL_HANDLE * cargo)
         return unix_to_pal_error(ERRNO(ret));
     if (ret < sizeof(struct hdl_header)) {
         /*
-         * This code block is just in case to cover all the possibility.
+         * This code block is just in case to cover all the possibilities
+         * to shield Iago attack.
+         * We know that the file descriptor is an unix domain socket with
+         * blocking mode and that the sender, _DkSendHandle() above, sends the
+         * header with single sendto syscall by ocall_sock_send() which
+         * transfers a message atomically.
          *
-         * read size == 0: return error to try again:
-         *                 This case won't happen because the file
-         *                 descriptor is Unix domain socket in blocking mode.
-         *                 It is actually EINTR.
+         * read size == 0: return error for the caller to try again.
+         *                 It should result in EINTR.
          *
-         * read size > 0: return partial read size and expect the caller
-         *                to handle it.
-         *                Actually this case won't happen because
-         *                This PAL API is used only for UNIX domain socket
-         *                and, the sender, _DkSendHandle, sends
-         *                struct hdl_header with single sendmsg() system call.
+         * read size > 0: return error for the caller to give up this file
+         *                descriptor.
+         *                If the header can't be send atomically for some
+         *                reason, the sender should get EMSGSIZE.
          */
         if (!ret)
             return -PAL_ERROR_TRYAGAIN;
-        return ret;
+        return -PAL_ERROR_DENIED;
     }
 
     // initialize variables to get body

+ 7 - 17
Pal/src/host/Linux-SGX/sgx_enclave.c

@@ -50,7 +50,7 @@ static int sgx_ocall_alloc_untrusted(void * pms)
                                    PROT_READ|PROT_WRITE,
                                    MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
     if (IS_ERR_P(addr))
-        return -ENOMEM;
+        return -ERRNO_P(addr);
 
     ms->ms_mem = addr;
     return 0;
@@ -66,7 +66,7 @@ static int sgx_ocall_map_untrusted(void * pms)
                                    MAP_FILE|MAP_SHARED,
                                    ms->ms_fd, ms->ms_offset);
     if (IS_ERR_P(addr))
-        return -ENOMEM;
+        return -ERRNO_P(addr);
 
     ms->ms_mem = addr;
     return 0;
@@ -282,10 +282,8 @@ static int sgx_ocall_sock_listen(void * pms)
     ret = INLINE_SYSCALL(socket, 3, ms->ms_domain,
                          ms->ms_type|SOCK_CLOEXEC,
                          ms->ms_protocol);
-    if (IS_ERR(ret)) {
-        ret = -EPERM;
+    if (IS_ERR(ret))
         goto err;
-    }
 
     fd = ret;
     if (ms->ms_addr->sa_family == AF_INET6) {
@@ -305,19 +303,15 @@ static int sgx_ocall_sock_listen(void * pms)
     if (ms->ms_addr) {
         socklen_t addrlen;
         ret = INLINE_SYSCALL(getsockname, 3, fd, ms->ms_addr, &addrlen);
-        if (IS_ERR(ret)) {
-            ret = -EPERM;
+        if (IS_ERR(ret))
             goto err_fd;
-        }
         ms->ms_addrlen = addrlen;
     }
 
     if (ms->ms_type & SOCK_STREAM) {
         ret = INLINE_SYSCALL(listen, 2, fd, DEFAULT_BACKLOG);
-        if (IS_ERR(ret)) {
-            ret = -EPERM;
+        if (IS_ERR(ret))
             goto err_fd;
-        }
     }
 
     ret = sock_getopt(fd, &ms->ms_sockopt);
@@ -367,10 +361,8 @@ static int sgx_ocall_sock_connect(void * pms)
     ret = INLINE_SYSCALL(socket, 3, ms->ms_domain,
                          ms->ms_type|SOCK_CLOEXEC,
                          ms->ms_protocol);
-    if (IS_ERR(ret)) {
-        ret = -EPERM;
+    if (IS_ERR(ret))
         goto err;
-    }
 
     fd = ret;
     if (ms->ms_addr->sa_family == AF_INET6) {
@@ -403,10 +395,8 @@ static int sgx_ocall_sock_connect(void * pms)
         socklen_t addrlen;
         ret = INLINE_SYSCALL(getsockname, 3, fd, ms->ms_bind_addr,
                              &addrlen);
-        if (IS_ERR(ret)) {
-            ret = -EPERM;
+        if (IS_ERR(ret))
             goto err_fd;
-        }
         ms->ms_bind_addrlen = addrlen;
     }
 

+ 2 - 6
Pal/src/host/Linux-SGX/sgx_process.c

@@ -61,10 +61,8 @@ int sgx_create_process (const char * uri, int nargs, const char ** args,
     if (IS_ERR((ret = INLINE_SYSCALL(pipe, 1, &fds[0]))) ||
         IS_ERR((ret = INLINE_SYSCALL(pipe, 1, &fds[2]))) ||
         IS_ERR((ret = INLINE_SYSCALL(socketpair, 4, AF_UNIX, SOCK_STREAM,
-                                     0, &fds[4])))) {
-        ret = -EPERM;
+                                     0, &fds[4]))))
         goto out;
-    }
 
     int proc_fds[2][3] = {
         { fds[0], fds[3], fds[4] },
@@ -78,10 +76,8 @@ int sgx_create_process (const char * uri, int nargs, const char ** args,
 
     ret = ARCH_VFORK();
 
-    if (IS_ERR(ret)) {
-        ret = -EPERM;
+    if (IS_ERR(ret))
         goto out;
-    }
 
     if (!ret) {
         for (int i = 0 ; i < 3 ; i++)