Bug 30843 (CVE-2023-4806) - potential use-after-free in getcanonname (CVE-2023-4806)
Summary: potential use-after-free in getcanonname (CVE-2023-4806)
Status: RESOLVED FIXED
Alias: CVE-2023-4806
Product: glibc
Classification: Unclassified
Component: network (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: 2.39
Assignee: Siddhesh Poyarekar
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-09-12 15:32 UTC by Siddhesh Poyarekar
Modified: 2023-12-11 16:37 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
siddhesh: security+


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Siddhesh Poyarekar 2023-09-12 15:32:33 UTC
In an extremely rare situation, the getaddrinfo function in glibc may access memory that has already been freed, resulting in an application crash.

This issue is only exploitable when a NSS module implements only the _nss_*_gethostbyname2_r hook without implementing the _nss_*_gethostbyname3_r hook. There are no known modules that are implemented in this way.

In addition to that condition, the resolved name should return a large number of IPv6 as well as IPv4 and the call to the getaddrinfo function should have AF_INET6 with AI_CANONNAME, AI_ALL and AI_V4MAPPED as flags.
Comment 1 Siddhesh Poyarekar 2023-09-12 15:32:51 UTC
I'm testing a patch.
Comment 2 Xi Ruoyao 2023-09-14 06:45:19 UTC
(In reply to Siddhesh Poyarekar from comment #0)

> This issue is only exploitable when a NSS module implements only the
> _nss_*_gethostbyname2_r hook without implementing the
> _nss_*_gethostbyname3_r hook. There are no known modules that are
> implemented in this way.

nss_wins from samba implements _nss_wins_gethostbyname_r and _nss_wins_gethostbyname2_r, but not _nss_wins_gethostbyname3_r.  Is it problematic?
Comment 3 Siddhesh Poyarekar 2023-09-14 09:56:29 UTC
(In reply to Xi Ruoyao from comment #2)
> nss_wins from samba implements _nss_wins_gethostbyname_r and
> _nss_wins_gethostbyname2_r, but not _nss_wins_gethostbyname3_r.  Is it
> problematic?

I should probably update the description; presence of a _nss_wins_getcanonname_r hook is also necessary (that's the hook that dereferences the freed memory after all) to trigger the user-after-free.  The nss wins plugin in samba doesn't seem to have that hook.
Comment 4 Xi Ruoyao 2023-09-14 10:02:42 UTC
(In reply to Siddhesh Poyarekar from comment #3)
> (In reply to Xi Ruoyao from comment #2)
> > nss_wins from samba implements _nss_wins_gethostbyname_r and
> > _nss_wins_gethostbyname2_r, but not _nss_wins_gethostbyname3_r.  Is it
> > problematic?
> 
> I should probably update the description; presence of a
> _nss_wins_getcanonname_r hook is also necessary (that's the hook that
> dereferences the freed memory after all) to trigger the user-after-free. 
> The nss wins plugin in samba doesn't seem to have that hook.

Thanks for the clarification, I spent two hours attempting to analysis the code and backport the patch to 2.35 and earlier but failed :(.
Comment 5 Sourceware Commits 2023-09-15 18:38:55 UTC
The master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=973fe93a5675c42798b2161c6f29c01b0e243994

commit 973fe93a5675c42798b2161c6f29c01b0e243994
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Comment 6 Sourceware Commits 2023-09-15 19:19:09 UTC
The release/2.38/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=00ae4f10b504bc4564e9f22f00907093f1ab9338

commit 00ae4f10b504bc4564e9f22f00907093f1ab9338
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
Comment 7 Sourceware Commits 2023-09-15 20:53:13 UTC
The release/2.37/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=6529a7466c935f36e9006b854d6f4e1d4876f942

commit 6529a7466c935f36e9006b854d6f4e1d4876f942
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
Comment 8 Sourceware Commits 2023-09-15 22:25:30 UTC
The release/2.36/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=a9728f798ec7f05454c95637ee6581afaa9b487d

commit a9728f798ec7f05454c95637ee6581afaa9b487d
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
Comment 9 Sourceware Commits 2023-09-15 23:48:22 UTC
The release/2.35/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e3ccb230a961b4797510e6a1f5f21fd9021853e7

commit e3ccb230a961b4797510e6a1f5f21fd9021853e7
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
Comment 10 Sourceware Commits 2023-09-16 00:50:03 UTC
The release/2.34/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e09ee267c03e3150c2c9ba28625ab130705a485e

commit e09ee267c03e3150c2c9ba28625ab130705a485e
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Fri Sep 15 13:51:12 2023 -0400

    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.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit 973fe93a5675c42798b2161c6f29c01b0e243994)
Comment 11 Siddhesh Poyarekar 2023-09-16 00:50:44 UTC
Fixed all the way back to 2.34.
Comment 12 Romain Geissler 2023-09-25 00:40:28 UTC
Hi,

Since it's a CVE fix, I guess some people will be tempted to backport the fix in their own downstream forks (especially distros). Please note that the above fix introduced a leak in getaddrinfo, for which a fix was just pushed in the master branch as commit ec6b95c3303c700eb89eebeda2d7264cc184a796. Direct gitweb link: https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=ec6b95c3303c700eb89eebeda2d7264cc184a796

I guess Siddhesh will backport this leak fix in release branches all the way back to 2.34 after the commit will have spent some time in the master branch.

Cheers,
Romain
Comment 13 Sourceware Commits 2023-09-26 11:40:52 UTC
The master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=fd134feba35fa839018965733b34d28a09a075dd

commit fd134feba35fa839018965733b34d28a09a075dd
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Comment 14 Sourceware Commits 2023-09-26 22:52:23 UTC
The release/2.38/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f6445dc94da185b3d1ee283f0ca0a34c4e1986cc

commit f6445dc94da185b3d1ee283f0ca0a34c4e1986cc
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit fd134feba35fa839018965733b34d28a09a075dd)
Comment 15 Sourceware Commits 2023-09-26 22:53:35 UTC
The release/2.37/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=94ef70136587c40a357f775677997c753b3de56c

commit 94ef70136587c40a357f775677997c753b3de56c
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit fd134feba35fa839018965733b34d28a09a075dd)
Comment 16 Sourceware Commits 2023-09-26 22:54:02 UTC
The release/2.36/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=32957eb6a86acdbeec9f38a60a7d5a0ff32db03d

commit 32957eb6a86acdbeec9f38a60a7d5a0ff32db03d
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit fd134feba35fa839018965733b34d28a09a075dd)
Comment 17 Sourceware Commits 2023-09-26 22:54:18 UTC
The release/2.35/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=73d4ce728a59deb2fd18969e559769b3f590fac9

commit 73d4ce728a59deb2fd18969e559769b3f590fac9
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit fd134feba35fa839018965733b34d28a09a075dd)
Comment 18 Sourceware Commits 2023-09-26 22:54:26 UTC
The release/2.34/master branch has been updated by Siddhesh Poyarekar <siddhesh@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=c3b99f8328939533a9b6ac93e8ae7285e90fbdab

commit c3b99f8328939533a9b6ac93e8ae7285e90fbdab
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date:   Tue Sep 26 07:38:07 2023 -0400

    Document CVE-2023-4806 and CVE-2023-5156 in NEWS
    
    These are tracked in BZ #30884 and BZ #30843.
    
    Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
    (cherry picked from commit fd134feba35fa839018965733b34d28a09a075dd)
Comment 19 Mikhail Novosyolov 2023-12-11 16:29:08 UTC
Why was this fix not backported into release/2.33/master?
Seems that v2.33 (and probably 2.32 etc. as well) are affected.
RHEL-8 contains a fix for version v2.28:
https://git.almalinux.org/rpms/glibc/src/branch/c8/SOURCES/glibc-RHEL-2423.patch
Comment 20 Siddhesh Poyarekar 2023-12-11 16:37:25 UTC
Upstream glibc does not do branch maintenance; the branch backports are driven by convenience of downstream distributions.  Please feel free to propose a backport for a stable branch to libc-stable@sourceware.org if you need to.