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

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