[gcr] gcr: Fix failure case in gcr_secure_memory_try_realloc()



commit 9d66118bf1b8618c62f7dcb27f0f16f49d2ad613
Author: Philip Withnall <philip tecnocode co uk>
Date:   Tue Dec 6 01:07:55 2016 +0000

    gcr: Fix failure case in gcr_secure_memory_try_realloc()
    
    try_realloc() is explicitly documented as returning NULL in the failure
    case, so remove an assertion that it can never happen. Similarly for
    try_alloc().
    
    This case can be hit if an application tries to allocate more than the
    process’ RLIMIT_MEMLOCK limit (and the process is not privileged). This
    limit is typically 64KiB, so not astronomical.
    
    Add a test case.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=775685

 gcr/gcr-secure-memory.c  |    3 +-
 gcr/test-secure-memory.c |   77 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+), 2 deletions(-)
---
diff --git a/gcr/gcr-secure-memory.c b/gcr/gcr-secure-memory.c
index f1668e9..c7651f5 100644
--- a/gcr/gcr-secure-memory.c
+++ b/gcr/gcr-secure-memory.c
@@ -178,8 +178,7 @@ gcr_secure_memory_try_realloc (gpointer memory,
        new_memory = egg_secure_realloc_full ("gcr-secure-memory", memory,
                                              size, 0);
 
-       g_assert (new_memory != NULL);
-
+       /* Might be NULL if reallocation failed. */
        return new_memory;
 }
 
diff --git a/gcr/test-secure-memory.c b/gcr/test-secure-memory.c
index 812f213..f1a7a1f 100644
--- a/gcr/test-secure-memory.c
+++ b/gcr/test-secure-memory.c
@@ -27,9 +27,11 @@
 
 #include <glib.h>
 
+#include <errno.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <sys/resource.h>
 
 #define IS_ZERO -1
 
@@ -46,6 +48,32 @@ find_non_zero (gpointer mem, gsize len)
        return -1;
 }
 
+extern int egg_secure_warnings;
+
+static gsize
+get_rlimit_memlock (void)
+{
+       struct rlimit memlock;
+
+       if (getrlimit (RLIMIT_MEMLOCK, &memlock) != 0)
+               g_error ("getrlimit() failed: %s", strerror (errno));
+
+       /* Check that the limit is finite, and that if the caller increases its
+        * size by one (to get the first invalid allocation size), things won’t
+        * explode. */
+       if (memlock.rlim_cur == RLIM_INFINITY ||
+           memlock.rlim_cur >= G_MAXSIZE - 1) {
+               /* Try reducing the limit to 64KiB. */
+               memlock.rlim_cur = MIN (64 * 1024, memlock.rlim_max);
+               if (setrlimit (RLIMIT_MEMLOCK, &memlock) != 0) {
+                       g_test_skip ("setrlimit() failed");
+                       return 0;
+               }
+       }
+
+       return memlock.rlim_cur;
+}
+
 static void
 test_alloc_free (void)
 {
@@ -89,6 +117,27 @@ test_alloc_two (void)
        gcr_secure_memory_free (p);
 }
 
+/* Test alloc() with an allocation larger than RLIMIT_MEMLOCK, which should
+ * fail. */
+static void
+test_alloc_oversized (void)
+{
+       gsize limit;
+       gpointer mem;
+
+       limit = get_rlimit_memlock ();
+       if (limit == 0)
+               return;
+
+       /* Try the allocation. */
+       egg_secure_warnings = 0;
+
+       mem = gcr_secure_memory_try_alloc (limit + 1);
+       g_assert_null (mem);
+
+       egg_secure_warnings = 1;
+}
+
 static void
 test_realloc (void)
 {
@@ -133,6 +182,32 @@ test_realloc_across (void)
        gcr_secure_memory_free (p2);
 }
 
+/* Test realloc() with an allocation larger than RLIMIT_MEMLOCK, which should
+ * fail. */
+static void
+test_realloc_oversized (void)
+{
+       gsize limit;
+       gpointer mem, new_mem;
+
+       limit = get_rlimit_memlock ();
+       if (limit == 0)
+               return;
+
+       /* Try the allocation. */
+       mem = gcr_secure_memory_alloc (64);
+       g_assert_nonnull (mem);
+
+       egg_secure_warnings = 0;
+
+       new_mem = gcr_secure_memory_try_realloc (mem, limit + 1);
+       g_assert_null (new_mem);
+
+       egg_secure_warnings = 1;
+
+       gcr_secure_memory_free (mem);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -141,8 +216,10 @@ main (int argc, char **argv)
 
        g_test_add_func ("/memory/alloc-free", test_alloc_free);
        g_test_add_func ("/memory/alloc-two", test_alloc_two);
+       g_test_add_func ("/memory/alloc-oversized", test_alloc_oversized);
        g_test_add_func ("/memory/realloc", test_realloc);
        g_test_add_func ("/memory/realloc-across", test_realloc_across);
+       g_test_add_func ("/memory/realloc-oversized", test_realloc_oversized);
 
        return g_test_run ();
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]