Blame SOURCES/0001-tabrmd-options-fix-memory-leak.patch

1a1093
From ff90674fd801dd369231a20c47ebef0d08402e9e Mon Sep 17 00:00:00 2001
1a1093
From: William Roberts <william.c.roberts@intel.com>
1a1093
Date: Tue, 12 Jan 2021 14:12:48 -0600
1a1093
Subject: [PATCH 1/6] tabrmd-options: fix memory leak
1a1093
1a1093
The tabrmd_options_t structure is initialized with static char *
1a1093
strings. These strings can be replaced by g_option_context_parse().
1a1093
However, g_option_context_parse() replaces the string with allocated
1a1093
memory and thus needs a call to g_free. Either one would need to keep
1a1093
track if glib allocated the string and conditionally free it, or just
1a1093
set all the strings to glib allocated strings. This patch takes the
1a1093
approach of always allocating the option strings.
1a1093
1a1093
Fixes leaks like:
1a1093
==2677142==ERROR: LeakSanitizer: detected memory leaks
1a1093
1a1093
Direct leak of 9 byte(s) in 1 object(s) allocated from:
1a1093
    #8 0x7fbd1acd5da1 in g_option_context_parse (/usr/lib/x86_64-linux-gnu/libglib-2.0.so.0+0x5eda1)
1a1093
    #9 0x4cc438 in parse_opts /home/wcrobert/workspace/tpm2-abrmd/src/tabrmd-options.c:103:10
1a1093
    #10 0x4c7ffe in main /home/wcrobert/workspace/tpm2-abrmd/src/tabrmd.c:41:10
1a1093
    #11 0x7fbd1a8770b2 in __libc_start_main /build/glibc-ZN95T4/glibc-2.31/csu/../csu/libc-start.c:308:16
1a1093
    #12 0x42004d in _start (/home/wcrobert/workspace/tpm2-abrmd/src/tpm2-abrmd+0x42004d)
1a1093
1a1093
Signed-off-by: William Roberts <william.c.roberts@intel.com>
1a1093
---
1a1093
 src/tabrmd-init.c    |  2 ++
1a1093
 src/tabrmd-options.c | 53 +++++++++++++++++++++++++++++++++++++++-----
1a1093
 src/tabrmd-options.h | 11 +++++----
1a1093
 src/tabrmd.c         |  4 +++-
1a1093
 4 files changed, 59 insertions(+), 11 deletions(-)
1a1093
1a1093
diff --git a/src/tabrmd-init.c b/src/tabrmd-init.c
1a1093
index 2ad7539..58e0103 100644
1a1093
--- a/src/tabrmd-init.c
1a1093
+++ b/src/tabrmd-init.c
1a1093
@@ -99,6 +99,8 @@ gmain_data_cleanup (gmain_data_t *data)
1a1093
     if (data->loop != NULL) {
1a1093
         main_loop_quit (data->loop);
1a1093
     }
1a1093
+
1a1093
+    tabrmd_options_free(&data->options);
1a1093
 }
