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

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