Blob Blame History Raw
From 27ae6c5b8b37a8086800cd1a4edbb01a7fddfad6 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Thu, 21 Nov 2013 11:59:40 -0500
Subject: [PATCH 1/2] Add Thread-safe implementation of strerror()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Unfortunately strerror() is not thread safe so we have to juggle with
strerror_r() which is a can of worms as 2 incompatible implementations
are available depending on what is defined at compile time.

Try to do something sane.

https://fedorahosted.org/gss-proxy/ticket/111

Reviewed-by: Günther Deschner <gdeschner@redhat.com>
---
 proxy/src/gp_common.h |  3 +++
 proxy/src/gp_util.c   | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/proxy/src/gp_common.h b/proxy/src/gp_common.h
index b5c525f..f2b8c3e 100644
--- a/proxy/src/gp_common.h
+++ b/proxy/src/gp_common.h
@@ -69,6 +69,9 @@ bool gp_same(const char *a, const char *b);
 bool gp_boolean_is_true(const char *s);
 char *gp_getenv(const char *name);
 
+/* NOTE: read the note in gp_util.c before using gp_strerror() */
+char *gp_strerror(int errnum);
+
 #include "rpcgen/gss_proxy.h"
 
 union gp_rpc_arg {
diff --git a/proxy/src/gp_util.c b/proxy/src/gp_util.c
index a6c870f..4fbac4e 100644
--- a/proxy/src/gp_util.c
+++ b/proxy/src/gp_util.c
@@ -27,6 +27,8 @@
 #include <stdbool.h>
 #include <string.h>
 #include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
 
 bool gp_same(const char *a, const char *b)
 {
@@ -66,3 +68,60 @@ char *gp_getenv(const char *name)
     return NULL;
 #endif
 }
+
+/* NOTE: because strerror_r() is such a mess with glibc, we need to do some
+ * magic checking to find out what function prototype is being used of the
+ * two incompatible ones, and pray it doesn't change in the future.
+ * On top of that to avoid impacting the current code too much we've got to use
+ * thread-local storage to hold a buffer.
+ * gp_strerror() is basically a thread-safe version of strerror() that can
+ * never fail.
+ */
+const char gp_internal_err[] = "Internal strerror_r() error.";
+#define MAX_GP_STRERROR 1024
+char *gp_strerror(int errnum)
+{
+    static __thread char buf[MAX_GP_STRERROR];
+    int saved_errno = errno;
+
+#if ((_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && !_GNU_SOURCE)
+    /* XSI version */
+    int ret;
+
+    ret = strerror_r(errnum, buf, MAX_GP_STRERROR);
+    if (ret == -1) ret = errno;
+    switch (ret) {
+    case 0:
+        break;
+    case EINVAL:
+        ret = snprintf(buf, MAX_GP_STRERROR,
+                       "Unknown error code: %d", errnum);
+        if (ret > 0) break;
+        /* fallthrough */
+    default:
+        ret = snprintf(buf, MAX_GP_STRERROR,
+                       "Internal error describing error code: %d", errnum);
+        if (ret > 0) break;
+        memset(buf, 0, MAX_GP_STRERROR);
+        strncpy(buf, gp_internal_err, MAX_GP_STRERROR);
+        buf[MAX_GP_STRERROR -1] = '\0';
+    }
+#else
+    /* GNU-specific version */
+    char *ret;
+
+    ret = strerror_r(errnum, buf, MAX_GP_STRERROR);
+    if (ret == NULL) {
+        memset(buf, 0, MAX_GP_STRERROR);
+        strncpy(buf, gp_internal_err, MAX_GP_STRERROR);
+        buf[MAX_GP_STRERROR -1] = '\0';
+    } else if (ret != buf) {
+        memset(buf, 0, MAX_GP_STRERROR);
+        strncpy(buf, ret, MAX_GP_STRERROR);
+        buf[MAX_GP_STRERROR -1] = '\0';
+    }
+#endif
+
+    errno = saved_errno;
+    return buf;
+}
-- 
1.8.3.1


From db8099da53167ca4ebf3b9f5ef0c702ddfe8b366 Mon Sep 17 00:00:00 2001
From: Simo Sorce <simo@redhat.com>
Date: Thu, 21 Nov 2013 12:14:36 -0500
Subject: [PATCH 2/2] Use gp_strerror() everywhere instead of strerror()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

https://fedorahosted.org/gss-proxy/ticket/111

Reviewed-by: Günther Deschner <gdeschner@redhat.com>
---
 proxy/src/client/gpm_init_sec_context.c |  4 ++--
 proxy/src/gp_config.c                   |  2 +-
 proxy/src/gp_config_dinglibs.c          |  4 ++--
 proxy/src/gp_init.c                     | 10 +++++-----
 proxy/src/gp_socket.c                   | 14 +++++++-------
 5 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/proxy/src/client/gpm_init_sec_context.c b/proxy/src/client/gpm_init_sec_context.c
index f6dfe53..bd88055 100644
--- a/proxy/src/client/gpm_init_sec_context.c
+++ b/proxy/src/client/gpm_init_sec_context.c
@@ -90,7 +90,7 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
     /* execute proxy request */
     ret = gpm_make_call(GSSX_INIT_SEC_CONTEXT, &uarg, &ures);
     if (ret) {
-        gpm_save_internal_status(ret, strerror(ret));
+        gpm_save_internal_status(ret, gp_strerror(ret));
         goto done;
     }
 
@@ -114,7 +114,7 @@ OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status,
     if (res->output_token) {
         ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf);
         if (ret) {
-            gpm_save_internal_status(ret, strerror(ret));
+            gpm_save_internal_status(ret, gp_strerror(ret));
             goto done;
         }
     }
