forked from pool/redis
Accepting request 1032521 from server:database
OBS-URL: https://build.opensuse.org/request/show/1032521 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/redis?expand=0&rev=84
This commit is contained in:
commit
8648d41f3f
202
cve-2022-3647.patch
Normal file
202
cve-2022-3647.patch
Normal file
@ -0,0 +1,202 @@
|
||||
From 0bf90d944313919eb8e63d3588bf63a367f020a3 Mon Sep 17 00:00:00 2001
|
||||
From: "Meir Shpilraien (Spielrein)" <meir@redis.com>
|
||||
Date: Thu, 29 Sep 2022 08:58:58 +0300
|
||||
Subject: [PATCH] Avoid crash on crash report when a bad function pointer was
|
||||
called (#11298)
|
||||
|
||||
If Redis crashes due to calling an invalid function pointer,
|
||||
the `backtrace` function will try to dereference this invalid pointer
|
||||
which will cause a crash inside the crash report and will kill
|
||||
the processes without having all the crash report information.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
=== REDIS BUG REPORT START: Cut & paste starting from here ===
|
||||
198672:M 19 Sep 2022 18:06:12.936 # Redis 255.255.255 crashed by signal: 11, si_code: 1
|
||||
198672:M 19 Sep 2022 18:06:12.936 # Accessing address: 0x1
|
||||
198672:M 19 Sep 2022 18:06:12.936 # Crashed running the instruction at: 0x1
|
||||
// here the processes is crashing
|
||||
```
|
||||
|
||||
This PR tries to fix this crash be:
|
||||
1. Identify the issue when it happened.
|
||||
2. Replace the invalid pointer with a pointer to some dummy function
|
||||
so that `backtrace` will not crash.
|
||||
|
||||
I identification is done by comparing `eip` to `info->si_addr`, if they
|
||||
are the same we know that the crash happened on the same address it tries to
|
||||
accesses and we can conclude that it tries to call and invalid function pointer.
|
||||
|
||||
To replace the invalid pointer we introduce a new function, `setMcontextEip`,
|
||||
which is very similar to `getMcontextEip` and it knows to set the Eip for the
|
||||
different supported OS's. After printing the trace we retrieve the old `Eip` value.
|
||||
---
|
||||
src/debug.c | 80 ++++++++++++++++++++++++++++++++++++++---------------
|
||||
1 file changed, 58 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/src/debug.c b/src/debug.c
|
||||
index 8cc811be444b..b15ac8780d83 100644
|
||||
--- a/src/debug.c
|
||||
+++ b/src/debug.c
|
||||
@@ -1123,73 +1123,88 @@ void bugReportStart(void) {
|
||||
}
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
-static void *getMcontextEip(ucontext_t *uc) {
|
||||
+
|
||||
+/* Returns the current eip and set it to the given new value (if its not NULL) */
|
||||
+static void* getAndSetMcontextEip(ucontext_t *uc, void *eip) {
|
||||
#define NOT_SUPPORTED() do {\
|
||||
UNUSED(uc);\
|
||||
+ UNUSED(eip);\
|
||||
return NULL;\
|
||||
} while(0)
|
||||
+#define GET_SET_RETURN(target_var, new_val) do {\
|
||||
+ void *old_val = (void*)target_var; \
|
||||
+ if (new_val) { \
|
||||
+ void **temp = (void**)&target_var; \
|
||||
+ *temp = new_val; \
|
||||
+ } \
|
||||
+ return old_val; \
|
||||
+} while(0)
|
||||
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)
|
||||
/* OSX < 10.6 */
|
||||
#if defined(__x86_64__)
|
||||
- return (void*) uc->uc_mcontext->__ss.__rip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext->__ss.__rip, eip);
|
||||
#elif defined(__i386__)
|
||||
- return (void*) uc->uc_mcontext->__ss.__eip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext->__ss.__eip, eip);
|
||||
#else
|
||||
- return (void*) uc->uc_mcontext->__ss.__srr0;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext->__ss.__srr0, eip);
|
||||
#endif
|
||||
#elif defined(__APPLE__) && defined(MAC_OS_X_VERSION_10_6)
|
||||
/* OSX >= 10.6 */
|
||||
#if defined(_STRUCT_X86_THREAD_STATE64) && !defined(__i386__)
|
||||
- return (void*) uc->uc_mcontext->__ss.__rip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext->__ss.__rip, eip);
|
||||
#elif defined(__i386__)
|
||||
- return (void*) uc->uc_mcontext->__ss.__eip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext->__ss.__eip, eip);
|
||||
#else
|
||||
/* OSX ARM64 */
|
||||
- return (void*) arm_thread_state64_get_pc(uc->uc_mcontext->__ss);
|
||||
+ void *old_val = (void*)arm_thread_state64_get_pc(uc->uc_mcontext->__ss);
|
||||
+ if (eip) {
|
||||
+ arm_thread_state64_set_pc_fptr(uc->uc_mcontext->__ss, eip);
|
||||
+ }
|
||||
+ return old_val;
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
/* Linux */
|
||||
#if defined(__i386__) || ((defined(__X86_64__) || defined(__x86_64__)) && defined(__ILP32__))
|
||||
- return (void*) uc->uc_mcontext.gregs[14]; /* Linux 32 */
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.gregs[14], eip);
|
||||
#elif defined(__X86_64__) || defined(__x86_64__)
|
||||
- return (void*) uc->uc_mcontext.gregs[16]; /* Linux 64 */
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.gregs[16], eip);
|
||||
#elif defined(__ia64__) /* Linux IA64 */
|
||||
- return (void*) uc->uc_mcontext.sc_ip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.sc_ip, eip);
|
||||
#elif defined(__arm__) /* Linux ARM */
|
||||
- return (void*) uc->uc_mcontext.arm_pc;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.arm_pc, eip);
|
||||
#elif defined(__aarch64__) /* Linux AArch64 */
|
||||
- return (void*) uc->uc_mcontext.pc;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.pc, eip);
|
||||
#else
|
||||
NOT_SUPPORTED();
|
||||
#endif
|
||||
#elif defined(__FreeBSD__)
|
||||
/* FreeBSD */
|
||||
#if defined(__i386__)
|
||||
- return (void*) uc->uc_mcontext.mc_eip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.mc_eip, eip);
|
||||
#elif defined(__x86_64__)
|
||||
- return (void*) uc->uc_mcontext.mc_rip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.mc_rip, eip);
|
||||
#else
|
||||
NOT_SUPPORTED();
|
||||
#endif
|
||||
#elif defined(__OpenBSD__)
|
||||
/* OpenBSD */
|
||||
#if defined(__i386__)
|
||||
- return (void*) uc->sc_eip;
|
||||
+ GET_SET_RETURN(uc->sc_eip, eip);
|
||||
#elif defined(__x86_64__)
|
||||
- return (void*) uc->sc_rip;
|
||||
+ GET_SET_RETURN(uc->sc_rip, eip);
|
||||
#else
|
||||
NOT_SUPPORTED();
|
||||
#endif
|
||||
#elif defined(__NetBSD__)
|
||||
#if defined(__i386__)
|
||||
- return (void*) uc->uc_mcontext.__gregs[_REG_EIP];
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.__gregs[_REG_EIP], eip);
|
||||
#elif defined(__x86_64__)
|
||||
- return (void*) uc->uc_mcontext.__gregs[_REG_RIP];
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.__gregs[_REG_RIP], eip);
|
||||
#else
|
||||
NOT_SUPPORTED();
|
||||
#endif
|
||||
#elif defined(__DragonFly__)
|
||||
- return (void*) uc->uc_mcontext.mc_rip;
|
||||
+ GET_SET_RETURN(uc->uc_mcontext.mc_rip, eip);
|
||||
#else
|
||||
NOT_SUPPORTED();
|
||||
#endif
|
||||
@@ -1951,6 +1966,10 @@ void dumpCodeAroundEIP(void *eip) {
|
||||
}
|
||||
}
|
||||
|
||||
+void invalidFunctionWasCalled() {}
|
||||
+
|
||||
+typedef void (*invalidFunctionWasCalledType)();
|
||||
+
|
||||
void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
|
||||
UNUSED(secret);
|
||||
UNUSED(info);
|
||||
@@ -1968,13 +1987,30 @@ void sigsegvHandler(int sig, siginfo_t *info, void *secret) {
|
||||
|
||||
#ifdef HAVE_BACKTRACE
|
||||
ucontext_t *uc = (ucontext_t*) secret;
|
||||
- void *eip = getMcontextEip(uc);
|
||||
+ void *eip = getAndSetMcontextEip(uc, NULL);
|
||||
if (eip != NULL) {
|
||||
serverLog(LL_WARNING,
|
||||
"Crashed running the instruction at: %p", eip);
|
||||
}
|
||||
|
||||
- logStackTrace(getMcontextEip(uc), 1);
|
||||
+ if (eip == info->si_addr) {
|
||||
+ /* When eip matches the bad address, it's an indication that we crashed when calling a non-mapped
|
||||
+ * function pointer. In that case the call to backtrace will crash trying to access that address and we
|
||||
+ * won't get a crash report logged. Set it to a valid point to avoid that crash. */
|
||||
+
|
||||
+ /* This trick allow to avoid compiler warning */
|
||||
+ void *ptr;
|
||||
+ invalidFunctionWasCalledType *ptr_ptr = (invalidFunctionWasCalledType*)&ptr;
|
||||
+ *ptr_ptr = invalidFunctionWasCalled;
|
||||
+ getAndSetMcontextEip(uc, ptr);
|
||||
+ }
|
||||
+
|
||||
+ logStackTrace(eip, 1);
|
||||
+
|
||||
+ if (eip == info->si_addr) {
|
||||
+ /* Restore old eip */
|
||||
+ getAndSetMcontextEip(uc, eip);
|
||||
+ }
|
||||
|
||||
logRegisters(uc);
|
||||
#endif
|
||||
@@ -2079,7 +2115,7 @@ void watchdogSignalHandler(int sig, siginfo_t *info, void *secret) {
|
||||
|
||||
serverLogFromHandler(LL_WARNING,"\n--- WATCHDOG TIMER EXPIRED ---");
|
||||
#ifdef HAVE_BACKTRACE
|
||||
- logStackTrace(getMcontextEip(uc), 1);
|
||||
+ logStackTrace(getAndSetMcontextEip(uc, NULL), 1);
|
||||
#else
|
||||
serverLogFromHandler(LL_WARNING,"Sorry: no support for backtrace().");
|
||||
#endif
|
@ -1,3 +1,10 @@
|
||||
-------------------------------------------------------------------
|
||||
Mon Oct 24 14:56:10 UTC 2022 - Danilo Spinella <danilo.spinella@suse.com>
|
||||
|
||||
- Fix CVE-2022-3647, crash in sigsegvHandler debug function
|
||||
(CVE-2022-3647, bsc#1204633)
|
||||
* cve-2022-3647.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Sep 21 20:36:11 UTC 2022 - Michael Ströder <michael@stroeder.com>
|
||||
|
||||
|
@ -40,6 +40,9 @@ Source10: https://raw.githubusercontent.com/redis/redis-hashes/master/READ
|
||||
Patch0: %{name}-conf.patch
|
||||
Patch3: reproducible.patch
|
||||
Patch4: ppc-atomic.patch
|
||||
# PATCH-FIX-UPSTREAm bsc#1204633 danilo.spinella@suse.com CVE-2022-3647
|
||||
# crash in sigsegvHandler debug function
|
||||
Patch5: cve-2022-3647.patch
|
||||
BuildRequires: jemalloc-devel
|
||||
BuildRequires: libopenssl-devel >= 1.1.1
|
||||
BuildRequires: pkgconfig
|
||||
@ -67,6 +70,7 @@ echo "`grep -F %{name}-%{version}.tar.gz %{SOURCE10} | cut -d' ' -f4` %{SOURCE0
|
||||
%patch0
|
||||
%patch3 -p1
|
||||
%patch4 -p1
|
||||
%patch5 -p1
|
||||
|
||||
%build
|
||||
export HOST=OBS # for reproducible builds
|
||||
|
Loading…
Reference in New Issue
Block a user