1a1093
 /*
1a1093
  * This function initializes and configures all of the long-lived objects
1a1093
diff --git a/src/tabrmd-options.c b/src/tabrmd-options.c
1a1093
index 0dd7b87..22f249c 100644
1a1093
--- a/src/tabrmd-options.c
1a1093
+++ b/src/tabrmd-options.c
1a1093
@@ -16,6 +16,12 @@
1a1093
 #define G_OPTION_FLAG_NONE 0
1a1093
 #endif
1a1093
 
1a1093
+#define SET_STR_IF_NULL(var, value) \
1a1093
+    do { \
1a1093
+        var = var == NULL ? g_strdup(value) : var; \
1a1093
+        g_assert(var); \
1a1093
+    } while(0)
1a1093
+
1a1093
 /*
1a1093
  * This is a GOptionArgFunc callback invoked from the GOption processor from
1a1093
  * the parse_opts function below. It will be called when the daemon is
1a1093
@@ -36,6 +42,22 @@ show_version (const gchar  *option_name,
1a1093
     g_print ("tpm2-abrmd version %s\n", VERSION);
1a1093
     exit (0);
1a1093
 }
1a1093
+
1a1093
+/**
1a1093
+ * Frees internal memory associated with a tabrmd_options_t struct.
1a1093
+ * @param opts
1a1093
+ *  The options to free, note it doesn't free opts itself.
1a1093
+ */
1a1093
+void
1a1093
+tabrmd_options_free(tabrmd_options_t *opts)
1a1093
+{
1a1093
+    g_assert(opts);
1a1093
+
1a1093
+    g_clear_pointer(&opts->dbus_name, g_free);
1a1093
+    g_clear_pointer(&opts->prng_seed_file, g_free);
1a1093
+    g_clear_pointer(&opts->tcti_conf, g_free);
1a1093
+}
1a1093
+
1a1093
 /**
1a1093
  * This function parses the parameter argument vector and populates the
1a1093
  * parameter 'options' structure with data needed to configure the tabrmd.
1a1093
@@ -51,7 +73,7 @@ parse_opts (gint argc,
1a1093
             gchar *argv[],
1a1093
             tabrmd_options_t *options)
1a1093
 {
1a1093
-    gchar *logger_name = "stdout";
1a1093
+    gchar *logger_name = NULL;
1a1093
     GOptionContext *ctx;
1a1093
     GError *err = NULL;
1a1093
     gboolean session_bus = FALSE;
1a1093
@@ -105,33 +127,52 @@ parse_opts (gint argc,
1a1093
         return FALSE;
1a1093
     }
1a1093
     g_option_context_free (ctx);
1a1093
+
1a1093
+    /*
1a1093
+     * Set unset STRING options to defaults, we do this so we can free allocated
1a1093
+     * string options with gfree, having a mix of const and allocated ptr's
1a1093
+     * causes leaks
1a1093
+     */
1a1093
+    SET_STR_IF_NULL(options->dbus_name, TABRMD_DBUS_NAME_DEFAULT);
1a1093
+    SET_STR_IF_NULL(options->prng_seed_file, TABRMD_ENTROPY_SRC_DEFAULT);
1a1093
+    SET_STR_IF_NULL(options->tcti_conf, TABRMD_TCTI_CONF_DEFAULT);
1a1093
+    SET_STR_IF_NULL(logger_name, "stdout");
1a1093
+
1a1093
     /* select the bus type, default to G_BUS_TYPE_SESSION */
1a1093
     options->bus = session_bus ? G_BUS_TYPE_SESSION : G_BUS_TYPE_SYSTEM;
1a1093
-    if (set_logger (logger_name) == -1) {
1a1093
+    gint ret = set_logger (logger_name);
1a1093
+    if (ret == -1) {
1a1093
         g_critical ("Unknown logger: %s, try --help\n", logger_name);
1a1093
-        return FALSE;
1a1093
+        g_free(logger_name);
1a1093
+        goto error;
1a1093
     }
1a1093
+    g_free(logger_name);
1a1093
+
1a1093
     if (options->max_connections < 1 ||
1a1093
         options->max_connections > TABRMD_CONNECTION_MAX)
1a1093
     {
1a1093
         g_critical ("maximum number of connections must be between 1 "
1a1093
                     "and %d", TABRMD_CONNECTION_MAX);
1a1093
-        return FALSE;
1a1093
+        goto error;
1a1093
     }
1a1093
     if (options->max_sessions < 1 ||
1a1093
         options->max_sessions > TABRMD_SESSIONS_MAX_DEFAULT)
1a1093
     {
1a1093
         g_critical ("max-sessions must be between 1 and %d",
1a1093
                     TABRMD_SESSIONS_MAX_DEFAULT);
1a1093
-        return FALSE;
1a1093
+        goto error;
1a1093
     }
1a1093
     if (options->max_transients < 1 ||
1a1093
         options->max_transients > TABRMD_TRANSIENT_MAX)
1a1093
     {
1a1093
         g_critical ("max-trans-obj parameter must be between 1 and %d",
1a1093
                     TABRMD_TRANSIENT_MAX);
1a1093
-        return FALSE;
1a1093
+        goto error;
1a1093
     }
1a1093
     g_warning ("tcti_conf after: \"%s\"", options->tcti_conf);
1a1093
     return TRUE;
1a1093
+
1a1093
+error:
1a1093
+    tabrmd_options_free(options);
1a1093
+    return FALSE;
1a1093
 }
