From fcc6497f25c6a498b75a85b2ecc9799a21d8f435 Mon Sep 17 00:00:00 2001 From: zhuyan Date: Thu, 19 Aug 2021 19:23:35 +0800 Subject: [PATCH] fix CVE-2020-28928 Signed-off-by: zhuyan --- ...te-wcsnrtombs-to-fix-buffer-overflow.patch | 112 ++++++++++++++++++ musl.spec | 7 +- 2 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 backport-rewrite-wcsnrtombs-to-fix-buffer-overflow.patch diff --git a/backport-rewrite-wcsnrtombs-to-fix-buffer-overflow.patch b/backport-rewrite-wcsnrtombs-to-fix-buffer-overflow.patch new file mode 100644 index 0000000..2c47e89 --- /dev/null +++ b/backport-rewrite-wcsnrtombs-to-fix-buffer-overflow.patch @@ -0,0 +1,112 @@ +From 3ab2a4e02682df1382955071919d8aa3c3ec40d4 Mon Sep 17 00:00:00 2001 +From: Rich Felker +Date: Thu, 19 Nov 2020 17:12:43 -0500 +Subject: [PATCH] rewrite wcsnrtombs to fix buffer overflow and other bugs + +the original wcsnrtombs implementation, which has been largely +untouched since 0.5.0, attempted to build input-length-limiting +conversion on top of wcsrtombs, which only limits output length. as +best I recall, this choice was made out of a mix of disdain over +having yet another variant function to implement (added in POSIX 2008; +not standard C) and preference not to switch things around and +implement the wcsrtombs in terms of the more general new function, +probably over namespace issues. the strategy employed was to impose +output limits that would ensure the input limit wasn't exceeded, then +finish up the tail character-at-a-time. unfortunately, none of that +worked correctly. + +first, the logic in the wcsrtombs loop was wrong in that it could +easily get stuck making no forward progress, by imposing an output +limit too small to convert even one character. + +the character-at-a-time loop that followed was even worse. it made no +effort to ensure that the converted multibyte character would fit in +the remaining output space, only that there was a nonzero amount of +output space remaining. it also employed an incorrect interpretation +of wcrtomb's interface contract for converting the null character, +thereby failing to act on end of input, and remaining space accounting +was subject to unsigned wrap-around. together these errors allow +unbounded overflow of the destination buffer, controlled by input +length limit and input wchar_t string contents. + +given the extent to which this function was broken, it's plausible +that most applications that would have been rendered exploitable were +sufficiently broken not to be usable in the first place. however, it's +also plausible that common (especially ASCII-only) inputs succeeded in +the wcsrtombs loop, which mostly worked, while leaving the wildly +erroneous code in the second loop exposed to particular non-ASCII +inputs. + +CVE-2020-28928 has been assigned for this issue. +--- + src/multibyte/wcsnrtombs.c | 46 ++++++++++++++++---------------------- + 1 file changed, 19 insertions(+), 27 deletions(-) + +diff --git a/src/multibyte/wcsnrtombs.c b/src/multibyte/wcsnrtombs.c +index 676932b5..95e25e70 100644 +--- a/src/multibyte/wcsnrtombs.c ++++ b/src/multibyte/wcsnrtombs.c +@@ -1,41 +1,33 @@ + #include ++#include ++#include + + size_t wcsnrtombs(char *restrict dst, const wchar_t **restrict wcs, size_t wn, size_t n, mbstate_t *restrict st) + { +- size_t l, cnt=0, n2; +- char *s, buf[256]; + const wchar_t *ws = *wcs; +- const wchar_t *tmp_ws; +- +- if (!dst) s = buf, n = sizeof buf; +- else s = dst; +- +- while ( ws && n && ( (n2=wn)>=n || n2>32 ) ) { +- if (n2>=n) n2=n; +- tmp_ws = ws; +- l = wcsrtombs(s, &ws, n2, 0); +- if (!(l+1)) { +- cnt = l; +- n = 0; ++ size_t cnt = 0; ++ if (!dst) n=0; ++ while (ws && wn) { ++ char tmp[MB_LEN_MAX]; ++ size_t l = wcrtomb(nn) break; ++ memcpy(dst, tmp, l); ++ } ++ dst += l; + n -= l; + } +- wn = ws ? wn - (ws - tmp_ws) : 0; +- cnt += l; +- } +- if (ws) while (n && wn) { +- l = wcrtomb(s, *ws, 0); +- if ((l+1)<=1) { +- if (!l) ws = 0; +- else cnt = l; ++ if (!*ws) { ++ ws = 0; + break; + } +- ws++; wn--; +- /* safe - this loop runs fewer than sizeof(buf) times */ +- s+=l; n-=l; ++ ws++; ++ wn--; + cnt += l; + } + if (dst) *wcs = ws; +-- +2.27.0 + diff --git a/musl.spec b/musl.spec index d4359d5..03f73e4 100644 --- a/musl.spec +++ b/musl.spec @@ -46,13 +46,15 @@ Name: musl Version: 1.2.0 -Release: 2 +Release: 3 Summary: An implementation of the standard library for Linux-based systems License: MIT URL: https://musl.libc.org Source0: %{url}/releases/%{name}-%{version}.tar.gz +Patch6000: backport-rewrite-wcsnrtombs-to-fix-buffer-overflow.patch + BuildRequires: gcc BuildRequires: make BuildRequires: gnupg2 @@ -180,6 +182,9 @@ ln -sr %{buildroot}%{_libdir}/libc.so %{buildroot}%{_libdir}/libutil.so.1 %{_libdir}/musl-gcc.specs %changelog +* Tue Aug 19 2021 zhuyan - 1.2.0-3 +- fix CVE-2020-28928 + * Tue May 11 2021 Jiajie Li - 1.2.0-2 - Add musl-gcc support -- Gitee