diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/posix/posix_aio.h | 3 | ||||
| -rw-r--r-- | src/platform/posix/posix_epdesc.c | 55 | ||||
| -rw-r--r-- | src/platform/posix/posix_ipc.c | 16 | ||||
| -rw-r--r-- | src/platform/posix/posix_tcp.c | 2 | ||||
| -rw-r--r-- | src/platform/windows/win_ipc.c | 52 |
5 files changed, 110 insertions, 18 deletions
diff --git a/src/platform/posix/posix_aio.h b/src/platform/posix/posix_aio.h index 15dae06c..3954f225 100644 --- a/src/platform/posix/posix_aio.h +++ b/src/platform/posix/posix_aio.h @@ -34,7 +34,7 @@ extern int nni_posix_pipedesc_sockname(nni_posix_pipedesc *, nni_sockaddr *); extern int nni_posix_pipedesc_set_nodelay(nni_posix_pipedesc *, bool); extern int nni_posix_pipedesc_set_keepalive(nni_posix_pipedesc *, bool); -extern int nni_posix_epdesc_init(nni_posix_epdesc **); +extern int nni_posix_epdesc_init(nni_posix_epdesc **, int); extern void nni_posix_epdesc_set_local(nni_posix_epdesc *, void *, size_t); extern void nni_posix_epdesc_set_remote(nni_posix_epdesc *, void *, size_t); extern void nni_posix_epdesc_fini(nni_posix_epdesc *); @@ -43,5 +43,6 @@ extern void nni_posix_epdesc_connect(nni_posix_epdesc *, nni_aio *); extern int nni_posix_epdesc_listen(nni_posix_epdesc *); extern void nni_posix_epdesc_accept(nni_posix_epdesc *, nni_aio *); extern int nni_posix_epdesc_sockname(nni_posix_epdesc *, nni_sockaddr *); +extern int nni_posix_epdesc_set_permissions(nni_posix_epdesc *, mode_t); #endif // PLATFORM_POSIX_AIO_H diff --git a/src/platform/posix/posix_epdesc.c b/src/platform/posix/posix_epdesc.c index f97f12b8..0f63304f 100644 --- a/src/platform/posix/posix_epdesc.c +++ b/src/platform/posix/posix_epdesc.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> #include <sys/socket.h> +#include <sys/stat.h> #include <sys/types.h> #include <sys/uio.h> #include <sys/un.h> @@ -38,10 +39,13 @@ struct nni_posix_epdesc { nni_list connectq; nni_list acceptq; bool closed; + bool started; struct sockaddr_storage locaddr; struct sockaddr_storage remaddr; socklen_t loclen; socklen_t remlen; + mode_t perms; // UNIX sockets only + int mode; // end point mode (dialer/listener) nni_mtx mtx; }; @@ -287,17 +291,35 @@ nni_posix_epdesc_listen(nni_posix_epdesc *ed) #endif if (bind(fd, (struct sockaddr *) ss, len) < 0) { - nni_mtx_unlock(&ed->mtx); rv = nni_plat_errno(errno); + nni_mtx_unlock(&ed->mtx); (void) close(fd); return (rv); } + // For UNIX domain sockets, optionally set the permission bits. + // This is done after the bind and before listen, and on the file + // rather than the file descriptor. + // Experiments have shown that chmod() works correctly, provided that + // it is done *before* the listen() operation, whereas fchmod seems to + // have no impact. This behavior was observed on both macOS and Linux. + // YMMV on other platforms. + if ((ss->ss_family == AF_UNIX) && (ed->perms != 0)) { + struct sockaddr_un *sun = (void *) ss; + mode_t perms = ed->perms & ~(S_IFMT); + if ((rv = chmod(sun->sun_path, perms)) != 0) { + rv = nni_plat_errno(errno); + nni_mtx_unlock(&ed->mtx); + close(fd); + return (rv); + } + } + // Listen -- 128 depth is probably sufficient. If it isn't, other // bad things are going to happen. if (listen(fd, 128) != 0) { - nni_mtx_unlock(&ed->mtx); rv = nni_plat_errno(errno); + nni_mtx_unlock(&ed->mtx); (void) close(fd); return (rv); } @@ -311,6 +333,7 @@ nni_posix_epdesc_listen(nni_posix_epdesc *ed) nni_mtx_unlock(&ed->mtx); return (rv); } + ed->started = true; nni_mtx_unlock(&ed->mtx); return (0); } @@ -384,6 +407,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio) if ((rv = connect(fd, (void *) &ed->remaddr, ed->remlen)) == 0) { // Immediate connect, cool! This probably only happens on // loopback, and probably not on every platform. + ed->started = true; nni_posix_epdesc_finish(aio, 0, fd); nni_mtx_unlock(&ed->mtx); return; @@ -403,6 +427,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio) // We have to submit to the pollq, because the connection is pending. ed->node.fd = fd; + ed->started = true; if ((rv = nni_posix_pollq_add(&ed->node)) != 0) { ed->node.fd = -1; nni_mtx_unlock(&ed->mtx); @@ -418,7 +443,7 @@ nni_posix_epdesc_connect(nni_posix_epdesc *ed, nni_aio *aio) } int -nni_posix_epdesc_init(nni_posix_epdesc **edp) +nni_posix_epdesc_init(nni_posix_epdesc **edp, int mode) { nni_posix_epdesc *ed; int rv; @@ -439,6 +464,9 @@ nni_posix_epdesc_init(nni_posix_epdesc **edp) ed->node.data = ed; ed->node.fd = -1; ed->closed = false; + ed->started = false; + ed->perms = 0; // zero means use default (no change) + ed->mode = mode; nni_aio_list_init(&ed->connectq); nni_aio_list_init(&ed->acceptq); @@ -476,6 +504,27 @@ nni_posix_epdesc_set_remote(nni_posix_epdesc *ed, void *sa, size_t len) nni_mtx_unlock(&ed->mtx); } +int +nni_posix_epdesc_set_permissions(nni_posix_epdesc *ed, mode_t mode) +{ + nni_mtx_lock(&ed->mtx); + if (ed->mode != NNI_EP_MODE_LISTEN) { + nni_mtx_unlock(&ed->mtx); + return (NNG_ENOTSUP); + } + if (ed->started) { + nni_mtx_unlock(&ed->mtx); + return (NNG_EBUSY); + } + if ((mode & S_IFMT) != 0) { + nni_mtx_unlock(&ed->mtx); + return (NNG_EINVAL); + } + ed->perms = mode | S_IFSOCK; // we set IFSOCK to ensure non-zero + nni_mtx_unlock(&ed->mtx); + return (0); +} + void nni_posix_epdesc_fini(nni_posix_epdesc *ed) { diff --git a/src/platform/posix/posix_ipc.c b/src/platform/posix/posix_ipc.c index f7cfc0db..c1bb9292 100644 --- a/src/platform/posix/posix_ipc.c +++ b/src/platform/posix/posix_ipc.c @@ -49,7 +49,7 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode) int rv; struct sockaddr_un sun; - if ((rv = nni_posix_epdesc_init(&ed)) != 0) { + if ((rv = nni_posix_epdesc_init(&ed, mode)) != 0) { return (rv); } switch (mode) { @@ -87,6 +87,20 @@ nni_plat_ipc_ep_close(nni_plat_ipc_ep *ep) nni_posix_epdesc_close((void *) ep); } +int +nni_plat_ipc_ep_set_permissions(nni_plat_ipc_ep *ep, uint32_t bits) +{ + return (nni_posix_epdesc_set_permissions((void *) ep, (mode_t) bits)); +} + +int +nni_plat_ipc_ep_set_security_descriptor(nni_plat_ipc_ep *ep, void *attr) +{ + NNI_ARG_UNUSED(ep); + NNI_ARG_UNUSED(attr); + return (NNG_ENOTSUP); +} + // UNIX DOMAIN SOCKETS -- these have names in the file namespace. // We are going to check to see if there was a name already there. // If there was, and nothing is listening (ECONNREFUSED), then we diff --git a/src/platform/posix/posix_tcp.c b/src/platform/posix/posix_tcp.c index 81ec330b..c00f9433 100644 --- a/src/platform/posix/posix_tcp.c +++ b/src/platform/posix/posix_tcp.c @@ -36,7 +36,7 @@ nni_plat_tcp_ep_init(nni_plat_tcp_ep **epp, const nni_sockaddr *lsa, NNI_ARG_UNUSED(mode); - if ((rv = nni_posix_epdesc_init(&ed)) != 0) { + if ((rv = nni_posix_epdesc_init(&ed, mode)) != 0) { return (rv); } diff --git a/src/platform/windows/win_ipc.c b/src/platform/windows/win_ipc.c index d372f639..7d118672 100644 --- a/src/platform/windows/win_ipc.c +++ b/src/platform/windows/win_ipc.c @@ -21,14 +21,15 @@ struct nni_plat_ipc_pipe { }; struct nni_plat_ipc_ep { - char path[NNG_MAXADDRLEN + 16]; - nni_sockaddr addr; - int mode; - int started; - HANDLE p; // accept side only - nni_win_event acc_ev; // accept side only - nni_aio * con_aio; // conn side only - nni_list_node node; // conn side uses this + char path[NNG_MAXADDRLEN + 16]; + nni_sockaddr addr; + int mode; + bool started; + HANDLE p; // accept side only + nni_win_event acc_ev; // accept side only + nni_aio * con_aio; // conn side only + nni_list_node node; // conn side uses this + SECURITY_ATTRIBUTES sec_attr; }; static int nni_win_ipc_pipe_start(nni_win_event *, nni_aio *); @@ -203,7 +204,10 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode) } ZeroMemory(ep, sizeof(*ep)); - ep->mode = mode; + ep->mode = mode; + ep->sec_attr.nLength = sizeof(ep->sec_attr); + ep->sec_attr.lpSecurityDescriptor = NULL; + ep->sec_attr.bInheritHandle = FALSE; NNI_LIST_NODE_INIT(&ep->node); ep->addr = *sa; @@ -214,6 +218,30 @@ nni_plat_ipc_ep_init(nni_plat_ipc_ep **epp, const nni_sockaddr *sa, int mode) } int +nni_plat_ipc_ep_set_permissions(nni_plat_ipc_ep *ep, uint32_t bits) +{ + NNI_ARG_UNUSED(ep); + NNI_ARG_UNUSED(bits); + return (NNG_ENOTSUP); +} + +int +nni_plat_ipc_ep_set_security_descriptor(nni_plat_ipc_ep *ep, void *desc) +{ + if (ep->started) { + return (NNG_EBUSY); + } + if (ep->mode != NNI_EP_MODE_LISTEN) { + return (NNG_ENOTSUP); + } + if (!IsValidSecurityDescriptor((SECURITY_DESCRIPTOR *) desc)) { + return (NNG_EINVAL); + } + ep->sec_attr.lpSecurityDescriptor = desc; + return (0); +} + +int nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep) { int rv; @@ -233,7 +261,7 @@ nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep) FILE_FLAG_FIRST_PIPE_INSTANCE, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, - PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL); + PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &ep->sec_attr); if (p == INVALID_HANDLE_VALUE) { if ((rv = GetLastError()) == ERROR_ACCESS_DENIED) { rv = NNG_EADDRINUSE; @@ -252,7 +280,7 @@ nni_plat_ipc_ep_listen(nni_plat_ipc_ep *ep) } ep->p = p; - ep->started = 1; + ep->started = true; return (0); failed: @@ -281,7 +309,7 @@ nni_win_ipc_acc_finish(nni_win_event *evt, nni_aio *aio) PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, - PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, NULL); + PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, &ep->sec_attr); if (newp == INVALID_HANDLE_VALUE) { rv = nni_win_error(GetLastError()); // We connected, but as we cannot get a new pipe, |