1a1093
diff --git a/src/tabrmd-options.h b/src/tabrmd-options.h
1a1093
index 4994920..d6bcfe9 100644
1a1093
--- a/src/tabrmd-options.h
1a1093
+++ b/src/tabrmd-options.h
1a1093
@@ -15,10 +15,10 @@
1a1093
     .max_connections = TABRMD_CONNECTIONS_MAX_DEFAULT, \
1a1093
     .max_transients = TABRMD_TRANSIENT_MAX_DEFAULT, \
1a1093
     .max_sessions = TABRMD_SESSIONS_MAX_DEFAULT, \
1a1093
-    .dbus_name = TABRMD_DBUS_NAME_DEFAULT, \
1a1093
-    .prng_seed_file = TABRMD_ENTROPY_SRC_DEFAULT, \
1a1093
+    .dbus_name = NULL, \
1a1093
+    .prng_seed_file = NULL, \
1a1093
     .allow_root = FALSE, \
1a1093
-    .tcti_conf = TABRMD_TCTI_CONF_DEFAULT, \
1a1093
+    .tcti_conf = NULL, \
1a1093
 }
1a1093
 
1a1093
 typedef struct tabrmd_options {
1a1093
@@ -28,7 +28,7 @@ typedef struct tabrmd_options {
1a1093
     guint           max_transients;
1a1093
     guint           max_sessions;
1a1093
     gchar          *dbus_name;
1a1093
-    const gchar    *prng_seed_file;
1a1093
+    gchar          *prng_seed_file;
1a1093
     gboolean        allow_root;
1a1093
     gchar          *tcti_conf;
1a1093
 } tabrmd_options_t;
1a1093
@@ -38,4 +38,7 @@ parse_opts (gint argc,
1a1093
             gchar *argv[],
1a1093
             tabrmd_options_t *options);
1a1093
 
1a1093
+void
1a1093
+tabrmd_options_free(tabrmd_options_t *opts);
1a1093
+
1a1093
 #endif /* TABRMD_OPTIONS_H */
1a1093
diff --git a/src/tabrmd.c b/src/tabrmd.c
1a1093
index 7c93e90..e015de3 100644
1a1093
--- a/src/tabrmd.c
1a1093
+++ b/src/tabrmd.c
1a1093
@@ -43,7 +43,8 @@ main (int argc, char *argv[])
1a1093
     }
1a1093
     if (geteuid() == 0 && ! gmain_data.options.allow_root) {
1a1093
         g_print ("Refusing to run as root. Pass --allow-root if you know what you are doing.\n");
1a1093
-        return 1;
1a1093
+        ret = 1;
1a1093
+        goto out;
1a1093
     }
1a1093
 
1a1093
     g_mutex_init (&gmain_data.init_mutex);
1a1093
@@ -63,6 +64,7 @@ main (int argc, char *argv[])
1a1093
     if (ret == 0 && gmain_data.ipc_disconnected) {
1a1093
         ret = EX_IOERR;
1a1093
     }
1a1093
+out:
1a1093
     gmain_data_cleanup (&gmain_data);
1a1093
     return ret;
1a1093
 }
1a1093
-- 
1a1093
2.34.3
1a1093