Blame SOURCES/Close-epoll-fd-within-the-lock.patch

472fdf
From 69e1baa7d7f271d294e619148b4a2bae10230b5e Mon Sep 17 00:00:00 2001
472fdf
From: Simo Sorce <simo@redhat.com>
472fdf
Date: Wed, 6 Mar 2019 10:31:13 -0500
472fdf
Subject: [PATCH] Close epoll fd within the lock
472fdf
472fdf
A race condition may happen where we close the epoll socket, after
472fdf
another thread grabbed the lock and is using epoll itself.
472fdf
On some kernels this may cause epoll to not fire any event leaving the
472fdf
thread stuck forever.
472fdf
472fdf
Signed-off-by: Simo Sorce <simo@redhat.com>
472fdf
[rharwood@redhat.com: cleanup commit message, adjusted function ordering]
472fdf
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
472fdf
Merges: #241
472fdf
(cherry picked from commit 0ccfd32f8ef16caf65698c5319dfa251d43433af)
472fdf
472fdf
Squashed with:
472fdf
472fdf
Reorder functions
472fdf
472fdf
Keep related functions closer together like before
472fdf
472fdf
Signed-off-by: Simo Sorce <simo@redhat.com>
472fdf
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
472fdf
Resolves: #242
472fdf
(cherry picked from commit 6accc0afead574e11447447c949f2abcb1a34826)
472fdf
(cherry picked from commit c33de0c213d570f370fd954869c2ad99901b2cf3)
472fdf
[rharwood@redhat.com: I learned an important lesson upstream]
472fdf
---
472fdf
 proxy/src/client/gpm_common.c | 100 ++++++++++++++++++----------------
472fdf
 1 file changed, 54 insertions(+), 46 deletions(-)
472fdf
472fdf
diff --git a/proxy/src/client/gpm_common.c b/proxy/src/client/gpm_common.c
472fdf
index b482efb..554c91c 100644
472fdf
--- a/proxy/src/client/gpm_common.c
472fdf
+++ b/proxy/src/client/gpm_common.c
472fdf
@@ -139,44 +139,8 @@ static void gpm_close_socket(struct gpm_ctx *gpmctx)
472fdf
     gpmctx->fd = -1;
472fdf
 }
472fdf
 
472fdf
-static int gpm_grab_sock(struct gpm_ctx *gpmctx)
472fdf
+static void gpm_timer_close(struct gpm_ctx *gpmctx)
472fdf
 {
472fdf
-    int ret;
472fdf
-    pid_t p;
472fdf
-    uid_t u;
472fdf
-    gid_t g;
472fdf
-
472fdf
-    ret = pthread_mutex_lock(&gpmctx->lock);
472fdf
-    if (ret) {
472fdf
-        return ret;
472fdf
-    }
472fdf
-
472fdf
-    /* Detect fork / setresuid and friends */
472fdf
-    p = getpid();
472fdf
-    u = geteuid();
472fdf
-    g = getegid();
472fdf
-
472fdf
-    if (gpmctx->fd != -1 &&
472fdf
-        (p != gpmctx->pid || u != gpmctx->uid || g != gpmctx->gid)) {
472fdf
-        gpm_close_socket(gpmctx);
472fdf
-    }
472fdf
-
472fdf
-    if (gpmctx->fd == -1) {
472fdf
-        ret = gpm_open_socket(gpmctx);
472fdf
-    }
472fdf
-
472fdf
-    if (ret) {
472fdf
-        pthread_mutex_unlock(&gpmctx->lock);
472fdf
-    }
472fdf
-    return ret;
472fdf
-}
472fdf
-
472fdf
-static int gpm_release_sock(struct gpm_ctx *gpmctx)
472fdf
-{
472fdf
-    return pthread_mutex_unlock(&gpmctx->lock);
472fdf
-}
472fdf
-
472fdf
-static void gpm_timer_close(struct gpm_ctx *gpmctx) {
472fdf
     if (gpmctx->timerfd < 0) {
472fdf
         return;
472fdf
     }
472fdf
@@ -248,7 +212,59 @@ static int gpm_epoll_setup(struct gpm_ctx *gpmctx) {
472fdf
     return ret;
472fdf
 }
472fdf
 
472fdf
-static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags) {
472fdf
+static int gpm_release_sock(struct gpm_ctx *gpmctx)
472fdf
+{
472fdf
+    gpm_epoll_close(gpmctx);
472fdf
+    gpm_timer_close(gpmctx);
472fdf
+    return pthread_mutex_unlock(&gpmctx->lock);
472fdf
+}
472fdf
+
472fdf
+static int gpm_grab_sock(struct gpm_ctx *gpmctx)
472fdf
+{
472fdf
+    int ret;
472fdf
+    pid_t p;
472fdf
+    uid_t u;
472fdf
+    gid_t g;
472fdf
+
472fdf
+    ret = pthread_mutex_lock(&gpmctx->lock);
472fdf
+    if (ret) {
472fdf
+        return ret;
472fdf
+    }
472fdf
+
472fdf
+    /* Detect fork / setresuid and friends */
472fdf
+    p = getpid();
472fdf
+    u = geteuid();
472fdf
+    g = getegid();
472fdf
+
472fdf
+    if (gpmctx->fd != -1 &&
472fdf
+        (p != gpmctx->pid || u != gpmctx->uid || g != gpmctx->gid)) {
472fdf
+        gpm_close_socket(gpmctx);
472fdf
+    }
472fdf
+
472fdf
+    if (gpmctx->fd == -1) {
472fdf
+        ret = gpm_open_socket(gpmctx);
472fdf
+        if (ret) {
472fdf
+            goto done;
472fdf
+        }
472fdf
+    }
472fdf
+
472fdf
+    /* setup timer */
472fdf
+    ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT);
472fdf
+    if (ret) {
472fdf
+        goto done;
472fdf
+    }
472fdf
+    /* create epoll fd as well */
472fdf
+    ret = gpm_epoll_setup(gpmctx);
472fdf
+
472fdf
+done:
472fdf
+    if (ret) {
472fdf
+        gpm_release_sock(gpmctx);
472fdf
+    }
472fdf
+    return ret;
472fdf
+}
472fdf
+
472fdf
+static int gpm_epoll_wait(struct gpm_ctx *gpmctx, uint32_t event_flags)
472fdf
+{
472fdf
     int ret;
472fdf
     int epoll_ret;
472fdf
     struct epoll_event ev;
472fdf
@@ -526,11 +542,6 @@ static int gpm_send_recv_loop(struct gpm_ctx *gpmctx, char *send_buffer,
472fdf
     int ret;
472fdf
     int retry_count;
472fdf
 
472fdf
-    /* setup timer */
472fdf
-    ret = gpm_timer_setup(gpmctx, RESPONSE_TIMEOUT);
472fdf
-    if (ret)
472fdf
-        return ret;
472fdf
-
472fdf
     for (retry_count = 0; retry_count < MAX_TIMEOUT_RETRY; retry_count++) {
472fdf
         /* send to proxy */
472fdf
         ret = gpm_send_buffer(gpmctx, send_buffer, send_length);
472fdf
@@ -757,9 +768,6 @@ int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res)
472fdf
     }
472fdf
 
472fdf
 done:
472fdf
-    gpm_timer_close(gpmctx);
472fdf
-    gpm_epoll_close(gpmctx);
472fdf
-
472fdf
     if (sockgrab) {
472fdf
         gpm_release_sock(gpmctx);
472fdf
     }