Summary: | sinl() stack corruption from crafted input (CVE-2020-10029) | ||
---|---|---|---|
Product: | glibc | Reporter: | Guido Vranken <guidovranken> |
Component: | math | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | RESOLVED FIXED | ||
Severity: | normal | CC: | carnil, dominik.b.czarnota+bugzilla, fweimer, huzaifas |
Priority: | P2 | Flags: | fweimer:
security+
|
Version: | unspecified | ||
Target Milestone: | 2.32 | ||
See Also: | https://sourceware.org/bugzilla/show_bug.cgi?id=4586 | ||
Host: | Target: | ||
Build: | Last reconfirmed: |
Description
Guido Vranken
2020-01-31 07:57:16 UTC
This is a pseudo-zero. Bug 4586 (relating to handling of such values in printf) was marked INVALID, but did get fixed at some point, and I think we now consider such values should not cause a buffer overrun, although they need not be consistently handled like any particular valid floating-point representation. So we should make sure __kernel_rem_pio2 only gets called with arguments where the high significand bit is set as it probably expects, even for pseudo-zero and pseudo-normal long double arguments to the original function. The master branch has been updated by Joseph Myers <jsm28@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=9333498794cde1d5cca518badf79533a24114b6f commit 9333498794cde1d5cca518badf79533a24114b6f Author: Joseph Myers <joseph@codesourcery.com> Date: Wed Feb 12 23:31:56 2020 +0000 Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487). Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero argument (an representation where all the significand bits, including the explicit high bit, are zero, but the exponent is not zero, which is not a valid representation for the long double type). Although this is not a valid long double representation, existing practice in this area (see bug 4586, originally marked invalid but subsequently fixed) is that we still seek to avoid invalid memory accesses as a result, in case of programs that treat arbitrary binary data as long double representations, although the invalid representations of the ldbl-96 format do not need to be consistently handled the same as any particular valid representation. This patch makes the range reduction detect pseudo-zero and unnormal representations that would otherwise go to __kernel_rem_pio2, and returns a NaN for them instead of continuing with the range reduction process. (Pseudo-zero and unnormal representations whose unbiased exponent is less than -1 have already been safely returned from the function before this point without going through the rest of range reduction.) Pseudo-zero representations would previously result in the value passed to __kernel_rem_pio2 being all-zero, which is definitely unsafe; unnormal representations would previously result in a value passed whose high bit is zero, which might well be unsafe since that is not a form of input expected by __kernel_rem_pio2. Tested for x86_64. Fixed for 2.32. The master branch has been updated by Florian Weimer <fw@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c10acd40262486dac597001aecc20ad9d3bd0e4a commit c10acd40262486dac597001aecc20ad9d3bd0e4a Author: Florian Weimer <fweimer@redhat.com> Date: Thu Feb 13 17:01:15 2020 +0100 math/test-sinl-pseudo: Use stack protector only if available This fixes commit 9333498794cde1d5cca518bad ("Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487)."). __ieee754_rem_pio2l is used by cosl, sinl, sincosl, and tanl. The release/2.29/master branch has been updated by Patricia Franklin <patsy@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=0474cd5de60448f31d7b872805257092faa626e4 commit 0474cd5de60448f31d7b872805257092faa626e4 Author: Joseph Myers <joseph@codesourcery.com> Date: Wed Feb 12 23:31:56 2020 +0000 Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487). Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero argument (an representation where all the significand bits, including the explicit high bit, are zero, but the exponent is not zero, which is not a valid representation for the long double type). Although this is not a valid long double representation, existing practice in this area (see bug 4586, originally marked invalid but subsequently fixed) is that we still seek to avoid invalid memory accesses as a result, in case of programs that treat arbitrary binary data as long double representations, although the invalid representations of the ldbl-96 format do not need to be consistently handled the same as any particular valid representation. This patch makes the range reduction detect pseudo-zero and unnormal representations that would otherwise go to __kernel_rem_pio2, and returns a NaN for them instead of continuing with the range reduction process. (Pseudo-zero and unnormal representations whose unbiased exponent is less than -1 have already been safely returned from the function before this point without going through the rest of range reduction.) Pseudo-zero representations would previously result in the value passed to __kernel_rem_pio2 being all-zero, which is definitely unsafe; unnormal representations would previously result in a value passed whose high bit is zero, which might well be unsafe since that is not a form of input expected by __kernel_rem_pio2. Tested for x86_64. (cherry picked from commit 9333498794cde1d5cca518badf79533a24114b6f) The release/2.29/master branch has been updated by Patricia Franklin <patsy@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=8e5d591b101d7d8a4628522f1e5ec24b6dfa731b commit 8e5d591b101d7d8a4628522f1e5ec24b6dfa731b Author: Florian Weimer <fweimer@redhat.com> Date: Thu Feb 13 17:01:15 2020 +0100 math/test-sinl-pseudo: Use stack protector only if available This fixes commit 9333498794cde1d5cca518bad ("Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487)."). (cherry picked from commit c10acd40262486dac597001aecc20ad9d3bd0e4a) Looking at the way crash is caused via pseudo-zero numbers and after running the poc through gdb, it seems like on systems in which glibc is not compiled with -fstack-protector-all, (which means the vuln function is not protected by stack-canaries), all that can be achieved is overwrite the stack and the return address with 0's. This can only cause a crash and jumping any other location seems very difficult to achieve if not impossible. (In reply to Guido Vranken from comment #0) > This has been tested on x64 Linux with both the Ubuntu glibc and the > latest git glibc. Btw since Ubuntu 18.04 and 20.04 both seems patched as of today, if anyone wants to play with this, it can be reproduced on e.g. gcc:9.3 docker image (https://hub.docker.com/layers/gcc/library/gcc/9.3/images/sha256-dd7c100e12ddbf4178f5cd524a869fa54f453d35bf1b5f287ec6b70e3230c2e4?context=explore), or by using the following docker image (https://hub.docker.com/layers/disconnect3d/repro-cve-2020-10029/latest/images/sha256-0d7cf62eee140c9a0039945f8fe2ff3c53b7670b663cb67feef57878ab92ee06?context=explore) and command where I compiled the example in the cve-2020-10029 directory: docker run --rm -it --cap-drop=ALL --net=none disconnect3d/repro-cve-2020-10029 /cve-2020-10029/a.out The release/2.27/master branch has been updated by Dmitry Levin <ldv@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=59420258afaf73dc8fab63ce186bac792613fe08 commit 59420258afaf73dc8fab63ce186bac792613fe08 Author: Joseph Myers <joseph@codesourcery.com> Date: Wed Feb 12 23:31:56 2020 +0000 Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487). Bug 25487 reports stack corruption in ldbl-96 sinl on a pseudo-zero argument (an representation where all the significand bits, including the explicit high bit, are zero, but the exponent is not zero, which is not a valid representation for the long double type). Although this is not a valid long double representation, existing practice in this area (see bug 4586, originally marked invalid but subsequently fixed) is that we still seek to avoid invalid memory accesses as a result, in case of programs that treat arbitrary binary data as long double representations, although the invalid representations of the ldbl-96 format do not need to be consistently handled the same as any particular valid representation. This patch makes the range reduction detect pseudo-zero and unnormal representations that would otherwise go to __kernel_rem_pio2, and returns a NaN for them instead of continuing with the range reduction process. (Pseudo-zero and unnormal representations whose unbiased exponent is less than -1 have already been safely returned from the function before this point without going through the rest of range reduction.) Pseudo-zero representations would previously result in the value passed to __kernel_rem_pio2 being all-zero, which is definitely unsafe; unnormal representations would previously result in a value passed whose high bit is zero, which might well be unsafe since that is not a form of input expected by __kernel_rem_pio2. Tested for x86_64. (cherry picked from commit 9333498794cde1d5cca518badf79533a24114b6f) |