From 0aea3a20062923f5c39c947e31ac9f87b9b351ce Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Tue, 12 Sep 2017 07:54:13 +0200 Subject: glibc: CVE-2017-8804 Fixes memory leak in sunrpc when decoding malformed XDR References: https://security-tracker.debian.org/tracker/CVE-2017-8804 Upstream patch: https://sourceware.org/ml/libc-alpha/2017-05/msg00105.html Signed-off-by: Sona Sarmadi Signed-off-by: Martin Borg --- recipes-core/glibc/glibc/CVE-2017-8804.patch | 225 +++++++++++++++++++++++++++ recipes-core/glibc/glibc_%.bbappend | 1 + 2 files changed, 226 insertions(+) create mode 100644 recipes-core/glibc/glibc/CVE-2017-8804.patch (limited to 'recipes-core') diff --git a/recipes-core/glibc/glibc/CVE-2017-8804.patch b/recipes-core/glibc/glibc/CVE-2017-8804.patch new file mode 100644 index 0000000..ae21ad0 --- /dev/null +++ b/recipes-core/glibc/glibc/CVE-2017-8804.patch @@ -0,0 +1,225 @@ +From 45619a54f7d751a2a7dec7d7ee323e1545b881af Mon Sep 17 00:00:00 2001 +From: Sona Sarmadi +Date: Mon, 11 Sep 2017 13:35:44 +0200 +Subject: [PATCH] CVE-2017-8804 + +The xdr_bytes and xdr_string functions in the glibc or libc6 2.25 mishandle +failures of buffer deserialization, which allows remote attackers to cause +a denial of service (virtual memory allocation, or memory consumption if an +overcommit setting is not used) via a crafted UDP packet to port 111, a +related issue to CVE-2017-8779. + +CVE: CVE-2017-8804 +Upstream-Status: Backport [https://sourceware.org/ml/libc-alpha/2017-05/msg00105.html] + +Signed-off-by: Sona Sarmadi +--- + NEWS | 3 ++ + sunrpc/Makefile | 10 ++++++- + sunrpc/tst-xdrmem3.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + sunrpc/xdr.c | 41 ++++++++++++++++++++------ + 4 files changed, 127 insertions(+), 10 deletions(-) + create mode 100644 sunrpc/tst-xdrmem3.c + +diff --git a/NEWS b/NEWS +index ec15dde..29e795a 100644 +--- a/NEWS ++++ b/NEWS +@@ -211,6 +211,9 @@ Security related changes: + question type which is outside the range of valid question type values. + (CVE-2015-5180) + ++* The xdr_bytes and xdr_string routines free the internally allocated buffer ++ if deserialization of the buffer contents fails for any reason. ++ + The following bugs are resolved with this release: + + [4099] stdio: Overly agressive caching by stream i/o functions. +diff --git a/sunrpc/Makefile b/sunrpc/Makefile +index 0c1e612..12ec2e7 100644 +--- a/sunrpc/Makefile ++++ b/sunrpc/Makefile +@@ -93,9 +93,16 @@ rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ + extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) + others += rpcgen + +-tests = tst-xdrmem tst-xdrmem2 test-rpcent ++tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-xdrmem3 + xtests := tst-getmyaddr + ++tests-special += $(objpfx)mtrace-tst-xdrmem3.out ++generated += mtrace-tst-xdrmem3.out tst-xdrmem3.mtrace ++tst-xdrmem3-ENV = MALLOC_TRACE=$(objpfx)tst-xdrmem3.mtrace ++$(objpfx)mtrace-tst-xdrmem3.out: $(objpfx)tst-xdrmem3.out ++ $(common-objpfx)malloc/mtrace $(objpfx)tst-xdrmem3.mtrace > $@; \ ++ $(evaluate-test) ++ + ifeq ($(have-thread-library),yes) + xtests += thrsvc + endif +@@ -155,6 +162,7 @@ BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS) + $(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so + $(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so ++(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so + + $(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs)) + +diff --git a/sunrpc/tst-xdrmem3.c b/sunrpc/tst-xdrmem3.c +new file mode 100644 +index 0000000..b3c72ae +--- /dev/null ++++ b/sunrpc/tst-xdrmem3.c +@@ -0,0 +1,83 @@ ++/* Test xdr_bytes, xdr_string behavior on deserialization failure. ++ Copyright (C) 2017 Free Software Foundation, Inc. ++ This file is part of the GNU C Library. ++ ++ The GNU C Library is free software; you can redistribute it and/or ++ modify it under the terms of the GNU Lesser General Public ++ License as published by the Free Software Foundation; either ++ version 2.1 of the License, or (at your option) any later version. ++ ++ The GNU C Library is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ Lesser General Public License for more details. ++ ++ You should have received a copy of the GNU Lesser General Public ++ License along with the GNU C Library; if not, see ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++static int ++do_test (void) ++{ ++ mtrace (); ++ ++ /* If do_own_buffer, allocate the buffer and pass it to the ++ deserialization routine. Otherwise the routine is requested to ++ allocate the buffer. */ ++ for (int do_own_buffer = 0; do_own_buffer < 2; ++do_own_buffer) ++ { ++ /* Length 16 MiB, but only 2 bytes of data in the packet. */ ++ unsigned char buf[] = "\x01\x00\x00\x00\xff"; ++ XDR xdrs; ++ char *result; ++ unsigned int result_len; ++ ++ /* Test xdr_bytes. */ ++ xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE); ++ result_len = 0; ++ if (do_own_buffer) ++ { ++ char *own_buffer = xmalloc (10); ++ result = own_buffer; ++ TEST_VERIFY (!xdr_bytes (&xdrs, &result, &result_len, 10)); ++ TEST_VERIFY (result == own_buffer); ++ free (own_buffer); ++ } ++ else ++ { ++ result = NULL; ++ TEST_VERIFY (!xdr_bytes (&xdrs, &result, &result_len, -1)); ++ TEST_VERIFY (result == NULL); ++ } ++ TEST_VERIFY (result_len == 16 * 1024 * 1024); ++ xdr_destroy (&xdrs); ++ ++ /* Test xdr_string. */ ++ xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE); ++ if (do_own_buffer) ++ { ++ char *own_buffer = xmalloc (10); ++ result = own_buffer; ++ TEST_VERIFY (!xdr_string (&xdrs, &result, 10)); ++ TEST_VERIFY (result == own_buffer); ++ free (own_buffer); ++ } ++ else ++ { ++ result = NULL; ++ TEST_VERIFY (!xdr_string (&xdrs, &result, -1)); ++ TEST_VERIFY (result == NULL); ++ } ++ xdr_destroy (&xdrs); ++ } ++ ++ return 0; ++} ++ ++#include ++ +diff --git a/sunrpc/xdr.c b/sunrpc/xdr.c +index bfabf33..857f7c8 100644 +--- a/sunrpc/xdr.c ++++ b/sunrpc/xdr.c +@@ -620,14 +620,24 @@ xdr_bytes (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) + } + if (sp == NULL) + { +- *cpp = sp = (char *) mem_alloc (nodesize); ++ sp = (char *) mem_alloc (nodesize); ++ if (sp == NULL) ++ { ++ (void) __fxprintf (NULL, "%s: %s", __func__, ++ _("out of memory\n")); ++ return FALSE; ++ } + } +- if (sp == NULL) ++ if (!xdr_opaque (xdrs, sp, nodesize)) + { +- (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); ++ if (sp != *cpp) ++ /* *cpp was NULL, so this function allocated a new ++ buffer. */ ++ free (sp); + return FALSE; + } +- /* fall into ... */ ++ *cpp = sp; ++ return TRUE; + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, nodesize); +@@ -781,14 +791,27 @@ xdr_string (XDR *xdrs, char **cpp, u_int maxsize) + { + case XDR_DECODE: + if (sp == NULL) +- *cpp = sp = (char *) mem_alloc (nodesize); +- if (sp == NULL) + { +- (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); +- return FALSE; ++ sp = (char *) mem_alloc (nodesize); ++ if (sp == NULL) ++ { ++ (void) __fxprintf (NULL, "%s: %s", __func__, ++ _("out of memory\n")); ++ return FALSE; ++ } + } + sp[size] = 0; +- /* fall into ... */ ++ ++ if (!xdr_opaque (xdrs, sp, size)) ++ { ++ if (sp != *cpp) ++ /* *cpp was NULL, so this function allocated a new ++ buffer. */ ++ free (sp); ++ return FALSE; ++ } ++ *cpp = sp; ++ return TRUE; + + case XDR_ENCODE: + return xdr_opaque (xdrs, sp, size); +-- +1.9.1 + diff --git a/recipes-core/glibc/glibc_%.bbappend b/recipes-core/glibc/glibc_%.bbappend index 0e2cb2e..f2c9a31 100644 --- a/recipes-core/glibc/glibc_%.bbappend +++ b/recipes-core/glibc/glibc_%.bbappend @@ -3,5 +3,6 @@ FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" SRC_URI += "file://CVE-2017-1000366.patch \ file://CVE-2017-12132.patch \ + file://CVE-2017-8804.patch \ " -- cgit v1.2.3-54-g00ecf