[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#989509: buster-pu: package klibc/2.0.6-1+deb10u1



Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@packages.debian.org
Usertags: pu
X-Debbugs-Cc: debian-kernel@lists.debian.org, mirabilos <tg@debian.org>

[ Reason ]
There are open security issues that were triaged as no-dsa by the
security team.  These affect the heap functions (malloc and calloc)
and the cpio utility.

setjmp and longjmp are implemented incorrectly on s390x.

[ Impact ]
Some programs built using klibc may have potential heap overflows
that can be exploited for privilege escalation.

On s390x, programs using setjmp and longjmp may misbehave in
unpredictable ways.

[ Tests ]
malloc, calloc, setjmp, and longjmp are exercised by the test suite
that runs during build.  However the setjmp/longjmp test was not
sufficient to detect the bug.

Thorsten Glaser tested the s390x fix in unstable.  It has not (yet)
been manually tested in this version.

I have tested the cpio utility manually.

[ Risks ]
The changes are localised and seem comparatively low-risk to me.

[ Checklist ]
  [X] *all* changes are documented in the d/changelog
  [X] I reviewed all changes and I approve them
  [X] attach debdiff against the package in (old)stable
  [X] the issue is verified as fixed in unstable

[ Changes ]
All but one of the patches fixes a single bug or CVE as detailed in
its patch header.

The patch "malloc: Set errno on failure" is applied as a dependency
of "malloc: Fail if requested size > PTRDIFF_MAX".

[ Other info ]
diff -Nru klibc-2.0.6/debian/changelog klibc-2.0.6/debian/changelog
--- klibc-2.0.6/debian/changelog	2019-02-01 06:00:57.000000000 +0100
+++ klibc-2.0.6/debian/changelog	2021-06-05 20:20:42.000000000 +0200
@@ -1,3 +1,19 @@
+klibc (2.0.6-1+deb10u1) buster; urgency=medium
+
+  [ Ben Hutchings ]
+  * Apply security fixes from 2.0.9 (Closes: #989505):
+    - malloc: Set errno on failure
+    - malloc: Fail if requested size > PTRDIFF_MAX (CVE-2021-31873)
+    - calloc: Fail if multiplication overflows (CVE-2021-31870)
+    - cpio: Fix possible integer overflow on 32-bit systems (CVE-2021-31872)
+    - cpio: Fix possible crash on 64-bit systems (CVE-2021-31871)
+
+  [ Thorsten Glaser ]
+  * {set,long}jmp [s390x]: save/restore the correct FPU registers
+    (f8‥f15 not f1/f3/f5/f7) (Closes: #943425)
+
+ -- Ben Hutchings <benh@debian.org>  Sat, 05 Jun 2021 20:20:42 +0200
+
 klibc (2.0.6-1) unstable; urgency=medium
 
   * New upstream version:
diff -Nru klibc-2.0.6/debian/patches/0035-klibc-malloc-Set-errno-on-failure.patch klibc-2.0.6/debian/patches/0035-klibc-malloc-Set-errno-on-failure.patch
--- klibc-2.0.6/debian/patches/0035-klibc-malloc-Set-errno-on-failure.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0035-klibc-malloc-Set-errno-on-failure.patch	2021-04-30 04:30:16.000000000 +0200
@@ -0,0 +1,32 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 28 Apr 2021 03:57:39 +0200
+Subject: [klibc] malloc: Set errno on failure
+Origin: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/commit/?id=7f6626d12daa2f1efd9953d1f4ba2065348dc5cd
+
+malloc() is specified to set errno = ENOMEM on failure, so do that.
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ usr/klibc/malloc.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/usr/klibc/malloc.c b/usr/klibc/malloc.c
+index 413b7337..bb57c9f6 100644
+--- a/usr/klibc/malloc.c
++++ b/usr/klibc/malloc.c
+@@ -8,6 +8,7 @@
+ #include <unistd.h>
+ #include <sys/mman.h>
+ #include <assert.h>
++#include <errno.h>
+ #include "malloc.h"
+ 
+ /* Both the arena list and the free memory list are double linked
+@@ -169,6 +170,7 @@ void *malloc(size_t size)
+ #endif
+ 
+ 	if (fp == (struct free_arena_header *)MAP_FAILED) {
++		errno = ENOMEM;
+ 		return NULL;	/* Failed to get a block */
+ 	}
+ 
diff -Nru klibc-2.0.6/debian/patches/0036-klibc-malloc-Fail-if-requested-size-PTRDIFF_MAX.patch klibc-2.0.6/debian/patches/0036-klibc-malloc-Fail-if-requested-size-PTRDIFF_MAX.patch
--- klibc-2.0.6/debian/patches/0036-klibc-malloc-Fail-if-requested-size-PTRDIFF_MAX.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0036-klibc-malloc-Fail-if-requested-size-PTRDIFF_MAX.patch	2021-04-30 04:30:16.000000000 +0200
@@ -0,0 +1,41 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 28 Apr 2021 04:03:49 +0200
+Subject: [klibc] malloc: Fail if requested size > PTRDIFF_MAX
+Origin: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/commit/?id=a31ae8c508fc8d1bca4f57e9f9f88127572d5202
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-31873
+
+malloc() adds some overhead to the requested size, which may result in
+an integer overflow and subsequent buffer overflow if it is close to
+SIZE_MAX.  It should fail if size is large enough for this to happen.
+
+Further, it's not legal for a C object to be larger than
+PTRDIFF_MAX (half of SIZE_MAX) as pointer arithmetic within it could
+overflow.  So return failure immediately if size is greater than that.
+
+CVE-2021-31873
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ usr/klibc/malloc.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/usr/klibc/malloc.c b/usr/klibc/malloc.c
+index bb57c9f6..abda84c2 100644
+--- a/usr/klibc/malloc.c
++++ b/usr/klibc/malloc.c
+@@ -147,6 +147,15 @@ void *malloc(size_t size)
+ 	if (size == 0)
+ 		return NULL;
+ 
++	/* Various additions below will overflow if size is close to
++	   SIZE_MAX.  Further, it's not legal for a C object to be
++	   larger than PTRDIFF_MAX (half of SIZE_MAX) as pointer
++	   arithmetic within it could overflow. */
++	if (size > PTRDIFF_MAX) {
++		errno = ENOMEM;
++		return NULL;
++	}
++
+ 	/* Add the obligatory arena header, and round up */
+ 	size = (size + 2 * sizeof(struct arena_header) - 1) & ARENA_SIZE_MASK;
+ 
diff -Nru klibc-2.0.6/debian/patches/0037-klibc-calloc-Fail-if-multiplication-overflows.patch klibc-2.0.6/debian/patches/0037-klibc-calloc-Fail-if-multiplication-overflows.patch
--- klibc-2.0.6/debian/patches/0037-klibc-calloc-Fail-if-multiplication-overflows.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0037-klibc-calloc-Fail-if-multiplication-overflows.patch	2021-04-30 04:30:16.000000000 +0200
@@ -0,0 +1,43 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 28 Apr 2021 04:29:50 +0200
+Subject: [klibc] calloc: Fail if multiplication overflows
+Origin: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/commit/?id=292650f04c2b5348b4efbad61fb014ed09b4f3f2
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-31870
+
+calloc() multiplies its 2 arguments together and passes the result to
+malloc().  Since the factors and product both have type size_t, this
+can result in an integer overflow and subsequent buffer overflow.
+Check for this and fail if it happens.
+
+CVE-2021-31870
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ usr/klibc/calloc.c | 11 ++++++++---
+ 1 file changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/usr/klibc/calloc.c b/usr/klibc/calloc.c
+index 53dcc6b2..4a81cda1 100644
+--- a/usr/klibc/calloc.c
++++ b/usr/klibc/calloc.c
+@@ -2,12 +2,17 @@
+  * calloc.c
+  */
+ 
++#include <errno.h>
+ #include <stdlib.h>
+ #include <string.h>
+ 
+-/* FIXME: This should look for multiplication overflow */
+-
+ void *calloc(size_t nmemb, size_t size)
+ {
+-	return zalloc(nmemb * size);
++	unsigned long prod;
++
++	if (__builtin_umull_overflow(nmemb, size, &prod)) {
++		errno = ENOMEM;
++		return NULL;
++	}
++	return zalloc(prod);
+ }
diff -Nru klibc-2.0.6/debian/patches/0039-klibc-cpio-Fix-possible-integer-overflow-on-32-bit-s.patch klibc-2.0.6/debian/patches/0039-klibc-cpio-Fix-possible-integer-overflow-on-32-bit-s.patch
--- klibc-2.0.6/debian/patches/0039-klibc-cpio-Fix-possible-integer-overflow-on-32-bit-s.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0039-klibc-cpio-Fix-possible-integer-overflow-on-32-bit-s.patch	2021-04-30 04:30:16.000000000 +0200
@@ -0,0 +1,68 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 28 Apr 2021 05:16:34 +0200
+Subject: [klibc] cpio: Fix possible integer overflow on 32-bit systems
+Origin: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/commit/?id=9b1c91577aef7f2e72c3aa11a27749160bd278ff
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-31872
+
+The maximum name and file sizes in the "new" header format are 32-bit
+unsigned values.  However, the I/O functions mostly use long for sizes
+and offsets, so that sizes >= 2^31 are handled wrongly on 32-bit
+systems.
+
+The current GNU cpio code doesn't seem to have this problem, but the
+divergence between this version and that is large enough that I can't
+simply cherry-pick a fix for it.
+
+As a short-term fix, in read_in_new_ascii(), fail if c_namesize or
+c_filesize is > LONG_MAX.
+
+CVE-2021-31872
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ usr/utils/cpio.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/usr/utils/cpio.c b/usr/utils/cpio.c
+index cb616791..ac481310 100644
+--- a/usr/utils/cpio.c
++++ b/usr/utils/cpio.c
+@@ -17,6 +17,7 @@
+ 
+ #include <errno.h>
+ #include <fcntl.h>
++#include <limits.h>
+ #include <malloc.h>
+ #include <stdbool.h>
+ #include <stdio.h>
+@@ -904,6 +905,15 @@ static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des)
+ 		file_hdr->c_hdr[i] = strtoul(hexbuf, NULL, 16);
+ 		ah += 8;
+ 	}
++
++	/* Sizes > LONG_MAX can currently result in integer overflow
++	   in various places.  Fail if name is too large. */
++	if (file_hdr->c_namesize > LONG_MAX) {
++		fprintf(stderr, "%s: name size out of range\n",
++			progname);
++		exit(1);
++	}
++
+ 	/* Read file name from input.  */
+ 	free(file_hdr->c_name);
+ 	file_hdr->c_name = (char *)xmalloc(file_hdr->c_namesize);
+@@ -914,6 +924,14 @@ static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des)
+ 	   is rounded up to the next long-word, so we might need to drop
+ 	   1-3 bytes.  */
+ 	tape_skip_padding(in_des, file_hdr->c_namesize + 110);
++
++	/* Fail if file is too large.  We could check this earlier
++	   but it's helpful to report the name. */
++	if (file_hdr->c_filesize > LONG_MAX) {
++		fprintf(stderr, "%s: %s: file size out of range\n",
++			progname, file_hdr->c_name);
++		exit(1);
++	}
+ }
+ 
+ /* Return 16-bit integer I with the bytes swapped.  */
diff -Nru klibc-2.0.6/debian/patches/0040-klibc-cpio-Fix-possible-crash-on-64-bit-systems.patch klibc-2.0.6/debian/patches/0040-klibc-cpio-Fix-possible-crash-on-64-bit-systems.patch
--- klibc-2.0.6/debian/patches/0040-klibc-cpio-Fix-possible-crash-on-64-bit-systems.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0040-klibc-cpio-Fix-possible-crash-on-64-bit-systems.patch	2021-04-30 04:30:16.000000000 +0200
@@ -0,0 +1,32 @@
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 28 Apr 2021 19:46:47 +0200
+Subject: [klibc] cpio: Fix possible crash on 64-bit systems
+Origin: https://git.kernel.org/pub/scm/libs/klibc/klibc.git/commit/?id=2e48a12ab1e30d43498c2d53e878a11a1b5102d5
+Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2021-31871
+
+copyin_link() tries to allocate (unsigned int)c_filesize + 1 bytes.
+If c_filesize == UINT_MAX, this works out as 0 bytes, resulting in a
+null pointer and a subsequent SIGSEGV.
+
+The previous commit made this impossible on 32-bit systems.
+
+CVE-2021-31871
+
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+---
+ usr/utils/cpio.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/usr/utils/cpio.c b/usr/utils/cpio.c
+index ac481310..9b0b6ae9 100644
+--- a/usr/utils/cpio.c
++++ b/usr/utils/cpio.c
+@@ -832,7 +832,7 @@ static void copyin_link(struct new_cpio_header *file_hdr, int in_file_des)
+ 	char *link_name = NULL;	/* Name of hard and symbolic links.  */
+ 	int res;		/* Result of various function calls.  */
+ 
+-	link_name = (char *)xmalloc((unsigned int)file_hdr->c_filesize + 1);
++	link_name = (char *)xmalloc(file_hdr->c_filesize + 1);
+ 	link_name[file_hdr->c_filesize] = '\0';
+ 	tape_buffered_read(link_name, in_file_des, file_hdr->c_filesize);
+ 	tape_skip_padding(in_file_des, file_hdr->c_filesize);
diff -Nru klibc-2.0.6/debian/patches/0041-klibc-set-long-jmp-s390x-save-restore-the-correct-re.patch klibc-2.0.6/debian/patches/0041-klibc-set-long-jmp-s390x-save-restore-the-correct-re.patch
--- klibc-2.0.6/debian/patches/0041-klibc-set-long-jmp-s390x-save-restore-the-correct-re.patch	1970-01-01 01:00:00.000000000 +0100
+++ klibc-2.0.6/debian/patches/0041-klibc-set-long-jmp-s390x-save-restore-the-correct-re.patch	2021-06-05 20:19:52.000000000 +0200
@@ -0,0 +1,57 @@
+Description: {set,long}jmp [s390x]: save/restore the correct registers
+ The s390x ABI actually has FPU registers f8‥f15, not f1/f3/f5/f7,
+ to be saved. (Closes: Debian #943425)
+Author: mirabilos <tg@debian.org>
+Forwarded: https://lists.zytor.com/archives/klibc/2021-May/004620.html
+
+--- a/usr/include/arch/s390/klibc/archsetjmp.h
++++ b/usr/include/arch/s390/klibc/archsetjmp.h
+@@ -16,7 +16,7 @@ struct __jmp_buf {
+ 
+ struct __jmp_buf {
+ 	uint64_t __gregs[10]; /* general registers r6-r15 */
+-	uint64_t __fpregs[4]; /* fp registers f1, f3, f5, f7 */
++	uint64_t __fpregs[8]; /* fp registers f8-f15 */
+ };
+ 
+ #endif /* __s390x__ */
+--- a/usr/klibc/arch/s390/setjmp.S
++++ b/usr/klibc/arch/s390/setjmp.S
+@@ -38,10 +38,14 @@ longjmp:
+ 
+ setjmp:
+ 	stmg	%r6,%r15,0(%r2)		# save all general registers
+-	std	%f1,80(%r2)		# save fp registers f4 and f6
+-	std	%f3,88(%r2)
+-	std	%f5,96(%r2)
+-	std	%f7,104(%r2)
++	std	%f8,80(%r2)		# save fp registers f8 to f15
++	std	%f9,88(%r2)
++	std	%f10,96(%r2)
++	std	%f11,104(%r2)
++	std	%f12,112(%r2)
++	std	%f13,120(%r2)
++	std	%f14,128(%r2)
++	std	%f15,136(%r2)
+ 	lghi	%r2,0			# return 0
+ 	br	%r14
+ 
+@@ -54,10 +58,14 @@ setjmp:
+ longjmp:
+ 	lgr	%r1,%r2			# jmp_buf
+ 	lgr	%r2,%r3			# return value
+-	ld	%f7,104(%r1)		# restore all saved registers
+-	ld	%f5,96(%r1)
+-	ld	%f3,88(%r1)
+-	ld	%f1,80(%r1)
++	ld	%f15,136(%r1)		# restore all saved registers
++	ld	%f14,128(%r1)
++	ld	%f13,120(%r1)
++	ld	%f12,112(%r1)
++	ld	%f11,104(%r1)
++	ld	%f10,96(%r1)
++	ld	%f9,88(%r1)
++	ld	%f8,80(%r1)
+ 	lmg	%r6,%r15,0(%r1)
+ 	br	%r14			# return to restored address
+ 
diff -Nru klibc-2.0.6/debian/patches/series klibc-2.0.6/debian/patches/series
--- klibc-2.0.6/debian/patches/series	2019-02-01 06:00:06.000000000 +0100
+++ klibc-2.0.6/debian/patches/series	2021-06-05 20:19:52.000000000 +0200
@@ -1 +1,7 @@
 resume-backward-compatibility-for-resume_offset.patch
+0035-klibc-malloc-Set-errno-on-failure.patch
+0036-klibc-malloc-Fail-if-requested-size-PTRDIFF_MAX.patch
+0037-klibc-calloc-Fail-if-multiplication-overflows.patch
+0039-klibc-cpio-Fix-possible-integer-overflow-on-32-bit-s.patch
+0040-klibc-cpio-Fix-possible-crash-on-64-bit-systems.patch
+0041-klibc-set-long-jmp-s390x-save-restore-the-correct-re.patch

Reply to: