meta-starlingx: remove the upstream layer
[pti/rtp.git] / meta-starlingx / meta-stx-distro / recipes-security / gssproxy / files / client-Switch-to-non-blocking-sockets.patch
diff --git a/meta-starlingx/meta-stx-distro/recipes-security/gssproxy/files/client-Switch-to-non-blocking-sockets.patch b/meta-starlingx/meta-stx-distro/recipes-security/gssproxy/files/client-Switch-to-non-blocking-sockets.patch
deleted file mode 100644 (file)
index 2d0b34b..0000000
+++ /dev/null
@@ -1,485 +0,0 @@
-From 1962e6128a4d86a7c54977577e1e4224cadbb5f7 Mon Sep 17 00:00:00 2001
-From: Alexander Scheel <ascheel@redhat.com>
-Date: Wed, 2 Aug 2017 15:11:49 -0400
-Subject: [PATCH] [client] Switch to non-blocking sockets
-
-Switch the gssproxy client library to non-blocking sockets, allowing
-for timeout and retry operations.  The client will automatically retry
-both send() and recv() operations three times on ETIMEDOUT.  If the
-combined send() and recv() hit the three time limit, ETIMEDOUT will be
-exposed to the caller in the minor status.
-
-Signed-off-by: Alexander Scheel <ascheel@redhat.com>
-Reviewed-by: Simo Sorce <simo@redhat.com>
-[rharwood@redhat.com: commit message cleanups, rebased]
-Reviewed-by: Robbie Harwood <rharwood@redhat.com>
-(cherry picked from commit d035646c8feb0b78f0c157580ca02c46cd00dd7e)
----
- proxy/src/client/gpm_common.c | 317 +++++++++++++++++++++++++++++++---
- 1 file changed, 295 insertions(+), 22 deletions(-)
-
-diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c
-index 2133618..dba23a6 100644
---- a/proxy/src/client/gpm_common.c
-+++ b/proxy/src/client/gpm_common.c
-@@ -7,9 +7,15 @@
- #include <stdlib.h>
- #include <time.h>
- #include <pthread.h>
-+#include <sys/epoll.h>
-+#include <fcntl.h>
-+#include <sys/timerfd.h>
- #define FRAGMENT_BIT (1 << 31)
-+#define RESPONSE_TIMEOUT 15
-+#define MAX_TIMEOUT_RETRY 3
-+
- struct gpm_ctx {
-     pthread_mutex_t lock;
-     int fd;
-@@ -20,6 +26,9 @@ struct gpm_ctx {
-     gid_t gid;
-     int next_xid;
-+
-+    int epollfd;
-+    int timerfd;
- };
- /* a single global struct is not particularly efficient,
-@@ -39,6 +48,8 @@ static void gpm_init_once(void)
-     pthread_mutex_init(&gpm_global_ctx.lock, &attr);
-     gpm_global_ctx.fd = -1;
-+    gpm_global_ctx.epollfd = -1;
-+    gpm_global_ctx.timerfd = -1;
-     seedp = time(NULL) + getpid() + pthread_self();
-     gpm_global_ctx.next_xid = rand_r(&seedp);
-@@ -69,6 +80,7 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx)
-     struct sockaddr_un addr = {0};
-     char name[PATH_MAX];
-     int ret;
-+    unsigned flags;
-     int fd = -1;
-     ret = get_pipe_name(name);
-@@ -86,6 +98,18 @@ static int gpm_open_socket(struct gpm_ctx *gpmctx)
-         goto done;
-     }
-+    ret = fcntl(fd, F_GETFD, &flags);
-+    if (ret != 0) {
-+        ret = errno;
-+        goto done;
-+    }
-+
-+    ret = fcntl(fd, F_SETFD, flags | O_NONBLOCK);
-+    if (ret != 0) {
-+        ret = errno;
-+        goto done;
-+    }
-+
-     ret = connect(fd, (struct sockaddr *)&addr, sizeof(addr));
-     if (ret == -1) {
-         ret = errno;
-@@ -163,6 +187,158 @@ static int gpm_release_sock(struct gpm_ctx *gpmctx)
-     return pthread_mutex_unlock(&gpmctx->lock);
- }
-+static void gpm_timer_close(struct gpm_ctx *gpmctx) {
-+    if (gpmctx->timerfd < 0) {
-+        return;
-+    }
-+
-+    close(gpmctx->timerfd);
-+    gpmctx->timerfd = -1;
-+}
-+
-+static int gpm_timer_setup(struct gpm_ctx *gpmctx, int timeout_seconds) {
-+    int ret;
-+    struct itimerspec its;
-+
-+    if (gpmctx->timerfd >= 0) {
-+        gpm_timer_close(gpmctx);
-+    }
-+
-+    gpmctx->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
-+    if (gpmctx->timerfd < 0) {
-+        return errno;
-+    }
-+
-+    its.it_interval.tv_sec = timeout_seconds;
-+    its.it_interval.tv_nsec = 0;
-+    its.it_value.tv_sec = timeout_seconds;
-+    its.it_value.tv_nsec = 0;
-+
-+    ret = timerfd_settime(gpmctx->timerfd, 0, &its, NULL);
-+    if (ret) {
-+        ret = errno;
-+        gpm_timer_close(gpmctx);
-+        return ret;
-+    }
-+
-+    return 0;
-+}
-+
-+static void gpm_epoll_close(struct gpm_ctx *gpmctx) {
-+    if (gpmctx->epollfd < 0) {
-+        return;
-+    }
-+
-+    close(gpmctx->epollfd);
-+    gpmctx->epollfd = -1;
-+}
-+
-+static int gpm_epoll_setup(struct gpm_ctx *gpmctx) {
-+    struct epoll_event ev;
-+    int ret;
-+
-+    if (gpmctx->epollfd >= 0) {
-+        gpm_epoll_close(gpmctx);
-+    }
-+
-+    gpmctx->epollfd = epoll_create1(EPOLL_CLOEXEC);
-+    if (gpmctx->epollfd == -1) {
-+        return errno;
-+    }
-+
-+    /* Add timer */
-+    ev.events = EPOLLIN;
-+    ev.data.fd = gpmctx->timerfd;
-+    ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_ADD, gpmctx->timerfd, &ev);
-+    if (ret == -1) {
-+        ret = errno;
-+        gpm_epoll_close(gpmctx);
-+        return ret;
-+    }
-+
-+    return ret;
-+}
-+
-+static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) {
-+    int ret;
-+    int epoll_ret;
-+    struct epoll_event ev;
-+    struct epoll_event events[2];
-+    uint64_t timer_read;
-+
-+    if (gpmctx->epollfd < 0) {
-+        ret = gpm_epoll_setup(gpmctx);
-+        if (ret)
-+            return ret;
-+    }
-+
-+    ev.events = event_flags;
-+    ev.data.fd = gpmctx->fd;
-+    epoll_ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_ADD, gpmctx->fd, &ev);
-+    if (epoll_ret == -1) {
-+        ret = errno;
-+        gpm_epoll_close(gpmctx);
-+        return ret;
-+    }
-+
-+    do {
-+        epoll_ret = epoll_wait(gpmctx->epollfd, events, 2, -1);
-+    } while (epoll_ret < 0 && errno == EINTR);
-+
-+    if (epoll_ret < 0) {
-+        /* Error while waiting that isn't EINTR */
-+        ret = errno;
-+        gpm_epoll_close(gpmctx);
-+    } else if (epoll_ret == 0) {
-+        /* Shouldn't happen as timeout == -1; treat it like a timeout
-+         * occurred. */
-+        ret = ETIMEDOUT;
-+        gpm_epoll_close(gpmctx);
-+    } else if (epoll_ret == 1 && events[0].data.fd == gpmctx->timerfd) {
-+        /* Got an event which is only our timer */
-+        ret = read(gpmctx->timerfd, &timer_read, sizeof(uint64_t));
-+        if (ret == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
-+            /* In the case when reading from the timer failed, don't hide the
-+             * timer error behind ETIMEDOUT such that it isn't retried */
-+            ret = errno;
-+        } else {
-+            /* If ret == 0, then we definitely timed out. Else, if ret == -1
-+             * and errno == EAGAIN or errno == EWOULDBLOCK, we're in a weird
-+             * edge case where epoll thinks the timer can be read, but it
-+             * is blocking more; treat it like a TIMEOUT and retry, as
-+             * nothing around us would handle EAGAIN from timer and retry
-+             * it. */
-+            ret = ETIMEDOUT;
-+        }
-+        gpm_epoll_close(gpmctx);
-+    } else {
-+        /* If ret == 2, then we ignore the timerfd; that way if the next
-+         * operation cannot be performed immediately, we timeout and retry.
-+         * If ret == 1 and data.fd == gpmctx->fd, return 0. */
-+        ret = 0;
-+    }
-+
-+    epoll_ret = epoll_ctl(gpmctx->epollfd, EPOLL_CTL_DEL, gpmctx->fd, NULL);
-+    if (epoll_ret == -1) {
-+        /* If we previously had an error, expose that error instead of
-+         * clobbering it with errno; else if no error, then assume it is
-+         * better to notify of the error deleting the event than it is
-+         * to continue. */
-+        if (ret == 0)
-+            ret = errno;
-+        gpm_epoll_close(gpmctx);
-+    }
-+
-+    return ret;
-+}
-+
-+static int gpm_retry_socket(struct gpm_ctx *gpmctx)
-+{
-+    gpm_epoll_close(gpmctx);
-+    gpm_close_socket(gpmctx);
-+    return gpm_open_socket(gpmctx);
-+}
-+
- /* must be called after the lock has been grabbed */
- static int gpm_send_buffer(struct gpm_ctx *gpmctx,
-                            char *buffer, uint32_t length)
-@@ -183,8 +359,13 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx,
-     retry = false;
-     do {
-         do {
-+            ret = gpm_epoll_wait(gpmctx, EPOLLOUT);
-+            if (ret != 0) {
-+                goto done;
-+            }
-+
-             ret = 0;
--            wn = send(gpmctx->fd, &size, sizeof(uint32_t), MSG_NOSIGNAL);
-+            wn = write(gpmctx->fd, &size, sizeof(uint32_t));
-             if (wn == -1) {
-                 ret = errno;
-             }
-@@ -192,8 +373,7 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx,
-         if (wn != 4) {
-             /* reopen and retry once */
-             if (retry == false) {
--                gpm_close_socket(gpmctx);
--                ret = gpm_open_socket(gpmctx);
-+                ret = gpm_retry_socket(gpmctx);
-                 if (ret == 0) {
-                     retry = true;
-                     continue;
-@@ -208,9 +388,14 @@ static int gpm_send_buffer(struct gpm_ctx *gpmctx,
-     pos = 0;
-     while (length > pos) {
--        wn = send(gpmctx->fd, buffer + pos, length - pos, MSG_NOSIGNAL);
-+        ret = gpm_epoll_wait(gpmctx, EPOLLOUT);
-+        if (ret) {
-+            goto done;
-+        }
-+
-+        wn = write(gpmctx->fd, buffer + pos, length - pos);
-         if (wn == -1) {
--            if (errno == EINTR) {
-+            if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
-                 continue;
-             }
-             ret = errno;
-@@ -231,7 +416,7 @@ done:
- /* must be called after the lock has been grabbed */
- static int gpm_recv_buffer(struct gpm_ctx *gpmctx,
--                           char *buffer, uint32_t *length)
-+                           char **buffer, uint32_t *length)
- {
-     uint32_t size;
-     ssize_t rn;
-@@ -239,6 +424,11 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx,
-     int ret;
-     do {
-+        ret = gpm_epoll_wait(gpmctx, EPOLLIN);
-+        if (ret) {
-+            goto done;
-+        }
-+
-         ret = 0;
-         rn = read(gpmctx->fd, &size, sizeof(uint32_t));
-         if (rn == -1) {
-@@ -258,11 +448,22 @@ static int gpm_recv_buffer(struct gpm_ctx *gpmctx,
-         goto done;
-     }
-+    *buffer = malloc(*length);
-+    if (*buffer == NULL) {
-+        ret = ENOMEM;
-+        goto done;
-+    }
-+
-     pos = 0;
-     while (*length > pos) {
--        rn = read(gpmctx->fd, buffer + pos, *length - pos);
-+        ret = gpm_epoll_wait(gpmctx, EPOLLIN);
-+        if (ret) {
-+            goto done;
-+        }
-+
-+        rn = read(gpmctx->fd, *buffer + pos, *length - pos);
-         if (rn == -1) {
--            if (errno == EINTR) {
-+            if (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
-                 continue;
-             }
-             ret = errno;
-@@ -281,6 +482,7 @@ done:
-     if (ret) {
-         /* on errors we can only close the fd and return */
-         gpm_close_socket(gpmctx);
-+        gpm_epoll_close(gpmctx);
-     }
-     return ret;
- }
-@@ -309,6 +511,63 @@ static struct gpm_ctx *gpm_get_ctx(void)
-     return &gpm_global_ctx;
- }
-+static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer,
-+                              uint32_t send_length, char** recv_buffer,
-+                              uint32_t *recv_length)
-+{
-+    int ret;
-+    int retry_count;
-+
-+    /* setup timer */
-+    ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT);
-+    if (ret)
-+        return ret;
-+
-+    for (retry_count = 0; retry_count < MAX_TIMEOUT_RETRY; retry_count++) {
-+        /* send to proxy */
-+        ret = gpm_send_buffer(gpmctx, send_buffer, send_length);
-+
-+        if (ret == 0) {
-+            /* No error, continue to recv */
-+        } else if (ret == ETIMEDOUT) {
-+            /* Close and reopen socket before trying again */
-+            ret = gpm_retry_socket(gpmctx);
-+            if (ret != 0)
-+                return ret;
-+            ret = ETIMEDOUT;
-+
-+            /* RETRY entire send */
-+            continue;
-+        } else {
-+            /* Other error */
-+            return ret;
-+        }
-+
-+        /* receive answer */
-+        ret = gpm_recv_buffer(gpmctx, recv_buffer, recv_length);
-+        if (ret == 0) {
-+            /* No error */
-+            break;
-+        } else if (ret == ETIMEDOUT) {
-+            /* Close and reopen socket before trying again */
-+            ret = gpm_retry_socket(gpmctx);
-+
-+            /* Free buffer and set it to NULL to prevent free(xdr_reply_ctx) */
-+            free(recv_buffer);
-+            recv_buffer = NULL;
-+
-+            if (ret != 0)
-+                return ret;
-+            ret = ETIMEDOUT;
-+        } else {
-+            /* Other error */
-+            return ret;
-+        }
-+    }
-+
-+    return ret;
-+}
-+
- OM_uint32 gpm_release_buffer(OM_uint32 *minor_status,
-                              gss_buffer_t buffer)
- {
-@@ -399,15 +658,20 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res)
-     gp_rpc_msg msg;
-     XDR xdr_call_ctx;
-     XDR xdr_reply_ctx;
--    char buffer[MAX_RPC_SIZE];
--    uint32_t length;
-+    char *send_buffer = NULL;
-+    char *recv_buffer = NULL;
-+    uint32_t send_length;
-+    uint32_t recv_length;
-     uint32_t xid;
-     bool xdrok;
-     bool sockgrab = false;
-     int ret;
--    xdrmem_create(&xdr_call_ctx, buffer, MAX_RPC_SIZE, XDR_ENCODE);
--    xdrmem_create(&xdr_reply_ctx, buffer, MAX_RPC_SIZE, XDR_DECODE);
-+    send_buffer = malloc(MAX_RPC_SIZE);
-+    if (send_buffer == NULL)
-+        return ENOMEM;
-+
-+    xdrmem_create(&xdr_call_ctx, send_buffer, MAX_RPC_SIZE, XDR_ENCODE);
-     memset(&msg, 0, sizeof(gp_rpc_msg));
-     msg.header.type = GP_RPC_CALL;
-@@ -450,22 +714,22 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res)
-         goto done;
-     }
--    /* send to proxy */
--    ret = gpm_send_buffer(gpmctx, buffer, xdr_getpos(&xdr_call_ctx));
--    if (ret) {
--        goto done;
--    }
-+    /* set send_length */
-+    send_length = xdr_getpos(&xdr_call_ctx);
--    /* receive answer */
--    ret = gpm_recv_buffer(gpmctx, buffer, &length);
--    if (ret) {
-+    /* Send request, receive response with timeout */
-+    ret = gpm_send_recv_loop(gpmctx, send_buffer, send_length, &recv_buffer,
-+                             &recv_length);
-+    if (ret)
-         goto done;
--    }
-     /* release the lock */
-     gpm_release_sock(gpmctx);
-     sockgrab = false;
-+    /* Create the reply context */
-+    xdrmem_create(&xdr_reply_ctx, recv_buffer, recv_length, XDR_DECODE);
-+
-     /* decode header */
-     memset(&msg, 0, sizeof(gp_rpc_msg));
-     xdrok = xdr_gp_rpc_msg(&xdr_reply_ctx, &msg);
-@@ -489,12 +753,21 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res)
-     }
- done:
-+    gpm_timer_close(gpmctx);
-+    gpm_epoll_close(gpmctx);
-+
-     if (sockgrab) {
-         gpm_release_sock(gpmctx);
-     }
-     xdr_free((xdrproc_t)xdr_gp_rpc_msg, (char *)&msg);
-     xdr_destroy(&xdr_call_ctx);
--    xdr_destroy(&xdr_reply_ctx);
-+
-+    if (recv_buffer != NULL)
-+        xdr_destroy(&xdr_reply_ctx);
-+
-+    free(send_buffer);
-+    free(recv_buffer);
-+
-     return ret;
- }