mirror of
https://abf.rosa.ru/djam/glibc40.git
synced 2025-02-23 15:52:52 +00:00
Fix CVE-2023-4806
This commit is contained in:
parent
c785123c5e
commit
894fcbf028
2 changed files with 112 additions and 1 deletions
107
CVE-2023-4806.patch
Normal file
107
CVE-2023-4806.patch
Normal file
|
@ -0,0 +1,107 @@
|
|||
From 74d98fb3d9e489666195d69efff04b5760632312 Mon Sep 17 00:00:00 2001
|
||||
From: Mikhail Novosyolov <m.novosyolov@rosalinux.ru>
|
||||
Date: Mon, 11 Dec 2023 20:09:59 +0300
|
||||
Subject: [PATCH] getaddrinfo: Fix use after free in getcanonname (CVE-2023-4806)
|
||||
|
||||
When an NSS plugin only implements the _gethostbyname2_r and
|
||||
_getcanonname_r callbacks, getaddrinfo could use memory that was freed
|
||||
during tmpbuf resizing, through h_name in a previous query response.
|
||||
|
||||
The backing store for res->at->name when doing a query with
|
||||
gethostbyname3_r or gethostbyname2_r is tmpbuf, which is reallocated in
|
||||
gethosts during the query. For AF_INET6 lookup with AI_ALL |
|
||||
AI_V4MAPPED, gethosts gets called twice, once for a v6 lookup and second
|
||||
for a v4 lookup. In this case, if the first call reallocates tmpbuf
|
||||
enough number of times, resulting in a malloc, th->h_name (that
|
||||
res->at->name refers to) ends up on a heap allocated storage in tmpbuf.
|
||||
Now if the second call to gethosts also causes the plugin callback to
|
||||
return NSS_STATUS_TRYAGAIN, tmpbuf will get freed, resulting in a UAF
|
||||
reference in res->at->name. This then gets dereferenced in the
|
||||
getcanonname_r plugin call, resulting in the use after free.
|
||||
|
||||
Fix this by copying h_name over and freeing it at the end. This
|
||||
resolves BZ #30843, which is assigned CVE-2023-4806.
|
||||
|
||||
Minimal port of https://git.almalinux.org/rpms/glibc/src/branch/c8/SOURCES/glibc-RHEL-2423.patch
|
||||
into glibc-2.33 by mikhailnov
|
||||
Original author: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
---
|
||||
sysdeps/posix/getaddrinfo.c | 21 +++++++++++++++++----
|
||||
1 file changed, 17 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||||
index 92d2a1c284..2e26a98050 100644
|
||||
--- a/sysdeps/posix/getaddrinfo.c
|
||||
+++ b/sysdeps/posix/getaddrinfo.c
|
||||
@@ -232,7 +232,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
}
|
||||
array[i].next = array + i + 1;
|
||||
}
|
||||
- array[0].name = h->h_name;
|
||||
array[count - 1].next = NULL;
|
||||
|
||||
*result = array;
|
||||
@@ -283,6 +282,18 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
} \
|
||||
*pat = addrmem; \
|
||||
\
|
||||
+ /* Store h_name so that it survives accidental deallocation when \
|
||||
+ gethosts is called again and tmpbuf gets reallocated. */ \
|
||||
+ if (h_name == NULL && th.h_name != NULL) \
|
||||
+ { \
|
||||
+ h_name = __strdup (th.h_name); \
|
||||
+ if (h_name == NULL) \
|
||||
+ { \
|
||||
+ __resolv_context_put (res_ctx); \
|
||||
+ result = -EAI_SYSTEM; \
|
||||
+ goto free_and_return; \
|
||||
+ } \
|
||||
+ } \
|
||||
if (localcanon != NULL && canon == NULL) \
|
||||
{ \
|
||||
canonbuf = __strdup (localcanon); \
|
||||
@@ -307,14 +318,14 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||||
memory allocation failure. The returned string is allocated on the
|
||||
heap; the caller has to free it. */
|
||||
static char *
|
||||
-getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
|
||||
+getcanonname (nss_action_list nip, const char *hname, const char *name)
|
||||
{
|
||||
nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
|
||||
char *s = (char *) name;
|
||||
if (cfct != NULL)
|
||||
{
|
||||
char buf[256];
|
||||
- if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
|
||||
+ if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf),
|
||||
&s, &errno, &h_errno)) != NSS_STATUS_SUCCESS)
|
||||
/* If the canonical name cannot be determined, use the passed
|
||||
string. */
|
||||
@@ -333,6 +344,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
struct gaih_addrtuple *at = NULL;
|
||||
bool got_ipv6 = false;
|
||||
const char *canon = NULL;
|
||||
+ char *h_name = NULL;
|
||||
const char *orig_name = name;
|
||||
|
||||
/* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||||
@@ -860,7 +872,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
if ((req->ai_flags & AI_CANONNAME) != 0
|
||||
&& canon == NULL)
|
||||
{
|
||||
- canonbuf = getcanonname (nip, at, name);
|
||||
+ canonbuf = getcanonname (nip, h_name, name);
|
||||
if (canonbuf == NULL)
|
||||
{
|
||||
__resolv_context_put (res_ctx);
|
||||
@@ -1102,6 +1114,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||||
free ((char *) name);
|
||||
free (addrmem);
|
||||
free (canonbuf);
|
||||
+ free (h_name);
|
||||
|
||||
return result;
|
||||
}
|
||||
--
|
||||
2.40.1
|
||||
|
|
@ -102,7 +102,7 @@ Version: 2.33
|
|||
#Source0: http://ftp.gnu.org/gnu/glibc/%{oname}-%{version}.tar.xz
|
||||
# use ./upd.sh to make a tarball and automatically update Release
|
||||
Source0: glibc-%{commit}.tar.xz
|
||||
Release: 10.git%{commit_short}.2
|
||||
Release: 10.git%{commit_short}.3
|
||||
License: LGPLv2+ and LGPLv2+ with exceptions and GPLv2+
|
||||
Group: System/Libraries
|
||||
Url: http://www.gnu.org/software/libc/
|
||||
|
@ -190,6 +190,10 @@ Patch1040: https://github.com/FireBurn/glibc/commit/2efa9591e5e8a129e7b73ad0dad3
|
|||
|
||||
Patch1051: glibc-2.34-select-i686.patch
|
||||
|
||||
# https://sourceware.org/bugzilla/show_bug.cgi?id=30843#c19
|
||||
# This fix does not introduce CVE-2023-5156
|
||||
Patch2001: CVE-2023-4806.patch
|
||||
|
||||
# do not remove this BR - it helps to bootstrap the generator
|
||||
BuildRequires: devel-rpm-generators
|
||||
BuildRequires: autoconf2.5
|
||||
|
|
Loading…
Add table
Reference in a new issue