Add workaround to make ubsan and ps_status.c compatible
authorAndres Freund <andres@anarazel.de>
Mon, 21 Nov 2022 21:54:54 +0000 (13:54 -0800)
committerAndres Freund <andres@anarazel.de>
Mon, 21 Nov 2022 21:56:23 +0000 (13:56 -0800)
At least on linux, set_ps_display() breaks /proc/$pid/environ. The sanitizer's
helper library uses /proc/$pid/environ to implement getenv(), as it wants to
work independent of libc. When just using undefined and alignment sanitizers,
the sanitizer library is only initialized when the first error occurs, by
which time we've often already called set_ps_display(), preventing the
sanitizer libraries from seeing the options.

We can work around that by defining __ubsan_default_options, a weak symbol
libsanitizer uses to get defaults from the application, and return
getenv("UBSAN_OPTIONS"). But only if main already was reached, so that we
don't end up relying on a not-yet-working getenv().

As it's just a function that won't get called when not running a sanitizer, it
doesn't seem necessary to make compilation of the function conditional.

Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/20220323173537.ll7klrglnp4gn2um@alap3.anarazel.de

src/backend/main/main.c

index 67f556b4dd81786058217963b28424fd3ea12da4..37989ba567817b4ff148e45fb30f0aff1a261868 100644 (file)
@@ -43,6 +43,7 @@
 
 
 const char *progname;
+static bool reached_main = false;
 
 
 static void startup_hacks(const char *progname);
@@ -59,6 +60,8 @@ main(int argc, char *argv[])
 {
    bool        do_check_root = true;
 
+   reached_main = true;
+
    /*
     * If supported on the current platform, set up a handler to be called if
     * the backend/postmaster crashes with a fatal signal or exception.
@@ -420,3 +423,30 @@ check_root(const char *progname)
    }
 #endif                         /* WIN32 */
 }
+
+/*
+ * At least on linux, set_ps_display() breaks /proc/$pid/environ. The
+ * sanitizer library uses /proc/$pid/environ to implement getenv() as it wants
+ * to work independent of libc. When just using undefined and alignment
+ * sanitizers, the sanitizer library is only initialized when the first error
+ * occurs, by which time we've often already called set_ps_display(),
+ * preventing the sanitizer libraries from seeing the options.
+ *
+ * We can work around that by defining __ubsan_default_options, a weak symbol
+ * libsanitizer uses to get defaults from the application, and return
+ * getenv("UBSAN_OPTIONS"). But only if main already was reached, so that we
+ * don't end up relying on a not-yet-working getenv().
+ *
+ * As this function won't get called when not running a sanitizer, it doesn't
+ * seem necessary to only compile it conditionally.
+ */
+const char *__ubsan_default_options(void);
+const char *
+__ubsan_default_options(void)
+{
+   /* don't call libc before it's guaranteed to be initialized */
+   if (!reached_main)
+       return "";
+
+   return getenv("UBSAN_OPTIONS");
+}