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

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