From 7e20a8044c75082fae0cdfec92fcdcafbe8d88f5 Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Wed, 8 Apr 2020 17:45:17 -0700 Subject: [PATCH] [LibOS,Pal] Replace 32-bit pipeid with 256-bit pipe name Previously, Graphene used the notation "pipe:" to emulate pipes, socketpairs, and UNIX domain sockets. In particular, pipes and socketpairs received random integer IDs, and sockets received deterministic integer IDs. However, 32-bit randomly generated IDs may collide quite often. Since pipe IDs/names should *not* repeat (otherwise e.g. derived crypto keys will be reused), this commit changes pipe IDs (pipeid) from uint32_t to char[96], and pipe IDs (names) become 256-bit random sequences. --- LibOS/shim/include/shim_handle.h | 13 +-- LibOS/shim/include/shim_internal.h | 6 -- LibOS/shim/include/shim_types.h | 3 + LibOS/shim/include/shim_utils.h | 3 +- LibOS/shim/src/shim_init.c | 125 ++++++++++++++++------------- LibOS/shim/src/sys/shim_pipe.c | 47 ++++++----- LibOS/shim/src/sys/shim_socket.c | 71 ++++++++-------- Pal/include/lib/hex.h | 2 +- Pal/include/pal/pal.h | 9 ++- Pal/src/host/Linux-SGX/db_pipes.c | 51 ++++++------ Pal/src/host/Linux-SGX/pal_host.h | 6 +- Pal/src/host/Linux/db_pipes.c | 57 ++++++------- Pal/src/host/Linux/pal_host.h | 6 +- Pal/src/host/Linux/pal_linux.h | 2 - Pal/src/host/Linux/pal_security.h | 3 - Pal/src/host/Skeleton/db_pipes.c | 28 ++----- 16 files changed, 213 insertions(+), 219 deletions(-) diff --git a/LibOS/shim/include/shim_handle.h b/LibOS/shim/include/shim_handle.h index cad27283..a1fa5a15 100644 --- a/LibOS/shim/include/shim_handle.h +++ b/LibOS/shim/include/shim_handle.h @@ -127,11 +127,7 @@ struct shim_dev_handle { }; struct shim_pipe_handle { -#if USE_SIMPLE_PIPE == 1 - struct shim_handle* pair; -#else - IDTYPE pipeid; -#endif + char name[PIPE_URI_SIZE]; }; #define SOCK_STREAM 1 @@ -163,10 +159,6 @@ enum shim_sock_state { SOCK_SHUTDOWN, }; -struct shim_unix_data { - unsigned int pipeid; -}; - struct shim_sock_handle { int domain; int sock_type; @@ -190,8 +182,7 @@ struct shim_sock_handle { // UNIX addr struct addr_unix { struct shim_dentry* dentry; - unsigned int pipeid; - struct shim_unix_data* data; + char name[PIPE_URI_SIZE]; } un; } addr; diff --git a/LibOS/shim/include/shim_internal.h b/LibOS/shim/include/shim_internal.h index 7d146862..d63a6d68 100644 --- a/LibOS/shim/include/shim_internal.h +++ b/LibOS/shim/include/shim_internal.h @@ -827,10 +827,4 @@ static_always_inline void * current_stack(void) # error "Unsupported architecture" #endif /* __x86_64__ */ -static inline IDTYPE hashtype_to_idtype(HASHTYPE hash) { - static_assert(sizeof(HASHTYPE) == 8, "Unsupported HASHTYPE size"); - static_assert(sizeof(IDTYPE) == 4, "Unsupported IDTYPE size"); - return ((IDTYPE)hash) ^ ((IDTYPE)(hash >> 32)); -} - #endif /* _PAL_INTERNAL_H_ */ diff --git a/LibOS/shim/include/shim_types.h b/LibOS/shim/include/shim_types.h index 0ab7a531..7764fcb2 100644 --- a/LibOS/shim/include/shim_types.h +++ b/LibOS/shim/include/shim_types.h @@ -515,4 +515,7 @@ struct shim_qstr { struct shim_str * oflow; }; +/* maximum length of pipe/FIFO name (should be less than Linux sockaddr_un.sun_path = 108) */ +#define PIPE_URI_SIZE 96 + #endif /* _SHIM_TYPES_H_ */ diff --git a/LibOS/shim/include/shim_utils.h b/LibOS/shim/include/shim_utils.h index e1177022..7e607365 100644 --- a/LibOS/shim/include/shim_utils.h +++ b/LibOS/shim/include/shim_utils.h @@ -206,8 +206,7 @@ void append_r_debug(const char* uri, void* addr, void* dyn_addr); void clean_link_map_list(void); /* create unique files/pipes */ -#define PIPE_URI_SIZE 40 -int create_pipe(IDTYPE* pipeid, char* uri, size_t size, PAL_HANDLE* hdl, struct shim_qstr* qstr, +int create_pipe(char* name, char* uri, size_t size, PAL_HANDLE* hdl, struct shim_qstr* qstr, bool use_vmid_for_name); int create_dir(const char* prefix, char* path, size_t size, struct shim_handle** hdl); int create_file(const char* prefix, char* path, size_t size, struct shim_handle** hdl); diff --git a/LibOS/shim/src/shim_init.c b/LibOS/shim/src/shim_init.c index c05fb698..9c32502f 100644 --- a/LibOS/shim/src/shim_init.c +++ b/LibOS/shim/src/shim_init.c @@ -33,9 +33,10 @@ #include #include -#include -#include -#include +#include "hex.h" +#include "pal.h" +#include "pal_debug.h" +#include "pal_error.h" #include #include @@ -807,69 +808,85 @@ static int create_unique (int (*mkname) (char *, size_t, void *), } } -static int name_pipe_rand (char * uri, size_t size, void * id) -{ - IDTYPE pipeid; - size_t len; - int ret = DkRandomBitsRead(&pipeid, sizeof(pipeid)); +static int get_256b_random_hex_string(char* buf, size_t size) { + char random[32]; /* 256-bit random value, sufficiently crypto secure */ + + if (size < sizeof(random) * 2 + 1) + return -ENOMEM; + + int ret = DkRandomBitsRead(&random, sizeof(random)); if (ret < 0) return -convert_pal_errno(-ret); - debug("creating pipe: " URI_PREFIX_PIPE_SRV "%u\n", pipeid); - if ((len = snprintf(uri, size, URI_PREFIX_PIPE_SRV "%u", pipeid)) >= size) - return -ERANGE; - *((IDTYPE *)id) = pipeid; - return len; -} -static int name_pipe_vmid (char * uri, size_t size, void * id) -{ - IDTYPE pipeid = cur_process.vmid; - size_t len; - debug("creating pipe: " URI_PREFIX_PIPE_SRV "%u\n", pipeid); - if ((len = snprintf(uri, size, URI_PREFIX_PIPE_SRV "%u", pipeid)) >= size) - return -ERANGE; - *((IDTYPE *)id) = pipeid; - return len; -} - -static int open_pipe (const char * uri, void * obj) -{ - PAL_HANDLE pipe = DkStreamOpen(uri, 0, 0, 0, 0); - if (!pipe) - return PAL_NATIVE_ERRNO == PAL_ERROR_STREAMEXIST ? 1 : - -PAL_ERRNO; - if (obj) - *((PAL_HANDLE *) obj) = pipe; - else - DkObjectClose(pipe); + BYTES2HEXSTR(random, buf, size); return 0; } -static int pipe_addr (char * uri, size_t size, const void * id, - struct shim_qstr * qstr) -{ - IDTYPE pipeid = *((IDTYPE *) id); - size_t len; - if ((len = snprintf(uri, size, URI_PREFIX_PIPE "%u", pipeid)) == size) +static int name_pipe_rand(char* uri, size_t uri_size, void* name) { + char pipename[PIPE_URI_SIZE]; + + int ret = get_256b_random_hex_string(pipename, sizeof(pipename)); + if (ret < 0) + return ret; + + debug("creating pipe: " URI_PREFIX_PIPE_SRV "%s\n", pipename); + size_t len = snprintf(uri, uri_size, URI_PREFIX_PIPE_SRV "%s", pipename); + if (len >= uri_size) return -ERANGE; + + memcpy(name, pipename, sizeof(pipename)); + return len; +} + +static int name_pipe_vmid(char* uri, size_t uri_size, void* name) { + char pipename[PIPE_URI_SIZE]; + + size_t len = snprintf(pipename, sizeof(pipename), "%u", cur_process.vmid); + if (len >= sizeof(pipename)) + return -ERANGE; + + debug("creating pipe: " URI_PREFIX_PIPE_SRV "%s\n", pipename); + len = snprintf(uri, uri_size, URI_PREFIX_PIPE_SRV "%s", pipename); + if (len >= uri_size) + return -ERANGE; + + memcpy(name, pipename, sizeof(pipename)); + return len; +} + +static int open_pipe(const char* uri, void* obj) { + assert(obj); + + PAL_HANDLE pipe = DkStreamOpen(uri, 0, 0, 0, 0); + if (!pipe) + return PAL_NATIVE_ERRNO == PAL_ERROR_STREAMEXIST ? 1 : -PAL_ERRNO; + + PAL_HANDLE* pal_hdl = (PAL_HANDLE*)obj; + *pal_hdl = pipe; + return 0; +} + +static int pipe_addr(char* uri, size_t size, const void* name, struct shim_qstr* qstr) { + char* pipename = (char*)name; + + size_t len = snprintf(uri, size, URI_PREFIX_PIPE "%s", pipename); + if (len >= size) + return -ERANGE; + if (qstr) qstrsetstr(qstr, uri, len); return len; } -int create_pipe (IDTYPE * id, char * uri, size_t size, PAL_HANDLE * hdl, - struct shim_qstr * qstr, bool use_vmid_for_name) -{ - IDTYPE pipeid; - int ret; - if (use_vmid_for_name) - ret = create_unique(&name_pipe_vmid, &open_pipe, &pipe_addr, - uri, size, &pipeid, hdl, qstr); - else - ret = create_unique(&name_pipe_rand, &open_pipe, &pipe_addr, - uri, size, &pipeid, hdl, qstr); - if (ret > 0 && id) - *id = pipeid; +int create_pipe(char* name, char* uri, size_t size, PAL_HANDLE* hdl, struct shim_qstr* qstr, + bool use_vmid_for_name) { + char pipename[PIPE_URI_SIZE]; + + int ret = create_unique(use_vmid_for_name ? &name_pipe_vmid : &name_pipe_rand, &open_pipe, + &pipe_addr, uri, size, &pipename, hdl, qstr); + if (ret > 0 && name) { + memcpy(name, pipename, sizeof(pipename)); + } return ret; } diff --git a/LibOS/shim/src/sys/shim_pipe.c b/LibOS/shim/src/sys/shim_pipe.c index db92706d..00a54c7b 100644 --- a/LibOS/shim/src/sys/shim_pipe.c +++ b/LibOS/shim/src/sys/shim_pipe.c @@ -30,13 +30,16 @@ #include #include -int create_pipes(IDTYPE* pipeid, PAL_HANDLE* srv, PAL_HANDLE* cli, struct shim_qstr* qstr, - int flags) { - PAL_HANDLE hdl0 = NULL, hdl1 = NULL, hdl2 = NULL; +static int create_pipes(PAL_HANDLE* srv, PAL_HANDLE* cli, int flags, char* name, + struct shim_qstr* qstr) { int ret = 0; char uri[PIPE_URI_SIZE]; - if ((ret = create_pipe(pipeid, uri, PIPE_URI_SIZE, &hdl0, qstr, + PAL_HANDLE hdl0 = NULL; /* server pipe (temporary, waits for connect from hdl2) */ + PAL_HANDLE hdl1 = NULL; /* one pipe end (accepted connect from hdl2) */ + PAL_HANDLE hdl2 = NULL; /* other pipe end (connects to hdl0 and talks to hdl1) */ + + if ((ret = create_pipe(name, uri, PIPE_URI_SIZE, &hdl0, qstr, /*use_vmid_for_name=*/false)) < 0) { debug("pipe creation failure\n"); return ret; @@ -45,25 +48,26 @@ int create_pipes(IDTYPE* pipeid, PAL_HANDLE* srv, PAL_HANDLE* cli, struct shim_q if (!(hdl2 = DkStreamOpen(uri, 0, 0, 0, flags & O_NONBLOCK))) { ret = -PAL_ERRNO; debug("pipe connection failure\n"); - goto err; + goto out; } if (!(hdl1 = DkStreamWaitForClient(hdl0))) { ret = -PAL_ERRNO; debug("pipe acception failure\n"); - goto err; + goto out; } - DkStreamDelete(hdl0, 0); - DkObjectClose(hdl0); *srv = hdl1; *cli = hdl2; - return 0; -err: - if (hdl1) - DkObjectClose(hdl1); - if (hdl2) - DkObjectClose(hdl2); + ret = 0; + +out: + if (ret < 0) { + if (hdl1) + DkObjectClose(hdl1); + if (hdl2) + DkObjectClose(hdl2); + } DkStreamDelete(hdl0, 0); DkObjectClose(hdl0); return ret; @@ -93,11 +97,13 @@ int shim_do_pipe2(int* filedes, int flags) { hdl2->flags = O_WRONLY; hdl2->acc_mode = MAY_WRITE; - if ((ret = create_pipes(&hdl1->info.pipe.pipeid, &hdl1->pal_handle, &hdl2->pal_handle, - &hdl1->uri, flags)) < 0) + ret = create_pipes(&hdl1->pal_handle, &hdl2->pal_handle, flags, hdl1->info.pipe.name, + &hdl1->uri); + if (ret < 0) goto out; - qstrcopy(&hdl2->uri, &hdl2->uri); + memcpy(hdl2->info.pipe.name, hdl1->info.pipe.name, sizeof(hdl2->info.pipe.name)); + qstrcopy(&hdl2->uri, &hdl1->uri); flags = flags & O_CLOEXEC ? FD_CLOEXEC : 0; int vfd1 = set_new_fd_handle(hdl1, flags, NULL); @@ -172,11 +178,12 @@ int shim_do_socketpair(int domain, int type, int protocol, int* sv) { sock2->protocol = protocol; sock2->sock_state = SOCK_CONNECTED; - if ((ret = create_pipes(&sock1->addr.un.pipeid, &hdl1->pal_handle, &hdl2->pal_handle, - &hdl1->uri, type & SOCK_NONBLOCK ? O_NONBLOCK : 0)) < 0) + ret = create_pipes(&hdl1->pal_handle, &hdl2->pal_handle, type & SOCK_NONBLOCK ? O_NONBLOCK : 0, + sock1->addr.un.name, &hdl1->uri); + if (ret < 0) goto out; - sock2->addr.un.pipeid = sock1->addr.un.pipeid; + memcpy(sock2->addr.un.name, sock1->addr.un.name, sizeof(sock2->addr.un.name)); qstrcopy(&hdl2->uri, &hdl1->uri); int flags = type & SOCK_CLOEXEC ? FD_CLOEXEC : 0; diff --git a/LibOS/shim/src/sys/shim_socket.c b/LibOS/shim/src/sys/shim_socket.c index 9dfd5b44..50082702 100644 --- a/LibOS/shim/src/sys/shim_socket.c +++ b/LibOS/shim/src/sys/shim_socket.c @@ -27,8 +27,11 @@ #include #include #include -#include -#include + +#include "hex.h" +#include "pal.h" +#include "pal_error.h" + #include #include #include @@ -144,7 +147,7 @@ err: return ret; } -static int unix_create_uri(char* uri, int count, enum shim_sock_state state, unsigned int pipeid) { +static int unix_create_uri(char* uri, int count, enum shim_sock_state state, char* name) { int bytes = 0; switch (state) { @@ -156,11 +159,11 @@ static int unix_create_uri(char* uri, int count, enum shim_sock_state state, uns case SOCK_BOUND: case SOCK_LISTENED: case SOCK_ACCEPTED: - bytes = snprintf(uri, count, URI_PREFIX_PIPE_SRV "%u", pipeid); + bytes = snprintf(uri, count, URI_PREFIX_PIPE_SRV "%s", name); break; case SOCK_CONNECTED: - bytes = snprintf(uri, count, URI_PREFIX_PIPE "%u", pipeid); + bytes = snprintf(uri, count, URI_PREFIX_PIPE "%s", name); break; default: @@ -410,7 +413,7 @@ static int create_socket_uri(struct shim_handle* hdl) { if (sock->domain == AF_UNIX) { char uri_buf[32]; - int bytes = unix_create_uri(uri_buf, 32, sock->sock_state, sock->addr.un.pipeid); + int bytes = unix_create_uri(uri_buf, 32, sock->sock_state, sock->addr.un.name); if (bytes < 0) return bytes; @@ -447,6 +450,18 @@ static bool __socket_is_ipv6_v6only(struct shim_handle* hdl) { return false; } +static int hash_to_hex_string(HASHTYPE hash, char* buf, size_t size) { + static_assert(sizeof(hash) == 8, "Unsupported HASHTYPE size"); + char hashbytes[8]; + + if (size < sizeof(hashbytes) * 2 + 1) + return -ENOMEM; + + memcpy(hashbytes, &hash, sizeof(hash)); + BYTES2HEXSTR(hashbytes, buf, size); + return 0; +} + int shim_do_bind(int sockfd, struct sockaddr* addr, socklen_t addrlen) { if (!addr || test_user_memory(addr, addrlen, false)) @@ -492,13 +507,14 @@ int shim_do_bind(int sockfd, struct sockaddr* addr, socklen_t addrlen) { goto out; } - struct shim_unix_data* data = malloc(sizeof(struct shim_unix_data)); + /* instead of user-specified sun_path of UNIX socket, use its deterministic hash as name + * (deterministic so that independent parent and child connect to the same socket) */ + ret = hash_to_hex_string(dent->rel_path.hash, sock->addr.un.name, + sizeof(sock->addr.un.name)); + if (ret < 0) + goto out; - data->pipeid = hashtype_to_idtype(dent->rel_path.hash); - sock->addr.un.pipeid = data->pipeid; - sock->addr.un.data = data; sock->addr.un.dentry = dent; - } else if (sock->domain == AF_INET || sock->domain == AF_INET6) { if ((ret = inet_check_addr(sock->domain, addr, addrlen)) < 0) goto out; @@ -531,7 +547,7 @@ int shim_do_bind(int sockfd, struct sockaddr* addr, socklen_t addrlen) { dent->state ^= DENTRY_NEGATIVE; dent->state |= DENTRY_VALID | DENTRY_RECENTLY; dent->fs = &socket_builtin_fs; - dent->data = sock->addr.un.data; + dent->data = NULL; } if (sock->domain == AF_INET || sock->domain == AF_INET6) { @@ -561,11 +577,6 @@ out: if (sock->domain == AF_UNIX) { if (sock->addr.un.dentry) put_dentry(sock->addr.un.dentry); - - if (sock->addr.un.data) { - free(sock->addr.un.data); - sock->addr.un.data = NULL; - } } } @@ -754,18 +765,19 @@ int shim_do_connect(int sockfd, struct sockaddr* addr, int addrlen) { goto out; } - struct shim_unix_data* data = dent->data; - - if (!(dent->state & DENTRY_VALID) || dent->state & DENTRY_NEGATIVE) { - data = malloc(sizeof(struct shim_unix_data)); - data->pipeid = hashtype_to_idtype(dent->rel_path.hash); - } else if (dent->fs != &socket_builtin_fs) { + if (dent->state & DENTRY_VALID && !(dent->state & DENTRY_NEGATIVE) && + dent->fs != &socket_builtin_fs) { ret = -ECONNREFUSED; goto out; } - sock->addr.un.pipeid = data->pipeid; - sock->addr.un.data = data; + /* instead of user-specified sun_path of UNIX socket, use its deterministic hash as name + * (deterministic so that independent parent and child connect to the same socket) */ + ret = hash_to_hex_string(dent->rel_path.hash, sock->addr.un.name, + sizeof(sock->addr.un.name)); + if (ret < 0) + goto out; + sock->addr.un.dentry = dent; get_dentry(dent); } @@ -805,7 +817,7 @@ int shim_do_connect(int sockfd, struct sockaddr* addr, int addrlen) { dent->state ^= DENTRY_NEGATIVE; dent->state |= DENTRY_VALID | DENTRY_RECENTLY; dent->fs = &socket_builtin_fs; - dent->data = sock->addr.un.data; + dent->data = NULL; unlock(&dent->lock); } @@ -837,11 +849,6 @@ out: if (sock->domain == AF_UNIX) { if (sock->addr.un.dentry) put_dentry(sock->addr.un.dentry); - - if (sock->addr.un.data) { - free(sock->addr.un.data); - sock->addr.un.data = NULL; - } } } @@ -924,7 +931,7 @@ int __do_accept(struct shim_handle* hdl, int flags, struct sockaddr* addr, sockl cli_sock->sock_state = SOCK_ACCEPTED; if (sock->domain == AF_UNIX) { - cli_sock->addr.un.pipeid = sock->addr.un.pipeid; + memcpy(cli_sock->addr.un.name, sock->addr.un.name, sizeof(cli_sock->addr.un.name)); if (sock->addr.un.dentry) { get_dentry(sock->addr.un.dentry); cli_sock->addr.un.dentry = sock->addr.un.dentry; diff --git a/Pal/include/lib/hex.h b/Pal/include/lib/hex.h index 6b3fb445..62f50bcd 100644 --- a/Pal/include/lib/hex.h +++ b/Pal/include/lib/hex.h @@ -36,7 +36,7 @@ static inline __attribute__((always_inline)) char * __bytes2hexstr(void * hex, size_t size, char *str, size_t len) { - static char * ch = "0123456789abcdef"; + static const char* ch = "0123456789abcdef"; __UNUSED(len); assert(len >= size * 2 + 1); diff --git a/Pal/include/pal/pal.h b/Pal/include/pal/pal.h index 9f6e8f07..7602c7ca 100644 --- a/Pal/include/pal/pal.h +++ b/Pal/include/pal/pal.h @@ -56,6 +56,9 @@ typedef bool PAL_BOL; * since it is 3, across all host kernels. */ #define MAX_FDS 3 +/* maximum length of pipe/FIFO name (should be less than Linux sockaddr_un.sun_path = 108) */ +#define PIPE_NAME_MAX 96 + #ifdef IN_PAL #include typedef struct atomic_int PAL_REF; @@ -516,9 +519,9 @@ enum PAL_OPTION { * * `%file:...`, `dir:...`: Files or directories on the host file system. If #PAL_CREATE_TRY is * given in `create` flags, the file/directory will be created. * * `dev:...`: Open a device as a stream. For example, `dev:tty` represents the standard I/O. - * * `pipe.srv:`, `pipe:`, `pipe:`: Open a byte stream that can be used for RPC between - * processes. Pipes are located by numeric IDs. The server side of a pipe can accept any number - * of connections. If `pipe:` is given as the URI, it will open an anonymous bidirectional pipe. + * * `pipe.srv:`, `pipe:`, `pipe:`: Open a byte stream that can be used for RPC between + * processes. The server side of a pipe can accept any number of connections. If `pipe:` is given + * as the URI (i.e., without a name), it will open an anonymous bidirectional pipe. * * `tcp.srv::`, `tcp::`: Open a TCP socket to listen or connect to * a remote TCP socket. * * `udp.srv::`, `udp::`: Open a UDP socket to listen or connect to diff --git a/Pal/src/host/Linux-SGX/db_pipes.c b/Pal/src/host/Linux-SGX/db_pipes.c index f25362fb..1e96780b 100644 --- a/Pal/src/host/Linux-SGX/db_pipes.c +++ b/Pal/src/host/Linux-SGX/db_pipes.c @@ -38,8 +38,8 @@ typedef __kernel_pid_t pid_t; #include #include -static int pipe_addr(int pipeid, struct sockaddr_un* addr) { - /* use abstract UNIX sockets for pipes, with name format "@/graphene/12345678" */ +static int pipe_addr(const char* name, struct sockaddr_un* addr) { + /* use abstract UNIX sockets for pipes, with name format "@/graphene/" */ addr->sun_family = AF_UNIX; memset(addr->sun_path, 0, sizeof(addr->sun_path)); @@ -48,29 +48,29 @@ static int pipe_addr(int pipeid, struct sockaddr_un* addr) { size_t size = sizeof(addr->sun_path) - 1; /* pipe_prefix already contains a slash at the end, so not needed in the format string */ - int ret = snprintf(str, size, "%s%08x", pal_sec.pipe_prefix, pipeid); + int ret = snprintf(str, size, "%s%s", pal_sec.pipe_prefix, name); return ret >= 0 && (size_t)ret < size ? 0 : -EINVAL; } /*! * \brief Create a listening abstract UNIX socket as preparation for connecting two ends of a pipe. * - * An abstract UNIX socket with name "@/graphene/" is opened for listening. A corresponding + * An abstract UNIX socket with name "@/graphene/" is opened for listening. A corresponding * PAL handle with type `pipesrv` is created. This PAL handle typically serves only as an * intermediate step to connect two ends of the pipe (`pipecli` and `pipe`). As soon as the other * end of the pipe connects to this listening socket, a new accepted socket and the corresponding * PAL handle are created, and this `pipesrv` handle can be closed. * * \param[out] handle PAL handle of type `pipesrv` with abstract UNIX socket opened for listening. - * \param[in] pipeid Integer uniquely identifying the pipe. + * \param[in] name String uniquely identifying the pipe. * \param[in] options May contain PAL_OPTION_NONBLOCK. * \return 0 on success, negative PAL error code otherwise. */ -static int pipe_listen(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { +static int pipe_listen(PAL_HANDLE* handle, const char* name, int options) { int ret; struct sockaddr_un addr; - ret = pipe_addr(pipeid, &addr); + ret = pipe_addr(name, &addr); if (IS_ERR(ret)) return -PAL_ERROR_DENIED; @@ -92,8 +92,8 @@ static int pipe_listen(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { SET_HANDLE_TYPE(hdl, pipesrv); HANDLE_HDR(hdl)->flags |= RFD(0); /* cannot write to a listening socket */ hdl->pipe.fd = ret; - hdl->pipe.pipeid = pipeid; hdl->pipe.nonblocking = options & PAL_OPTION_NONBLOCK ? PAL_TRUE : PAL_FALSE; + memcpy(&hdl->pipe.name.str, name, sizeof(hdl->pipe.name.str)); *handle = hdl; return 0; @@ -133,8 +133,8 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) { SET_HANDLE_TYPE(clnt, pipecli); HANDLE_HDR(clnt)->flags |= RFD(0) | WFD(0); clnt->pipe.fd = ret; + clnt->pipe.name = handle->pipe.name; clnt->pipe.nonblocking = PAL_FALSE; /* FIXME: must set nonblocking based on `handle` value */ - clnt->pipe.pipeid = handle->pipe.pipeid; *client = clnt; return 0; @@ -144,20 +144,20 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) { * \brief Connect to the other end of the pipe and create PAL handle for our end of the pipe. * * This function connects to the other end of the pipe, represented as an abstract UNIX socket - * "@/graphene/" opened for listening. When the connection succeeds, a new `pipe` PAL handle + * "@/graphene/" opened for listening. When the connection succeeds, a new `pipe` PAL handle * is created with the corresponding underlying socket and is returned in `handle`. The other end of * the pipe is typically of type `pipecli`. * * \param[out] handle PAL handle of type `pipe` with abstract UNIX socket connected to another end. - * \param[in] pipeid Integer uniquely identifying the pipe. + * \param[in] name String uniquely identifying the pipe. * \param[in] options May contain PAL_OPTION_NONBLOCK. * \return 0 on success, negative PAL error code otherwise. */ -static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { +static int pipe_connect(PAL_HANDLE* handle, const char* name, int options) { int ret; struct sockaddr_un addr; - ret = pipe_addr(pipeid, &addr); + ret = pipe_addr(name, &addr); if (IS_ERR(ret)) return -PAL_ERROR_DENIED; @@ -180,8 +180,8 @@ static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { SET_HANDLE_TYPE(hdl, pipe); HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(0); hdl->pipe.fd = ret; - hdl->pipe.pipeid = pipeid; hdl->pipe.nonblocking = (options & PAL_OPTION_NONBLOCK) ? PAL_TRUE : PAL_FALSE; + memcpy(&hdl->pipe.name.str, name, sizeof(hdl->pipe.name.str)); *handle = hdl; return 0; @@ -233,17 +233,15 @@ static int pipe_private(PAL_HANDLE* handle, int options) { * ends of an anonymous pipe). * * - `type` is URI_TYPE_PIPE_SRV: create `pipesrv` handle (intermediate listening socket) with - * name in the form of "@/graphene/" where pipeid is - * derived from `uri` via strtol(). Caller is expected to call - * pipe_waitforclient() afterwards. + * name in the form of "@/graphene/". Caller is expected to + * call pipe_waitforclient() afterwards. * * - `type` is URI_TYPE_PIPE: create `pipe` handle (connecting socket) with name in the form of - * "@/graphene/" where pipeid is derived from `uri` via - * strtol(). + * "@/graphene/". * * \param[out] handle Created PAL handle of type `pipeprv`, `pipesrv`, or `pipe`. * \param[in] type Can be URI_TYPE_PIPE or URI_TYPE_PIPE_SRV. - * \param[in] uri Content is either NUL (for anonymous pipe) or an integer denoting pipeid. + * \param[in] uri Content is either NUL (for anonymous pipe) or a string with pipe name. * \param[in] access Not used. * \param[in] share Not used. * \param[in] create Not used. @@ -259,17 +257,14 @@ static int pipe_open(PAL_HANDLE* handle, const char* type, const char* uri, int if (!strcmp_static(type, URI_TYPE_PIPE) && !*uri) return pipe_private(handle, options); - char* endptr; - PAL_NUM pipeid = strtol(uri, &endptr, 10); - - if (*endptr) + if (strlen(uri) + 1 > PIPE_NAME_MAX) return -PAL_ERROR_INVAL; if (!strcmp_static(type, URI_TYPE_PIPE_SRV)) - return pipe_listen(handle, pipeid, options); + return pipe_listen(handle, uri, options); if (!strcmp_static(type, URI_TYPE_PIPE)) - return pipe_connect(handle, pipeid, options); + return pipe_connect(handle, uri, options); return -PAL_ERROR_INVAL; } @@ -487,7 +482,7 @@ static int pipe_attrsetbyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) { /*! * \brief Retrieve full URI of PAL handle. * - * Full URI is composed of the type and pipeid: ":". + * Full URI is composed of the type and pipe name: ":". * * \param[in] handle PAL handle of type `pipeprv`, `pipesrv`, `pipecli`, or `pipe`. * \param[out] buffer User-supplied buffer to write URI to. @@ -524,7 +519,7 @@ static int pipe_getname(PAL_HANDLE handle, char* buffer, size_t count) { buffer += prefix_len + 1; count -= prefix_len + 1; - ret = snprintf(buffer, count, "%lu\n", handle->pipe.pipeid); + ret = snprintf(buffer, count, "%s\n", handle->pipe.name.str); if (buffer[ret - 1] != '\n') { memset(buffer, 0, count); return -PAL_ERROR_OVERFLOW; diff --git a/Pal/src/host/Linux-SGX/pal_host.h b/Pal/src/host/Linux-SGX/pal_host.h index ca040f99..d975c685 100644 --- a/Pal/src/host/Linux-SGX/pal_host.h +++ b/Pal/src/host/Linux-SGX/pal_host.h @@ -71,6 +71,10 @@ struct pal_handle_thread { void * param; }; +typedef struct { + char str[PIPE_NAME_MAX]; +} PAL_PIPE_NAME; + /* RPC streams are encrypted with 256-bit AES keys */ typedef uint8_t PAL_SESSION_KEY[32]; @@ -98,7 +102,7 @@ typedef struct pal_handle struct { PAL_IDX fd; - PAL_NUM pipeid; + PAL_PIPE_NAME name; PAL_BOL nonblocking; } pipe; diff --git a/Pal/src/host/Linux/db_pipes.c b/Pal/src/host/Linux/db_pipes.c index 4e5b8aad..53a65896 100644 --- a/Pal/src/host/Linux/db_pipes.c +++ b/Pal/src/host/Linux/db_pipes.c @@ -40,8 +40,8 @@ typedef __kernel_pid_t pid_t; #include #include -static int pipe_addr(int pipeid, struct sockaddr_un* addr) { - /* use abstract UNIX sockets for pipes, with name format "@/graphene/12345678" */ +static int pipe_addr(const char* name, struct sockaddr_un* addr) { + /* use abstract UNIX sockets for pipes, with name format "@/graphene/" */ addr->sun_family = AF_UNIX; memset(addr->sun_path, 0, sizeof(addr->sun_path)); @@ -50,35 +50,29 @@ static int pipe_addr(int pipeid, struct sockaddr_un* addr) { size_t size = sizeof(addr->sun_path) - 1; /* FIXME: Below naming scheme is slightly different from Linux-SGX, not important though */ - int ret; - if (pal_sec.pipe_prefix_id) { - ret = snprintf(str, size, GRAPHENE_UNIX_PREFIX_FMT "/%08x", - pal_sec.pipe_prefix_id, pipeid); - } else { - ret = snprintf(str, size, "/graphene/%08x", pipeid); - } + int ret = snprintf(str, size, "/graphene/%s", name); return ret >= 0 && (size_t)ret < size ? 0 : -EINVAL; } /*! * \brief Create a listening abstract UNIX socket as preparation for connecting two ends of a pipe. * - * An abstract UNIX socket with name "@/graphene/" is opened for listening. A corresponding + * An abstract UNIX socket with name "@/graphene/" is opened for listening. A corresponding * PAL handle with type `pipesrv` is created. This PAL handle typically serves only as an * intermediate step to connect two ends of the pipe (`pipecli` and `pipe`). As soon as the other * end of the pipe connects to this listening socket, a new accepted socket and the corresponding * PAL handle are created, and this `pipesrv` handle can be closed. * * \param[out] handle PAL handle of type `pipesrv` with abstract UNIX socket opened for listening. - * \param[in] pipeid Integer uniquely identifying the pipe. + * \param[in] name String uniquely identifying the pipe. * \param[in] options May contain PAL_OPTION_NONBLOCK. * \return 0 on success, negative PAL error code otherwise. */ -static int pipe_listen(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { +static int pipe_listen(PAL_HANDLE* handle, const char* name, int options) { int ret; struct sockaddr_un addr; - ret = pipe_addr(pipeid, &addr); + ret = pipe_addr(name, &addr); if (IS_ERR(ret)) return -PAL_ERROR_DENIED; @@ -109,8 +103,8 @@ static int pipe_listen(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { SET_HANDLE_TYPE(hdl, pipesrv); HANDLE_HDR(hdl)->flags |= RFD(0); /* cannot write to a listening socket */ hdl->pipe.fd = fd; - hdl->pipe.pipeid = pipeid; hdl->pipe.nonblocking = options & PAL_OPTION_NONBLOCK ? PAL_TRUE : PAL_FALSE; + memcpy(&hdl->pipe.name.str, name, sizeof(hdl->pipe.name.str)); *handle = hdl; return 0; @@ -149,8 +143,8 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) { SET_HANDLE_TYPE(clnt, pipecli); HANDLE_HDR(clnt)->flags |= RFD(0) | WFD(0); clnt->pipe.fd = newfd; + clnt->pipe.name = handle->pipe.name; clnt->pipe.nonblocking = PAL_FALSE; /* FIXME: must set nonblocking based on `handle` value */ - clnt->pipe.pipeid = handle->pipe.pipeid; *client = clnt; return 0; @@ -160,20 +154,20 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) { * \brief Connect to the other end of the pipe and create PAL handle for our end of the pipe. * * This function connects to the other end of the pipe, represented as an abstract UNIX socket - * "@/graphene/" opened for listening. When the connection succeeds, a new `pipe` PAL handle + * "@/graphene/" opened for listening. When the connection succeeds, a new `pipe` PAL handle * is created with the corresponding underlying socket and is returned in `handle`. The other end of * the pipe is typically of type `pipecli`. * * \param[out] handle PAL handle of type `pipe` with abstract UNIX socket connected to another end. - * \param[in] pipeid Integer uniquely identifying the pipe. + * \param[in] name String uniquely identifying the pipe. * \param[in] options May contain PAL_OPTION_NONBLOCK. * \return 0 on success, negative PAL error code otherwise. */ -static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { +static int pipe_connect(PAL_HANDLE* handle, const char* name, int options) { int ret; struct sockaddr_un addr; - ret = pipe_addr(pipeid, &addr); + ret = pipe_addr(name, &addr); if (IS_ERR(ret)) return -PAL_ERROR_DENIED; @@ -198,8 +192,8 @@ static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, int options) { SET_HANDLE_TYPE(hdl, pipe); HANDLE_HDR(hdl)->flags |= RFD(0) | WFD(0); hdl->pipe.fd = fd; - hdl->pipe.pipeid = pipeid; hdl->pipe.nonblocking = (options & PAL_OPTION_NONBLOCK) ? PAL_TRUE : PAL_FALSE; + memcpy(&hdl->pipe.name.str, name, sizeof(hdl->pipe.name.str)); *handle = hdl; return 0; @@ -251,17 +245,15 @@ static int pipe_private(PAL_HANDLE* handle, int options) { * ends of an anonymous pipe). * * - `type` is URI_TYPE_PIPE_SRV: create `pipesrv` handle (intermediate listening socket) with - * name in the form of "@/graphene/" where pipeid is - * derived from `uri` via strtol(). Caller is expected to call - * pipe_waitforclient() afterwards. + * name in the form of "@/graphene/". Caller is expected to + * call pipe_waitforclient() afterwards. * * - `type` is URI_TYPE_PIPE: create `pipe` handle (connecting socket) with name in the form of - * "@/graphene/" where pipeid is derived from `uri` via - * strtol(). + * "@/graphene/". * * \param[out] handle Created PAL handle of type `pipeprv`, `pipesrv`, or `pipe`. * \param[in] type Can be URI_TYPE_PIPE or URI_TYPE_PIPE_SRV. - * \param[in] uri Content is either NUL (for anonymous pipe) or an integer denoting pipeid. + * \param[in] uri Content is either NUL (for anonymous pipe) or a string with pipe name. * \param[in] access Not used. * \param[in] share Not used. * \param[in] create Not used. @@ -277,17 +269,14 @@ static int pipe_open(PAL_HANDLE* handle, const char* type, const char* uri, int if (!strcmp_static(type, URI_TYPE_PIPE) && !*uri) return pipe_private(handle, options); - char* endptr; - PAL_NUM pipeid = strtol(uri, &endptr, 10); - - if (*endptr) + if (strlen(uri) + 1 > PIPE_NAME_MAX) return -PAL_ERROR_INVAL; if (!strcmp_static(type, URI_TYPE_PIPE_SRV)) - return pipe_listen(handle, pipeid, options); + return pipe_listen(handle, uri, options); if (!strcmp_static(type, URI_TYPE_PIPE)) - return pipe_connect(handle, pipeid, options); + return pipe_connect(handle, uri, options); return -PAL_ERROR_INVAL; } @@ -509,7 +498,7 @@ static int pipe_attrsetbyhdl(PAL_HANDLE handle, PAL_STREAM_ATTR* attr) { /*! * \brief Retrieve full URI of PAL handle. * - * Full URI is composed of the type and pipeid: ":". + * Full URI is composed of the type and pipe name: ":". * * \param[in] handle PAL handle of type `pipeprv`, `pipesrv`, `pipecli`, or `pipe`. * \param[out] buffer User-supplied buffer to write URI to. @@ -546,7 +535,7 @@ static int pipe_getname(PAL_HANDLE handle, char* buffer, size_t count) { buffer += prefix_len + 1; count -= prefix_len + 1; - ret = snprintf(buffer, count, "%lu\n", handle->pipe.pipeid); + ret = snprintf(buffer, count, "%s\n", handle->pipe.name.str); if (buffer[ret - 1] != '\n') { memset(buffer, 0, count); return -PAL_ERROR_OVERFLOW; diff --git a/Pal/src/host/Linux/pal_host.h b/Pal/src/host/Linux/pal_host.h index 9de8f0f8..de3fa867 100644 --- a/Pal/src/host/Linux/pal_host.h +++ b/Pal/src/host/Linux/pal_host.h @@ -59,6 +59,10 @@ typedef struct { PAL_HDR hdr; } PAL_RESERVED_HDR; +typedef struct { + char str[PIPE_NAME_MAX]; +} PAL_PIPE_NAME; + typedef struct pal_handle { /* TSAI: Here we define the internal types of PAL_HANDLE @@ -86,7 +90,7 @@ typedef struct pal_handle struct { PAL_IDX fd; - PAL_NUM pipeid; + PAL_PIPE_NAME name; PAL_BOL nonblocking; } pipe; diff --git a/Pal/src/host/Linux/pal_linux.h b/Pal/src/host/Linux/pal_linux.h index f7372e24..c9c32ac0 100644 --- a/Pal/src/host/Linux/pal_linux.h +++ b/Pal/src/host/Linux/pal_linux.h @@ -44,8 +44,6 @@ #define ERRNO INTERNAL_SYSCALL_ERRNO #define ERRNO_P INTERNAL_SYSCALL_ERRNO_P -#define GRAPHENE_UNIX_PREFIX_FMT "/graphene/%016lx" - struct timespec; struct timeval; diff --git a/Pal/src/host/Linux/pal_security.h b/Pal/src/host/Linux/pal_security.h index 40aa1474..f92d4a1b 100644 --- a/Pal/src/host/Linux/pal_security.h +++ b/Pal/src/host/Linux/pal_security.h @@ -62,9 +62,6 @@ extern struct pal_sec { unsigned int process_id; int random_device; - /* pipes and sockets */ - unsigned long pipe_prefix_id; - /* for debugger */ void (*_dl_debug_state)(void); struct r_debug* _r_debug; diff --git a/Pal/src/host/Skeleton/db_pipes.c b/Pal/src/host/Skeleton/db_pipes.c index 8925a1fb..a702d877 100644 --- a/Pal/src/host/Skeleton/db_pipes.c +++ b/Pal/src/host/Skeleton/db_pipes.c @@ -27,7 +27,7 @@ #include "pal_error.h" #include "pal_internal.h" -static int pipe_listen(PAL_HANDLE* handle, PAL_NUM pipeid, int create) { +static int pipe_listen(PAL_HANDLE* handle, const char* name, int options) { return -PAL_ERROR_NOTIMPLEMENTED; } @@ -35,41 +35,27 @@ static int pipe_waitforclient(PAL_HANDLE handle, PAL_HANDLE* client) { return -PAL_ERROR_NOTIMPLEMENTED; } -static int pipe_connect(PAL_HANDLE* handle, PAL_NUM pipeid, PAL_IDX connid, int create) { +static int pipe_connect(PAL_HANDLE* handle, const char* name, int options) { return -PAL_ERROR_NOTIMPLEMENTED; } -static int pipe_private(PAL_HANDLE* handle) { +static int pipe_private(PAL_HANDLE* handle, int options) { return -PAL_ERROR_NOTIMPLEMENTED; } -/* 'open' operation of pipe stream. For each pipe stream, it is identified by a decimal number in - URI. There could be two types: pipe and pipe.srv. They behave pretty much the same, except they - are two ends of the pipe. */ static int pipe_open(PAL_HANDLE* handle, const char* type, const char* uri, int access, int share, int create, int options) { if (!strcmp_static(type, URI_TYPE_PIPE) && !*uri) - return pipe_private(handle); + return pipe_private(handle, options); - char* endptr; - PAL_NUM pipeid = strtol(uri, &endptr, 10); - PAL_IDX connid = 0; - - if (*endptr == ':') { - if (create & PAL_CREATE_TRY) - return -PAL_ERROR_INVAL; - - connid = strtol(endptr + 1, &endptr, 10); - } - - if (*endptr) + if (strlen(uri) + 1 > PIPE_NAME_MAX) return -PAL_ERROR_INVAL; if (!strcmp_static(type, URI_TYPE_PIPE_SRV)) - return pipe_listen(handle, pipeid, create); + return pipe_listen(handle, uri, options); if (!strcmp_static(type, URI_TYPE_PIPE)) - return pipe_connect(handle, pipeid, connid, create); + return pipe_connect(handle, uri, options); return -PAL_ERROR_INVAL; }