diff options
| author | Andreas Wellving <andreas.wellving@enea.com> | 2018-09-12 14:51:53 +0200 |
|---|---|---|
| committer | Dan Andresan <Dan.Andresan@enea.com> | 2018-10-25 15:14:17 +0200 |
| commit | dfb6fefbd0ecb0de2a58f25c90f07682effd0d37 (patch) | |
| tree | 8130aae502169a5a922f5a3e6b4c6f91a8d208a3 | |
| parent | 5b8928cd5f01d83ae27824bb5d411723cabc3108 (diff) | |
| download | meta-el-common-dfb6fefbd0ecb0de2a58f25c90f07682effd0d37.tar.gz | |
glibc: Fix CVEs
CVE: CVE-2017-12133 CVE-2017-16997 CVE-2018-6551
Glibc in the upstream pyro is 2.25.
Reference:
CVE-2017-12133 https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d42eed4a044e5e10dfb885cf9891c2518a72a491
CVE-2017-16997 https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=21c5d14bfb4e08bee86f94fd815535d3be2c3869
CVE-2018-6551 https://sourceware.org/git/?p=glibc.git;a=patch;h=8e448310d74b283c5cd02b9ed7fb997b47bf9b22
Change-Id: I16492f0713f8134cf31597d2f38ab039c277d77c
Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
Signed-off-by: Adrian Mangeac <adrian.mangeac@enea.com>
5 files changed, 726 insertions, 8 deletions
diff --git a/recipes-core/glibc/glibc/CVE-2017-12133-sunrpc-Avoid-use-after-free-read-access-in-clntudp_c.patch b/recipes-core/glibc/glibc/CVE-2017-12133-sunrpc-Avoid-use-after-free-read-access-in-clntudp_c.patch new file mode 100644 index 0000000..8f88096 --- /dev/null +++ b/recipes-core/glibc/glibc/CVE-2017-12133-sunrpc-Avoid-use-after-free-read-access-in-clntudp_c.patch | |||
| @@ -0,0 +1,164 @@ | |||
| 1 | From bd43c78956040a5d419d5034cdddd4b62c5dd53e Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Andreas Wellving <andreas.wellving@enea.com> | ||
| 3 | Date: Mon, 22 Oct 2018 10:37:02 +0200 | ||
| 4 | Subject: [PATCH] sunrpc: Avoid use-after-free read access in clntudp_call [BZ #21115] | ||
| 5 | |||
| 6 | After commit bc779a1a5b3035133024b21e2f339fe4219fb11c | ||
| 7 | (CVE-2016-4429: sunrpc: Do not use alloca in clntudp_call | ||
| 8 | [BZ #20112]), ancillary data is stored on the heap, | ||
| 9 | but it is accessed after it has been freed. | ||
| 10 | |||
| 11 | The test case must be run under a heap debugger such as valgrind | ||
| 12 | to observe the invalid access. A malloc implementation which | ||
| 13 | immediately calls munmap on free would catch this bug as well. | ||
| 14 | |||
| 15 | This patch is for CVE-2017-12133. | ||
| 16 | (cherry picked from commit d42eed4a044e5e10dfb885cf9891c2518a72a491) | ||
| 17 | |||
| 18 | CVE: CVE-2017-12133 | ||
| 19 | Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=d42eed4a044e5e10dfb885cf9891c2518a72a491] | ||
| 20 | |||
| 21 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
| 22 | --- | ||
| 23 | ChangeLog | 8 +++++++ | ||
| 24 | NEWS | 1 + | ||
| 25 | sunrpc/Makefile | 3 ++- | ||
| 26 | sunrpc/clnt_udp.c | 2 +- | ||
| 27 | sunrpc/tst-udp-error.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++ | ||
| 28 | 5 files changed, 74 insertions(+), 2 deletions(-) | ||
| 29 | create mode 100644 sunrpc/tst-udp-error.c | ||
| 30 | |||
| 31 | diff --git a/ChangeLog b/ChangeLog | ||
| 32 | index 48b095b..097ab5c 100644 | ||
| 33 | --- a/ChangeLog | ||
| 34 | +++ b/ChangeLog | ||
| 35 | @@ -1,3 +1,11 @@ | ||
| 36 | +2017-02-27 Florian Weimer <fweimer@redhat.com> | ||
| 37 | + | ||
| 38 | + [BZ #21115] | ||
| 39 | + * sunrpc/clnt_udp.c (clntudp_call): Free ancillary data later. | ||
| 40 | + * sunrpc/Makefile (tests): Add tst-udp-error. | ||
| 41 | + (tst-udp-error): Link against libc.so explicitly. | ||
| 42 | + * sunrpc/tst-udp-error: New file. | ||
| 43 | + | ||
| 44 | 2018-01-18 Arjun Shankar <arjun@redhat.com> | ||
| 45 | |||
| 46 | [BZ #22343] | ||
| 47 | diff --git a/NEWS b/NEWS | ||
| 48 | index 5134f34..4765e1b 100644 | ||
| 49 | --- a/NEWS | ||
| 50 | +++ b/NEWS | ||
| 51 | @@ -376,6 +376,7 @@ The following bugs are resolved with this release: | ||
| 52 | [21081] string: Missing vzeroupper in memset-vec-unaligned-erms.S | ||
| 53 | [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485) | ||
| 54 | [22774] malloc: Integer overflow in malloc (CVE-2018-6551) | ||
| 55 | + [21115] sunrpc: Use-after-free in error path in clntudp_call | ||
| 56 | |||
| 57 | Version 2.24 | ||
| 58 | |||
| 59 | diff --git a/sunrpc/Makefile b/sunrpc/Makefile | ||
| 60 | index 12ec2e7..8b9f25f 100644 | ||
| 61 | --- a/sunrpc/Makefile | ||
| 62 | +++ b/sunrpc/Makefile | ||
| 63 | @@ -93,7 +93,7 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ | ||
| 64 | extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) | ||
| 65 | others += rpcgen | ||
| 66 | |||
| 67 | -tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-xdrmem3 | ||
| 68 | +tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-xdrmem3 tst-udp-error | ||
| 69 | xtests := tst-getmyaddr | ||
| 70 | |||
| 71 | tests-special += $(objpfx)mtrace-tst-xdrmem3.out | ||
| 72 | @@ -163,6 +163,7 @@ $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so | ||
| 73 | $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so | ||
| 74 | $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so | ||
| 75 | (objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so | ||
| 76 | +$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so | ||
| 77 | |||
| 78 | $(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs)) | ||
| 79 | |||
| 80 | diff --git a/sunrpc/clnt_udp.c b/sunrpc/clnt_udp.c | ||
| 81 | index 4d9acb1..1de25cb 100644 | ||
| 82 | --- a/sunrpc/clnt_udp.c | ||
| 83 | +++ b/sunrpc/clnt_udp.c | ||
| 84 | @@ -421,9 +421,9 @@ send_again: | ||
| 85 | cmsg = CMSG_NXTHDR (&msg, cmsg)) | ||
| 86 | if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) | ||
| 87 | { | ||
| 88 | - free (cbuf); | ||
| 89 | e = (struct sock_extended_err *) CMSG_DATA(cmsg); | ||
| 90 | cu->cu_error.re_errno = e->ee_errno; | ||
| 91 | + free (cbuf); | ||
| 92 | return (cu->cu_error.re_status = RPC_CANTRECV); | ||
| 93 | } | ||
| 94 | free (cbuf); | ||
| 95 | diff --git a/sunrpc/tst-udp-error.c b/sunrpc/tst-udp-error.c | ||
| 96 | new file mode 100644 | ||
| 97 | index 0000000..1efc02f | ||
| 98 | --- /dev/null | ||
| 99 | +++ b/sunrpc/tst-udp-error.c | ||
| 100 | @@ -0,0 +1,62 @@ | ||
| 101 | +/* Check for use-after-free in clntudp_call (bug 21115). | ||
| 102 | + Copyright (C) 2017 Free Software Foundation, Inc. | ||
| 103 | + This file is part of the GNU C Library. | ||
| 104 | + | ||
| 105 | + The GNU C Library is free software; you can redistribute it and/or | ||
| 106 | + modify it under the terms of the GNU Lesser General Public | ||
| 107 | + License as published by the Free Software Foundation; either | ||
| 108 | + version 2.1 of the License, or (at your option) any later version. | ||
| 109 | + | ||
| 110 | + The GNU C Library is distributed in the hope that it will be useful, | ||
| 111 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 112 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 113 | + Lesser General Public License for more details. | ||
| 114 | + | ||
| 115 | + You should have received a copy of the GNU Lesser General Public | ||
| 116 | + License along with the GNU C Library; if not, see | ||
| 117 | + <http://www.gnu.org/licenses/>. */ | ||
| 118 | + | ||
| 119 | +#include <netinet/in.h> | ||
| 120 | +#include <rpc/clnt.h> | ||
| 121 | +#include <rpc/svc.h> | ||
| 122 | +#include <support/check.h> | ||
| 123 | +#include <support/namespace.h> | ||
| 124 | +#include <support/xsocket.h> | ||
| 125 | +#include <unistd.h> | ||
| 126 | + | ||
| 127 | +static int | ||
| 128 | +do_test (void) | ||
| 129 | +{ | ||
| 130 | + support_become_root (); | ||
| 131 | + support_enter_network_namespace (); | ||
| 132 | + | ||
| 133 | + /* Obtain a likely-unused port number. */ | ||
| 134 | + struct sockaddr_in sin = | ||
| 135 | + { | ||
| 136 | + .sin_family = AF_INET, | ||
| 137 | + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), | ||
| 138 | + }; | ||
| 139 | + { | ||
| 140 | + int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); | ||
| 141 | + xbind (fd, (struct sockaddr *) &sin, sizeof (sin)); | ||
| 142 | + socklen_t sinlen = sizeof (sin); | ||
| 143 | + xgetsockname (fd, (struct sockaddr *) &sin, &sinlen); | ||
| 144 | + /* Close the socket, so that we will receive an error below. */ | ||
| 145 | + close (fd); | ||
| 146 | + } | ||
| 147 | + | ||
| 148 | + int sock = RPC_ANYSOCK; | ||
| 149 | + CLIENT *clnt = clntudp_create | ||
| 150 | + (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock); | ||
| 151 | + TEST_VERIFY_EXIT (clnt != NULL); | ||
| 152 | + TEST_VERIFY (clnt_call (clnt, 3, | ||
| 153 | + (xdrproc_t) xdr_void, NULL, | ||
| 154 | + (xdrproc_t) xdr_void, NULL, | ||
| 155 | + ((struct timeval) { 3, 0 })) | ||
| 156 | + == RPC_CANTRECV); | ||
| 157 | + clnt_destroy (clnt); | ||
| 158 | + | ||
| 159 | + return 0; | ||
| 160 | +} | ||
| 161 | + | ||
| 162 | +#include <support/test-driver.c> | ||
| 163 | |||
| 164 | |||
diff --git a/recipes-core/glibc/glibc/CVE-2017-16997-Check-for-empty-tokens-before-dynamic-string-tok.patch b/recipes-core/glibc/glibc/CVE-2017-16997-Check-for-empty-tokens-before-dynamic-string-tok.patch new file mode 100644 index 0000000..6401734 --- /dev/null +++ b/recipes-core/glibc/glibc/CVE-2017-16997-Check-for-empty-tokens-before-dynamic-string-tok.patch | |||
| @@ -0,0 +1,150 @@ | |||
| 1 | From 24ee2a5b63d15cf45c43ec598f11fe59878982a8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Andreas Wellving <andreas.wellving@enea.com> | ||
| 3 | Date: Mon, 22 Oct 2018 11:17:18 +0200 | ||
| 4 | Subject: [PATCH] elf: Check for empty tokens before dynamic string token expansion [BZ #22625] | ||
| 5 | |||
| 6 | The fillin_rpath function in elf/dl-load.c loops over each RPATH or | ||
| 7 | RUNPATH tokens and interprets empty tokens as the current directory | ||
| 8 | ("./"). In practice the check for empty token is done *after* the | ||
| 9 | dynamic string token expansion. The expansion process can return an | ||
| 10 | empty string for the $ORIGIN token if __libc_enable_secure is set | ||
| 11 | or if the path of the binary can not be determined (/proc not mounted). | ||
| 12 | |||
| 13 | Fix that by moving the check for empty tokens before the dynamic string | ||
| 14 | token expansion. In addition, check for NULL pointer or empty strings | ||
| 15 | return by expand_dynamic_string_token. | ||
| 16 | |||
| 17 | The above changes highlighted a bug in decompose_rpath, an empty array | ||
| 18 | is represented by the first element being NULL at the fillin_rpath | ||
| 19 | level, but by using a -1 pointer in decompose_rpath and other functions. | ||
| 20 | |||
| 21 | Changelog: | ||
| 22 | [BZ #22625] | ||
| 23 | * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic | ||
| 24 | string token expansion. Check for NULL pointer or empty string possibly | ||
| 25 | returned by expand_dynamic_string_token. | ||
| 26 | (decompose_rpath): Check for empty path after dynamic string | ||
| 27 | token expansion. | ||
| 28 | (cherry picked from commit 3e3c904daef69b8bf7d5cc07f793c9f07c3553ef) | ||
| 29 | |||
| 30 | CVE: CVE-2017-16997 | ||
| 31 | Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=21c5d14bfb4e08bee86f94fd815535d3be2c3869] | ||
| 32 | |||
| 33 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
| 34 | --- | ||
| 35 | ChangeLog | 10 ++++++++++ | ||
| 36 | NEWS | 4 ++++ | ||
| 37 | elf/dl-load.c | 49 +++++++++++++++++++++++++++++++++---------------- | ||
| 38 | 3 files changed, 47 insertions(+), 16 deletions(-) | ||
| 39 | |||
| 40 | diff --git a/ChangeLog b/ChangeLog | ||
| 41 | index a0c2f51..ad380fd 100644 | ||
| 42 | --- a/ChangeLog | ||
| 43 | +++ b/ChangeLog | ||
| 44 | @@ -1,3 +1,13 @@ | ||
| 45 | +2017-12-30 Aurelien Jarno <aurelien@aurel32.net> | ||
| 46 | + Dmitry V. Levin <ldv@altlinux.org> | ||
| 47 | + | ||
| 48 | + [BZ #22625] | ||
| 49 | + * elf/dl-load.c (fillin_rpath): Check for empty tokens before dynamic | ||
| 50 | + string token expansion. Check for NULL pointer or empty string possibly | ||
| 51 | + returned by expand_dynamic_string_token. | ||
| 52 | + (decompose_rpath): Check for empty path after dynamic string | ||
| 53 | + token expansion. | ||
| 54 | + | ||
| 55 | 2017-04-13 Florian Weimer <fweimer@redhat.com> | ||
| 56 | |||
| 57 | [BZ #21361] | ||
| 58 | diff --git a/NEWS b/NEWS | ||
| 59 | index 29e795a..195c06d 100644 | ||
| 60 | --- a/NEWS | ||
| 61 | +++ b/NEWS | ||
| 62 | @@ -214,6 +214,10 @@ Security related changes: | ||
| 63 | * The xdr_bytes and xdr_string routines free the internally allocated buffer | ||
| 64 | if deserialization of the buffer contents fails for any reason. | ||
| 65 | |||
| 66 | + CVE-2017-16997: Incorrect handling of RPATH or RUNPATH containing $ORIGIN | ||
| 67 | + for AT_SECURE or SUID binaries could be used to load libraries from the | ||
| 68 | + current directory. | ||
| 69 | + | ||
| 70 | The following bugs are resolved with this release: | ||
| 71 | |||
| 72 | [4099] stdio: Overly agressive caching by stream i/o functions. | ||
| 73 | diff --git a/elf/dl-load.c b/elf/dl-load.c | ||
| 74 | index a5318f9..bdb4484 100644 | ||
| 75 | --- a/elf/dl-load.c | ||
| 76 | +++ b/elf/dl-load.c | ||
| 77 | @@ -433,31 +433,40 @@ fillin_rpath (char *rpath, struct r_search_path_elem **result, const char *sep, | ||
| 78 | { | ||
| 79 | char *cp; | ||
| 80 | size_t nelems = 0; | ||
| 81 | - char *to_free; | ||
| 82 | |||
| 83 | while ((cp = __strsep (&rpath, sep)) != NULL) | ||
| 84 | { | ||
| 85 | struct r_search_path_elem *dirp; | ||
| 86 | + char *to_free = NULL; | ||
| 87 | + size_t len = 0; | ||
| 88 | |||
| 89 | - to_free = cp = expand_dynamic_string_token (l, cp, 1); | ||
| 90 | + /* `strsep' can pass an empty string. */ | ||
| 91 | + if (*cp != '\0') | ||
| 92 | + { | ||
| 93 | + to_free = cp = expand_dynamic_string_token (l, cp, 1); | ||
| 94 | |||
| 95 | - size_t len = strlen (cp); | ||
| 96 | + /* expand_dynamic_string_token can return NULL in case of empty | ||
| 97 | + path or memory allocation failure. */ | ||
| 98 | + if (cp == NULL) | ||
| 99 | + continue; | ||
| 100 | |||
| 101 | - /* `strsep' can pass an empty string. This has to be | ||
| 102 | - interpreted as `use the current directory'. */ | ||
| 103 | - if (len == 0) | ||
| 104 | - { | ||
| 105 | - static const char curwd[] = "./"; | ||
| 106 | - cp = (char *) curwd; | ||
| 107 | - } | ||
| 108 | + /* Compute the length after dynamic string token expansion and | ||
| 109 | + ignore empty paths. */ | ||
| 110 | + len = strlen (cp); | ||
| 111 | + if (len == 0) | ||
| 112 | + { | ||
| 113 | + free (to_free); | ||
| 114 | + continue; | ||
| 115 | + } | ||
| 116 | |||
| 117 | - /* Remove trailing slashes (except for "/"). */ | ||
| 118 | - while (len > 1 && cp[len - 1] == '/') | ||
| 119 | - --len; | ||
| 120 | + /* Remove trailing slashes (except for "/"). */ | ||
| 121 | + while (len > 1 && cp[len - 1] == '/') | ||
| 122 | + --len; | ||
| 123 | |||
| 124 | - /* Now add one if there is none so far. */ | ||
| 125 | - if (len > 0 && cp[len - 1] != '/') | ||
| 126 | - cp[len++] = '/'; | ||
| 127 | + /* Now add one if there is none so far. */ | ||
| 128 | + if (len > 0 && cp[len - 1] != '/') | ||
| 129 | + cp[len++] = '/'; | ||
| 130 | + } | ||
| 131 | |||
| 132 | /* Make sure we don't use untrusted directories if we run SUID. */ | ||
| 133 | if (__glibc_unlikely (check_trusted) && !is_trusted_path (cp, len)) | ||
| 134 | @@ -621,6 +630,14 @@ decompose_rpath (struct r_search_path_struct *sps, | ||
| 135 | necessary. */ | ||
| 136 | free (copy); | ||
| 137 | |||
| 138 | + /* There is no path after expansion. */ | ||
| 139 | + if (result[0] == NULL) | ||
| 140 | + { | ||
| 141 | + free (result); | ||
| 142 | + sps->dirs = (struct r_search_path_elem **) -1; | ||
| 143 | + return false; | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | sps->dirs = result; | ||
| 147 | /* The caller will change this value if we haven't used a real malloc. */ | ||
| 148 | sps->malloced = 1; | ||
| 149 | |||
| 150 | |||
diff --git a/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch b/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch new file mode 100644 index 0000000..cb766c4 --- /dev/null +++ b/recipes-core/glibc/glibc/CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch | |||
| @@ -0,0 +1,401 @@ | |||
| 1 | From 5d7411e9ec03cae8e9bb5df4b515744e5065a64c Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Andreas Wellving <andreas.wellving@enea.com> | ||
| 3 | Date: Mon, 22 Oct 2018 13:54:54 +0200 | ||
| 4 | Subject: [PATCH] Fix integer overflows in internal memalign and malloc [BZ #22343] [BZ #22774] | ||
| 5 | |||
| 6 | When posix_memalign is called with an alignment less than MALLOC_ALIGNMENT | ||
| 7 | and a requested size close to SIZE_MAX, it falls back to malloc code | ||
| 8 | (because the alignment of a block returned by malloc is sufficient to | ||
| 9 | satisfy the call). In this case, an integer overflow in _int_malloc leads | ||
| 10 | to posix_memalign incorrectly returning successfully. | ||
| 11 | |||
| 12 | Upon fixing this and writing a somewhat thorough regression test, it was | ||
| 13 | discovered that when posix_memalign is called with an alignment larger than | ||
| 14 | MALLOC_ALIGNMENT (so it uses _int_memalign instead) and a requested size | ||
| 15 | close to SIZE_MAX, a different integer overflow in _int_memalign leads to | ||
| 16 | posix_memalign incorrectly returning successfully. | ||
| 17 | |||
| 18 | Both integer overflows affect other memory allocation functions that use | ||
| 19 | _int_malloc (one affected malloc in x86) or _int_memalign as well. | ||
| 20 | |||
| 21 | This commit fixes both integer overflows. In addition to this, it adds a | ||
| 22 | regression test to guard against false successful allocations by the | ||
| 23 | following memory allocation functions when called with too-large allocation | ||
| 24 | sizes and, where relevant, various valid alignments: | ||
| 25 | malloc, realloc, calloc, memalign, posix_memalign, aligned_alloc, valloc, | ||
| 26 | and pvalloc. | ||
| 27 | |||
| 28 | (cherry picked from commit 8e448310d74b283c5cd02b9ed7fb997b47bf9b22) | ||
| 29 | |||
| 30 | CVE: CVE-2018-6551 | ||
| 31 | Upstream-Status: Backport [https://sourceware.org/git/?p=glibc.git;a=patch;h=8e448310d74b283c5cd02b9ed7fb997b47bf9b22] | ||
| 32 | |||
| 33 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
| 34 | --- | ||
| 35 | ChangeLog | 13 +++ | ||
| 36 | NEWS | 11 ++ | ||
| 37 | malloc/Makefile | 1 + | ||
| 38 | malloc/malloc.c | 30 ++++-- | ||
| 39 | malloc/tst-malloc-too-large.c | 237 ++++++++++++++++++++++++++++++++++++++++++ | ||
| 40 | 5 files changed, 284 insertions(+), 8 deletions(-) | ||
| 41 | create mode 100644 malloc/tst-malloc-too-large.c | ||
| 42 | |||
| 43 | diff --git a/ChangeLog b/ChangeLog | ||
| 44 | index ad380fd..48b095b 100644 | ||
| 45 | --- a/ChangeLog | ||
| 46 | +++ b/ChangeLog | ||
| 47 | @@ -1,3 +1,16 @@ | ||
| 48 | +2018-01-18 Arjun Shankar <arjun@redhat.com> | ||
| 49 | + | ||
| 50 | + [BZ #22343] | ||
| 51 | + [BZ #22774] | ||
| 52 | + CVE-2018-6485 | ||
| 53 | + CVE-2018-6551 | ||
| 54 | + * malloc/malloc.c (checked_request2size): call REQUEST_OUT_OF_RANGE | ||
| 55 | + after padding. | ||
| 56 | + (_int_memalign): check for integer overflow before calling | ||
| 57 | + _int_malloc. | ||
| 58 | + * malloc/tst-malloc-too-large.c: New test. | ||
| 59 | + * malloc/Makefile: Add tst-malloc-too-large. | ||
| 60 | + | ||
| 61 | 2017-12-30 Aurelien Jarno <aurelien@aurel32.net> | ||
| 62 | Dmitry V. Levin <ldv@altlinux.org> | ||
| 63 | |||
| 64 | diff --git a/NEWS b/NEWS | ||
| 65 | index 195c06d..5134f34 100644 | ||
| 66 | --- a/NEWS | ||
| 67 | +++ b/NEWS | ||
| 68 | @@ -1,3 +1,4 @@ | ||
| 69 | + | ||
| 70 | GNU C Library NEWS -- history of user-visible changes. | ||
| 71 | Copyright (C) 1992-2017 Free Software Foundation, Inc. | ||
| 72 | See the end for copying conditions. | ||
| 73 | @@ -218,6 +219,14 @@ Security related changes: | ||
| 74 | for AT_SECURE or SUID binaries could be used to load libraries from the | ||
| 75 | current directory. | ||
| 76 | |||
| 77 | + CVE-2018-6485: The posix_memalign and memalign functions, when called with | ||
| 78 | + an object size near the value of SIZE_MAX, would return a pointer to a | ||
| 79 | + buffer which is too small, instead of NULL. Reported by Jakub Wilk. | ||
| 80 | + | ||
| 81 | + CVE-2018-6551: The malloc function, when called with an object size near | ||
| 82 | + the value of SIZE_MAX, would return a pointer to a buffer which is too | ||
| 83 | + small, instead of NULL. | ||
| 84 | + | ||
| 85 | The following bugs are resolved with this release: | ||
| 86 | |||
| 87 | [4099] stdio: Overly agressive caching by stream i/o functions. | ||
| 88 | @@ -365,6 +374,8 @@ The following bugs are resolved with this release: | ||
| 89 | [21073] libc: tunables: insecure environment variables passed to | ||
| 90 | subprocesses with AT_SECURE | ||
| 91 | [21081] string: Missing vzeroupper in memset-vec-unaligned-erms.S | ||
| 92 | + [22343] malloc: Integer overflow in posix_memalign (CVE-2018-6485) | ||
| 93 | + [22774] malloc: Integer overflow in malloc (CVE-2018-6551) | ||
| 94 | |||
| 95 | Version 2.24 | ||
| 96 | |||
| 97 | diff --git a/malloc/Makefile b/malloc/Makefile | ||
| 98 | index e93b83b..ab9e795 100644 | ||
| 99 | --- a/malloc/Makefile | ||
| 100 | +++ b/malloc/Makefile | ||
| 101 | @@ -33,6 +33,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ | ||
| 102 | tst-mallocfork2 \ | ||
| 103 | tst-interpose-nothread \ | ||
| 104 | tst-interpose-thread \ | ||
| 105 | + tst-malloc-too-large \ | ||
| 106 | |||
| 107 | tests-static := \ | ||
| 108 | tst-interpose-static-nothread \ | ||
| 109 | diff --git a/malloc/malloc.c b/malloc/malloc.c | ||
| 110 | index 4885793..a82555d 100644 | ||
| 111 | --- a/malloc/malloc.c | ||
| 112 | +++ b/malloc/malloc.c | ||
| 113 | @@ -1202,14 +1202,21 @@ nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
| 114 | MINSIZE : \ | ||
| 115 | ((req) + SIZE_SZ + MALLOC_ALIGN_MASK) & ~MALLOC_ALIGN_MASK) | ||
| 116 | |||
| 117 | -/* Same, except also perform argument check */ | ||
| 118 | - | ||
| 119 | -#define checked_request2size(req, sz) \ | ||
| 120 | - if (REQUEST_OUT_OF_RANGE (req)) { \ | ||
| 121 | - __set_errno (ENOMEM); \ | ||
| 122 | - return 0; \ | ||
| 123 | - } \ | ||
| 124 | - (sz) = request2size (req); | ||
| 125 | +/* Same, except also perform an argument and result check. First, we check | ||
| 126 | + that the padding done by request2size didn't result in an integer | ||
| 127 | + overflow. Then we check (using REQUEST_OUT_OF_RANGE) that the resulting | ||
| 128 | + size isn't so large that a later alignment would lead to another integer | ||
| 129 | + overflow. */ | ||
| 130 | +#define checked_request2size(req, sz) \ | ||
| 131 | +({ \ | ||
| 132 | + (sz) = request2size (req); \ | ||
| 133 | + if (((sz) < (req)) \ | ||
| 134 | + || REQUEST_OUT_OF_RANGE (sz)) \ | ||
| 135 | + { \ | ||
| 136 | + __set_errno (ENOMEM); \ | ||
| 137 | + return 0; \ | ||
| 138 | + } \ | ||
| 139 | +}) | ||
| 140 | |||
| 141 | /* | ||
| 142 | --------------- Physical chunk operations --------------- | ||
| 143 | @@ -4423,6 +4430,13 @@ _int_memalign (mstate av, size_t alignment, size_t bytes) | ||
| 144 | */ | ||
| 145 | |||
| 146 | |||
| 147 | + /* Check for overflow. */ | ||
| 148 | + if (nb > SIZE_MAX - alignment - MINSIZE) | ||
| 149 | + { | ||
| 150 | + __set_errno (ENOMEM); | ||
| 151 | + return 0; | ||
| 152 | + } | ||
| 153 | + | ||
| 154 | /* Call malloc with worst case padding to hit alignment. */ | ||
| 155 | |||
| 156 | m = (char *) (_int_malloc (av, nb + alignment + MINSIZE)); | ||
| 157 | diff --git a/malloc/tst-malloc-too-large.c b/malloc/tst-malloc-too-large.c | ||
| 158 | new file mode 100644 | ||
| 159 | index 0000000..1f7bf29 | ||
| 160 | --- /dev/null | ||
| 161 | +++ b/malloc/tst-malloc-too-large.c | ||
| 162 | @@ -0,0 +1,237 @@ | ||
| 163 | +/* Test and verify that too-large memory allocations fail with ENOMEM. | ||
| 164 | + Copyright (C) 2018 Free Software Foundation, Inc. | ||
| 165 | + This file is part of the GNU C Library. | ||
| 166 | + | ||
| 167 | + The GNU C Library is free software; you can redistribute it and/or | ||
| 168 | + modify it under the terms of the GNU Lesser General Public | ||
| 169 | + License as published by the Free Software Foundation; either | ||
| 170 | + version 2.1 of the License, or (at your option) any later version. | ||
| 171 | + | ||
| 172 | + The GNU C Library is distributed in the hope that it will be useful, | ||
| 173 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 174 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 175 | + Lesser General Public License for more details. | ||
| 176 | + | ||
| 177 | + You should have received a copy of the GNU Lesser General Public | ||
| 178 | + License along with the GNU C Library; if not, see | ||
| 179 | + <http://www.gnu.org/licenses/>. */ | ||
| 180 | + | ||
| 181 | +/* Bug 22375 reported a regression in malloc where if after malloc'ing then | ||
| 182 | + free'ing a small block of memory, malloc is then called with a really | ||
| 183 | + large size argument (close to SIZE_MAX): instead of returning NULL and | ||
| 184 | + setting errno to ENOMEM, malloc incorrectly returns the previously | ||
| 185 | + allocated block instead. Bug 22343 reported a similar case where | ||
| 186 | + posix_memalign incorrectly returns successfully when called with an with | ||
| 187 | + a really large size argument. | ||
| 188 | + | ||
| 189 | + Both of these were caused by integer overflows in the allocator when it | ||
| 190 | + was trying to pad the requested size to allow for book-keeping or | ||
| 191 | + alignment. This test guards against such bugs by repeatedly allocating | ||
| 192 | + and freeing small blocks of memory then trying to allocate various block | ||
| 193 | + sizes larger than the memory bus width of 64-bit targets, or almost | ||
| 194 | + as large as SIZE_MAX on 32-bit targets supported by glibc. In each case, | ||
| 195 | + it verifies that such impossibly large allocations correctly fail. */ | ||
| 196 | + | ||
| 197 | + | ||
| 198 | +#include <stdlib.h> | ||
| 199 | +#include <malloc.h> | ||
| 200 | +#include <errno.h> | ||
| 201 | +#include <stdint.h> | ||
| 202 | +#include <sys/resource.h> | ||
| 203 | +#include <libc-internal.h> | ||
| 204 | +#include <support/check.h> | ||
| 205 | +#include <unistd.h> | ||
| 206 | +#include <sys/param.h> | ||
| 207 | + | ||
| 208 | + | ||
| 209 | +/* This function prepares for each 'too-large memory allocation' test by | ||
| 210 | + performing a small successful malloc/free and resetting errno prior to | ||
| 211 | + the actual test. */ | ||
| 212 | +static void | ||
| 213 | +test_setup (void) | ||
| 214 | +{ | ||
| 215 | + void *volatile ptr = malloc (16); | ||
| 216 | + TEST_VERIFY_EXIT (ptr != NULL); | ||
| 217 | + free (ptr); | ||
| 218 | + errno = 0; | ||
| 219 | +} | ||
| 220 | + | ||
| 221 | + | ||
| 222 | +/* This function tests each of: | ||
| 223 | + - malloc (SIZE) | ||
| 224 | + - realloc (PTR_FOR_REALLOC, SIZE) | ||
| 225 | + - for various values of NMEMB: | ||
| 226 | + - calloc (NMEMB, SIZE/NMEMB) | ||
| 227 | + - calloc (SIZE/NMEMB, NMEMB) | ||
| 228 | + and precedes each of these tests with a small malloc/free before it. */ | ||
| 229 | +static void | ||
| 230 | +test_large_allocations (size_t size) | ||
| 231 | +{ | ||
| 232 | + void * ptr_to_realloc; | ||
| 233 | + | ||
| 234 | + test_setup (); | ||
| 235 | + TEST_VERIFY (malloc (size) == NULL); | ||
| 236 | + TEST_VERIFY (errno == ENOMEM); | ||
| 237 | + | ||
| 238 | + ptr_to_realloc = malloc (16); | ||
| 239 | + TEST_VERIFY_EXIT (ptr_to_realloc != NULL); | ||
| 240 | + test_setup (); | ||
| 241 | + TEST_VERIFY (realloc (ptr_to_realloc, size) == NULL); | ||
| 242 | + TEST_VERIFY (errno == ENOMEM); | ||
| 243 | + free (ptr_to_realloc); | ||
| 244 | + | ||
| 245 | + for (size_t nmemb = 1; nmemb <= 8; nmemb *= 2) | ||
| 246 | + if ((size % nmemb) == 0) | ||
| 247 | + { | ||
| 248 | + test_setup (); | ||
| 249 | + TEST_VERIFY (calloc (nmemb, size / nmemb) == NULL); | ||
| 250 | + TEST_VERIFY (errno == ENOMEM); | ||
| 251 | + | ||
| 252 | + test_setup (); | ||
| 253 | + TEST_VERIFY (calloc (size / nmemb, nmemb) == NULL); | ||
| 254 | + TEST_VERIFY (errno == ENOMEM); | ||
| 255 | + } | ||
| 256 | + else | ||
| 257 | + break; | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | + | ||
| 261 | +static long pagesize; | ||
| 262 | + | ||
| 263 | +/* This function tests the following aligned memory allocation functions | ||
| 264 | + using several valid alignments and precedes each allocation test with a | ||
| 265 | + small malloc/free before it: | ||
| 266 | + memalign, posix_memalign, aligned_alloc, valloc, pvalloc. */ | ||
| 267 | +static void | ||
| 268 | +test_large_aligned_allocations (size_t size) | ||
| 269 | +{ | ||
| 270 | + /* ptr stores the result of posix_memalign but since all those calls | ||
| 271 | + should fail, posix_memalign should never change ptr. We set it to | ||
| 272 | + NULL here and later on we check that it remains NULL after each | ||
| 273 | + posix_memalign call. */ | ||
| 274 | + void * ptr = NULL; | ||
| 275 | + | ||
| 276 | + size_t align; | ||
| 277 | + | ||
| 278 | + /* All aligned memory allocation functions expect an alignment that is a | ||
| 279 | + power of 2. Given this, we test each of them with every valid | ||
| 280 | + alignment from 1 thru PAGESIZE. */ | ||
| 281 | + for (align = 1; align <= pagesize; align *= 2) | ||
| 282 | + { | ||
| 283 | + test_setup (); | ||
| 284 | + TEST_VERIFY (memalign (align, size) == NULL); | ||
| 285 | + TEST_VERIFY (errno == ENOMEM); | ||
| 286 | + | ||
| 287 | + /* posix_memalign expects an alignment that is a power of 2 *and* a | ||
| 288 | + multiple of sizeof (void *). */ | ||
| 289 | + if ((align % sizeof (void *)) == 0) | ||
| 290 | + { | ||
| 291 | + test_setup (); | ||
| 292 | + TEST_VERIFY (posix_memalign (&ptr, align, size) == ENOMEM); | ||
| 293 | + TEST_VERIFY (ptr == NULL); | ||
| 294 | + } | ||
| 295 | + | ||
| 296 | + /* aligned_alloc expects a size that is a multiple of alignment. */ | ||
| 297 | + if ((size % align) == 0) | ||
| 298 | + { | ||
| 299 | + test_setup (); | ||
| 300 | + TEST_VERIFY (aligned_alloc (align, size) == NULL); | ||
| 301 | + TEST_VERIFY (errno == ENOMEM); | ||
| 302 | + } | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + /* Both valloc and pvalloc return page-aligned memory. */ | ||
| 306 | + | ||
| 307 | + test_setup (); | ||
| 308 | + TEST_VERIFY (valloc (size) == NULL); | ||
| 309 | + TEST_VERIFY (errno == ENOMEM); | ||
| 310 | + | ||
| 311 | + test_setup (); | ||
| 312 | + TEST_VERIFY (pvalloc (size) == NULL); | ||
| 313 | + TEST_VERIFY (errno == ENOMEM); | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | + | ||
| 317 | +#define FOURTEEN_ON_BITS ((1UL << 14) - 1) | ||
| 318 | +#define FIFTY_ON_BITS ((1UL << 50) - 1) | ||
| 319 | + | ||
| 320 | + | ||
| 321 | +static int | ||
| 322 | +do_test (void) | ||
| 323 | +{ | ||
| 324 | + | ||
| 325 | +#if __WORDSIZE >= 64 | ||
| 326 | + | ||
| 327 | + /* This test assumes that none of the supported targets have an address | ||
| 328 | + bus wider than 50 bits, and that therefore allocations for sizes wider | ||
| 329 | + than 50 bits will fail. Here, we ensure that the assumption continues | ||
| 330 | + to be true in the future when we might have address buses wider than 50 | ||
| 331 | + bits. */ | ||
| 332 | + | ||
| 333 | + struct rlimit alloc_size_limit | ||
| 334 | + = { | ||
| 335 | + .rlim_cur = FIFTY_ON_BITS, | ||
| 336 | + .rlim_max = FIFTY_ON_BITS | ||
| 337 | + }; | ||
| 338 | + | ||
| 339 | + setrlimit (RLIMIT_AS, &alloc_size_limit); | ||
| 340 | + | ||
| 341 | +#endif /* __WORDSIZE >= 64 */ | ||
| 342 | + | ||
| 343 | + DIAG_PUSH_NEEDS_COMMENT; | ||
| 344 | +#if __GNUC_PREREQ (7, 0) | ||
| 345 | + /* GCC 7 warns about too-large allocations; here we want to test | ||
| 346 | + that they fail. */ | ||
| 347 | + DIAG_IGNORE_NEEDS_COMMENT (7, "-Walloc-size-larger-than="); | ||
| 348 | +#endif | ||
| 349 | + | ||
| 350 | + /* Aligned memory allocation functions need to be tested up to alignment | ||
| 351 | + size equivalent to page size, which should be a power of 2. */ | ||
| 352 | + pagesize = sysconf (_SC_PAGESIZE); | ||
| 353 | + TEST_VERIFY_EXIT (powerof2 (pagesize)); | ||
| 354 | + | ||
| 355 | + /* Loop 1: Ensure that all allocations with SIZE close to SIZE_MAX, i.e. | ||
| 356 | + in the range (SIZE_MAX - 2^14, SIZE_MAX], fail. | ||
| 357 | + | ||
| 358 | + We can expect that this range of allocation sizes will always lead to | ||
| 359 | + an allocation failure on both 64 and 32 bit targets, because: | ||
| 360 | + | ||
| 361 | + 1. no currently supported 64-bit target has an address bus wider than | ||
| 362 | + 50 bits -- and (2^64 - 2^14) is much wider than that; | ||
| 363 | + | ||
| 364 | + 2. on 32-bit targets, even though 2^32 is only 4 GB and potentially | ||
| 365 | + addressable, glibc itself is more than 2^14 bytes in size, and | ||
| 366 | + therefore once glibc is loaded, less than (2^32 - 2^14) bytes remain | ||
| 367 | + available. */ | ||
| 368 | + | ||
| 369 | + for (size_t i = 0; i <= FOURTEEN_ON_BITS; i++) | ||
| 370 | + { | ||
| 371 | + test_large_allocations (SIZE_MAX - i); | ||
| 372 | + test_large_aligned_allocations (SIZE_MAX - i); | ||
| 373 | + } | ||
| 374 | + | ||
| 375 | +#if __WORDSIZE >= 64 | ||
| 376 | + /* On 64-bit targets, we need to test a much wider range of too-large | ||
| 377 | + sizes, so we test at intervals of (1 << 50) that allocation sizes | ||
| 378 | + ranging from SIZE_MAX down to (1 << 50) fail: | ||
| 379 | + The 14 MSBs are decremented starting from "all ON" going down to 1, | ||
| 380 | + the 50 LSBs are "all ON" and then "all OFF" during every iteration. */ | ||
| 381 | + for (size_t msbs = FOURTEEN_ON_BITS; msbs >= 1; msbs--) | ||
| 382 | + { | ||
| 383 | + size_t size = (msbs << 50) | FIFTY_ON_BITS; | ||
| 384 | + test_large_allocations (size); | ||
| 385 | + test_large_aligned_allocations (size); | ||
| 386 | + | ||
| 387 | + size = msbs << 50; | ||
| 388 | + test_large_allocations (size); | ||
| 389 | + test_large_aligned_allocations (size); | ||
| 390 | + } | ||
| 391 | +#endif /* __WORDSIZE >= 64 */ | ||
| 392 | + | ||
| 393 | + DIAG_POP_NEEDS_COMMENT; | ||
| 394 | + | ||
| 395 | + return 0; | ||
| 396 | +} | ||
| 397 | + | ||
| 398 | + | ||
| 399 | +#include <support/test-driver.c> | ||
| 400 | |||
| 401 | |||
diff --git a/recipes-core/glibc/glibc_%.bbappend b/recipes-core/glibc/glibc_%.bbappend deleted file mode 100644 index f2c9a31..0000000 --- a/recipes-core/glibc/glibc_%.bbappend +++ /dev/null | |||
| @@ -1,8 +0,0 @@ | |||
| 1 | # look for files in the layer first | ||
| 2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
| 3 | |||
| 4 | SRC_URI += "file://CVE-2017-1000366.patch \ | ||
| 5 | file://CVE-2017-12132.patch \ | ||
| 6 | file://CVE-2017-8804.patch \ | ||
| 7 | " | ||
| 8 | |||
diff --git a/recipes-core/glibc/glibc_2.25.bbappend b/recipes-core/glibc/glibc_2.25.bbappend new file mode 100644 index 0000000..bbd2585 --- /dev/null +++ b/recipes-core/glibc/glibc_2.25.bbappend | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | # look for files in the layer first | ||
| 2 | FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" | ||
| 3 | |||
| 4 | SRC_URI += " \ | ||
| 5 | file://CVE-2017-1000366.patch \ | ||
| 6 | file://CVE-2017-12132.patch \ | ||
| 7 | file://CVE-2017-8804.patch \ | ||
| 8 | file://CVE-2017-16997-Check-for-empty-tokens-before-dynamic-string-tok.patch \ | ||
| 9 | file://CVE-2018-6551-Fix-integer-overflows-in-internal-memalign-and-malloc-functions.patch \ | ||
| 10 | file://CVE-2017-12133-sunrpc-Avoid-use-after-free-read-access-in-clntudp_c.patch \ | ||
| 11 | " | ||
