summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2019-09-11 09:13:50 -0400
committerNick Mathewson <nickm@torproject.org>2019-09-11 09:13:50 -0400
commit0891a31ad32d0567fbc8f73a0598925cb543d699 (patch)
tree5ac10a3540a4a931ddc9b3f29aefcbab39d5f040
parent4596ead2fc88e4b1482b0f3bc8ff356daea2337b (diff)
downloadtor-0891a31ad32d0567fbc8f73a0598925cb543d699.tar.gz
tor-0891a31ad32d0567fbc8f73a0598925cb543d699.zip
madvise: tolerate EINVAL and ENOSYS when minherit fails
These errors can occur if we are built on a system with support for madvise(MADV_NOFORK) but then we are run on a system whose kernel does not support that flag. If the error is something that we don't tolerate at all, we now log it before crashing. Fixes bug 31696. I am calling this a bugfix on 0.4.1.1-alpha, where we actually started using the map_anon code. This is similar to, but not the same as, the fix for #31570.
-rw-r--r--changes/bug316965
-rw-r--r--src/lib/malloc/map_anon.c24
2 files changed, 26 insertions, 3 deletions
diff --git a/changes/bug31696 b/changes/bug31696
new file mode 100644
index 0000000000..b9d6c4130c
--- /dev/null
+++ b/changes/bug31696
@@ -0,0 +1,5 @@
+ o Major bugfixes (crash, Linux):
+ - Tolerate systems (including some Linux installations) where madvise
+ and/or MADV_DONTFORK are available at build-time, but not at run time.
+ Previously, these systems would notice a failed syscall and abort.
+ Fixes bug 31696; bugfix on 0.4.1.1-alpha.
diff --git a/src/lib/malloc/map_anon.c b/src/lib/malloc/map_anon.c
index 0f6a4150c7..08b754540e 100644
--- a/src/lib/malloc/map_anon.c
+++ b/src/lib/malloc/map_anon.c
@@ -27,6 +27,9 @@
#include <windows.h>
#endif
+#include <string.h>
+#include <errno.h>
+
/**
* Macro to get the high bytes of a size_t, if there are high bytes.
* Windows needs this; other operating systems define a size_t that does
@@ -136,18 +139,33 @@ noinherit_mem(void *mem, size_t sz, inherit_res_t *inherit_result_out)
return 0;
}
#endif /* defined(FLAG_ZERO) */
+
#ifdef FLAG_NOINHERIT
int r2 = MINHERIT(mem, sz, FLAG_NOINHERIT);
if (r2 == 0) {
*inherit_result_out = INHERIT_RES_DROP;
+ return 0;
}
- return r2;
-#else /* !(defined(FLAG_NOINHERIT)) */
+#endif /* defined(FLAG_NOINHERIT) */
+
+#if defined(FLAG_ZERO) || defined(FLAG_NOINHERIT)
+ /* At least one operation was tried, and neither succeeded. */
+
+ if (errno == ENOSYS || errno == EINVAL) {
+ /* Syscall not supported, or flag not supported. */
+ return 0;
+ } else {
+ tor_log_err_sigsafe("Unexpected error from minherit: ",
+ strerror(errno),
+ NULL);
+ return -1;
+ }
+#else
(void)inherit_result_out;
(void)mem;
(void)sz;
return 0;
-#endif /* defined(FLAG_NOINHERIT) */
+#endif
}
/**