diff --git a/proxy/src/gp_config.c b/proxy/src/gp_config.c
index 63f264e..2fc4a6f 100644
--- a/proxy/src/gp_config.c
+++ b/proxy/src/gp_config.c
@@ -464,7 +464,7 @@ int load_config(struct gp_config *cfg)
 
 done:
     if (ret != 0) {
-        GPERROR("Error reading configuration %d: %s", ret, strerror(ret));
+        GPERROR("Error reading configuration %d: %s", ret, gp_strerror(ret));
     }
     gp_config_close(ctx);
     safefree(ctx);
diff --git a/proxy/src/gp_config_dinglibs.c b/proxy/src/gp_config_dinglibs.c
index 8716b91..515b951 100644
--- a/proxy/src/gp_config_dinglibs.c
+++ b/proxy/src/gp_config_dinglibs.c
@@ -238,7 +238,7 @@ int gp_dinglibs_init(const char *config_file,
                                &file_ctx);
     if (ret) {
         GPDEBUG("Failed to open config file: %d (%s)\n",
-            ret, strerror(ret));
+            ret, gp_strerror(ret));
         ini_config_destroy(ini_config);
         return ret;
     }
@@ -255,7 +255,7 @@ int gp_dinglibs_init(const char *config_file,
         char **errors = NULL;
         /* we had a parsing failure */
         GPDEBUG("Failed to parse config file: %d (%s)\n",
-            ret, strerror(ret));
+            ret, gp_strerror(ret));
         if (ini_config_error_count(ini_config)) {
             ini_config_get_errors(ini_config, &errors);
             if (errors) {
diff --git a/proxy/src/gp_init.c b/proxy/src/gp_init.c
index 92c0a47..7e29c59 100644
--- a/proxy/src/gp_init.c
+++ b/proxy/src/gp_init.c
@@ -158,7 +158,7 @@ void init_proc_nfsd(struct gp_config *cfg)
         ret = errno;
         GPDEBUG("Failed to open %s: %d (%s)\n",
                 LINUX_PROC_USE_GSS_PROXY_FILE,
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
         return;
     }
 
@@ -167,7 +167,7 @@ void init_proc_nfsd(struct gp_config *cfg)
         ret = errno;
         GPDEBUG("Failed to write to %s: %d (%s)\n",
                 LINUX_PROC_USE_GSS_PROXY_FILE,
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
     }
 
     ret = close(fd);
@@ -175,7 +175,7 @@ void init_proc_nfsd(struct gp_config *cfg)
         ret = errno;
         GPDEBUG("Failed to close %s: %d (%s)\n",
                 LINUX_PROC_USE_GSS_PROXY_FILE,
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
     }
 }
 
@@ -191,7 +191,7 @@ void write_pid(void)
     if (!f) {
         ret = errno;
         GPDEBUG("Failed to open %s: %d (%s)\n",
-                GP_PID_FILE, ret, strerror(ret));
+                GP_PID_FILE, ret, gp_strerror(ret));
         return;
     }
 
@@ -204,6 +204,6 @@ void write_pid(void)
     if (ret != 0) {
         ret = errno;
         GPDEBUG("Failed to close %s: %d (%s)\n",
-                GP_PID_FILE, ret, strerror(ret));
+                GP_PID_FILE, ret, gp_strerror(ret));
     }
 }
diff --git a/proxy/src/gp_socket.c b/proxy/src/gp_socket.c
index b1851a2..3e8afc5 100644
--- a/proxy/src/gp_socket.c
+++ b/proxy/src/gp_socket.c
@@ -184,7 +184,7 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx,
     fd = socket(AF_UNIX, SOCK_STREAM, 0);
     if (fd == -1) {
         ret = errno;
-        GPDEBUG("Failed to init socket! (%d: %s)\n", ret, strerror(ret));
+        GPDEBUG("Failed to init socket! (%d: %s)\n", ret, gp_strerror(ret));
         goto done;
     }
 
@@ -192,14 +192,14 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx,
     if (ret == -1) {
         ret = errno;
         GPDEBUG("Failed to bind socket %s! (%d: %s)\n", addr.sun_path,
-            ret, strerror(ret));
+            ret, gp_strerror(ret));
         goto done;
     }
 
     ret = listen(fd, 10);
     if (ret == -1) {
         ret = errno;
-        GPDEBUG("Failed to listen! (%d: %s)\n", ret, strerror(ret));
+        GPDEBUG("Failed to listen! (%d: %s)\n", ret, gp_strerror(ret));
         goto done;
     }
 
@@ -218,7 +218,7 @@ struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx,
 done:
     if (ret) {
         GPERROR("Failed to create Unix Socket! (%d:%s)",
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
         if (fd != -1) {
             close(fd);
             fd = -1;
@@ -245,7 +245,7 @@ static int get_peercred(int fd, struct gp_conn *conn)
     if (ret == -1) {
         ret = errno;
         GPDEBUG("Failed to get SO_PEERCRED options! (%d:%s)\n",
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
         return ret;
     }
     if (len != sizeof(struct ucred)) {
@@ -262,7 +262,7 @@ static int get_peercred(int fd, struct gp_conn *conn)
     } else {
         ret = errno;
         GPDEBUG("Failed to get peer's SELinux context (%d:%s)\n",
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
         /* consider thisnot fatal, selinux may be disabled */
     }
 
@@ -579,7 +579,7 @@ void accept_sock_conn(verto_ctx *vctx, verto_ev *ev)
 done:
     if (ret) {
         GPERROR("Error connecting client: (%d:%s)",
-                ret, strerror(ret));
+                ret, gp_strerror(ret));
         gp_conn_free(conn);
     }
 }
-- 
1.8.3.1