Skip to content
Snippets Groups Projects
Commit 4372ac34 authored by Aurelien Jarno's avatar Aurelien Jarno Committed by Dylan Aïssi
Browse files

Import Debian changes 2.31-13+deb11u11

parent bb40be28
No related branches found
No related tags found
3 merge requests!73Merge changes from apertis/v2023-updates into apertis/v2023,!70Update from debian/bullseye for apertis/v2022-updates,!69Update from debian/bullseye for apertis/v2023-updates
Pipeline #760452 passed
glibc (2.31-13+deb11u11) bullseye; urgency=medium
* debian/patches/git-updates.diff: update from upstream stable branch:
- debian/patches/any/local-CVE-2024-2961-iso-2022-cn-ext.patch: upstreamed.
- debian/patches/any/local-CVE-2024-33599-nscd.patch: upstreamed.
- debian/patches/any/local-CVE-2024-33600-nscd.patch: upstreamed.
- debian/patches/any/local-CVE-2024-33601-33602-nscd.diff: upstreamed.
- Fixes ffsll() performance issue depending on code alignment.
- Performance improvements for memcpy() on arm64.
- Fixes y2038 regression in nscd following CVE-2024-33601 and
CVE-2024-33602 fix.
- Fix compatibility with make 4.4.
- Fixes build with --enable-hardcoded-path-in-tests with newer linkers.
-- Aurelien Jarno <aurel32@debian.org> Thu, 15 Aug 2024 11:21:36 +0200
glibc (2.31-13+deb11u10) bullseye-security; urgency=medium
 
* debian/patches/local-CVE-2024-33599-nscd.patch: Fix a stack-based buffer
......
commit 3703c32a8d304c1ee12126134ce69be965f38000
Author: Charles Fol <folcharles@gmail.com>
Date: Thu Mar 28 12:25:38 2024 -0300
iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
ISO-2022-CN-EXT uses escape sequences to indicate character set changes
(as specified by RFC 1922). While the SOdesignation has the expected
bounds checks, neither SS2designation nor SS3designation have its;
allowing a write overflow of 1, 2, or 3 bytes with fixed values:
'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
Checked on aarch64-linux-gnu.
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit f9dc609e06b1136bb0408be9605ce7973a767ada)
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
index 8fbb67a52b..31b1cf8a9f 100644
--- a/iconvdata/Makefile
+++ b/iconvdata/Makefile
@@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
bug-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 bug-iconv14 \
- bug-iconv15
+ bug-iconv15 \
+ tst-iconv-iso-2022-cn-ext
ifeq ($(have-thread-library),yes)
tests += bug-iconv3
endif
@@ -322,6 +323,8 @@ $(objpfx)bug-iconv14.out: $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so))
$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
$(addprefix $(objpfx),$(modules.so))
+$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
$(objpfx)iconv-test.out: run-iconv-test.sh $(objpfx)gconv-modules \
$(addprefix $(objpfx),$(modules.so)) \
diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
index 947b807421..34e1010bed 100644
--- a/iconvdata/iso-2022-cn-ext.c
+++ b/iconvdata/iso-2022-cn-ext.c
@@ -575,6 +575,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert (used == CNS11643_2_set); /* XXX */ \
escseq = "*H"; \
*outptr++ = ESC; \
@@ -588,6 +594,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
{ \
const char *escseq; \
\
+ if (outptr + 4 > outend) \
+ { \
+ result = __GCONV_FULL_OUTPUT; \
+ break; \
+ } \
+ \
assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
*outptr++ = ESC; \
diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
new file mode 100644
index 0000000000..96a8765fd5
--- /dev/null
+++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
@@ -0,0 +1,128 @@
+/* Verify ISO-2022-CN-EXT does not write out of the bounds.
+ Copyright (C) 2024 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <errno.h>
+#include <iconv.h>
+#include <sys/mman.h>
+
+#include <support/xunistd.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* The test sets up a two memory page buffer with the second page marked
+ PROT_NONE to trigger a fault if the conversion writes beyond the exact
+ expected amount. Then we carry out various conversions and precisely
+ place the start of the output buffer in order to trigger a SIGSEGV if the
+ process writes anywhere between 1 and page sized bytes more (only one
+ PROT_NONE page is setup as a canary) than expected. These tests exercise
+ all three of the cases in ISO-2022-CN-EXT where the converter must switch
+ character sets and may run out of buffer space while doing the
+ operation. */
+
+static int
+do_test (void)
+{
+ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
+ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
+
+ char *ntf;
+ size_t ntfsize;
+ char *outbufbase;
+ {
+ int pgz = getpagesize ();
+ TEST_VERIFY_EXIT (pgz > 0);
+ ntfsize = 2 * pgz;
+
+ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
+ | MAP_ANONYMOUS, -1);
+ xmprotect (ntf + pgz, pgz, PROT_NONE);
+
+ outbufbase = ntf + pgz;
+ }
+
+ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
+ {
+ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
+
+ for (int i = 0; i < 9; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS2designation. */
+ {
+ char inbuf[] = "㴽 \xe3\xb4\xbd";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ /* Same as before for SS3designation. */
+ {
+ char inbuf[] = "劄 \xe5\x8a\x84";
+
+ for (int i = 0; i < 14; i++)
+ {
+ char *inp = inbuf;
+ size_t inleft = sizeof (inbuf) - 1;
+
+ char *outp = outbufbase - i;
+ size_t outleft = i;
+
+ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
+ == (size_t) -1);
+ TEST_COMPARE (errno, E2BIG);
+
+ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
+ }
+ }
+
+ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
+
+ xmunmap (ntf, ntfsize);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
commit 69c58d5ef9f584ea198bd00f7964d364d0e6b921
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:00:45 2024 +0200
CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
Using alloca matches what other caches do. The request length is
bounded by MAXKEYLEN.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa)
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index 381aa721ef..a833ef039e 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -503,12 +503,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
= (struct indataset *) mempool_alloc (db,
sizeof (*dataset) + req->key_len,
1);
- struct indataset dataset_mem;
bool cacheable = true;
if (__glibc_unlikely (dataset == NULL))
{
cacheable = false;
- dataset = &dataset_mem;
+ /* The alloca is safe because nscd_run_worker verfies that
+ key_len is not larger than MAXKEYLEN. */
+ dataset = alloca (sizeof (*dataset) + req->key_len);
}
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
commit 69c58d5ef9f584ea198bd00f7964d364d0e6b921
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:00:45 2024 +0200
CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup cache (bug 31677)
Using alloca matches what other caches do. The request length is
bounded by MAXKEYLEN.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
(cherry picked from commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa)
commit 304ce5fe466c4762b21b36c26926a4657b59b53e
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:01:07 2024 +0200
CVE-2024-33600: nscd: Do not send missing not-found response in addgetnetgrentX (bug 31678)
If we failed to add a not-found response to the cache, the dataset
point can be null, resulting in a null pointer dereference.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa)
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index a833ef039e..e936b698c4 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -148,7 +148,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
/* No such service. */
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
memset (&data, '\0', sizeof (data));
@@ -349,7 +349,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
{
cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
&key_copy);
- goto writeout;
+ goto maybe_cache_add;
}
total = buffilled;
@@ -411,14 +411,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
if (he == NULL && fd != -1)
- {
- /* We write the dataset before inserting it to the database
- since while inserting this thread might block and so would
- unnecessarily let the receiver wait. */
- writeout:
+ /* We write the dataset before inserting it to the database since
+ while inserting this thread might block and so would
+ unnecessarily let the receiver wait. */
writeall (fd, &dataset->resp, dataset->head.recsize);
- }
+ maybe_cache_add:
if (cacheable)
{
/* If necessary, we also propagate the data to disk. */
@@ -514,14 +512,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
sizeof (innetgroup_response_header),
- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
+ he == NULL ? 0 : dh->nreloads + 1,
+ result == NULL ? db->negtimeout : result->head.ttl);
/* Set the notfound status and timeout based on the result from
getnetgrent. */
- dataset->head.notfound = result->head.notfound;
+ dataset->head.notfound = result == NULL || result->head.notfound;
dataset->head.timeout = timeout;
dataset->resp.version = NSCD_VERSION;
- dataset->resp.found = result->resp.found;
+ dataset->resp.found = result != NULL && result->resp.found;
/* Until we find a matching entry the result is 0. */
dataset->resp.result = 0;
@@ -569,7 +568,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
goto out;
}
- if (he == NULL)
+ /* addgetnetgrentX may have already sent a notfound response. Do
+ not send another one. */
+ if (he == NULL && dataset->resp.found)
{
/* We write the dataset before inserting it to the database
since while inserting this thread might block and so would
commit bbf5a58ccb55679217f94de706164d15372fbbc0
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Apr 25 15:01:07 2024 +0200
CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX (bug 31680)
This avoids potential memory corruption when the underlying NSS
callback function does not use the buffer space to store all strings
(e.g., for constant strings).
Instead of custom buffer management, two scratch buffers are used.
This increases stack usage somewhat.
Scratch buffer allocation failure is handled by return -1
(an invalid timeout value) instead of terminating the process.
This fixes bug 31679.
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
(cherry picked from commit c04a21e050d64a1193a6daab872bca2528bda44b)
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
index e936b698c4..4027565202 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
+#include <scratch_buffer.h>
#include "../inet/netgroup.h"
#include "nscd.h"
@@ -66,6 +67,16 @@ struct dataset
char strdata[0];
};
+/* Send a notfound response to FD. Always returns -1 to indicate an
+ ephemeral error. */
+static time_t
+send_notfound (int fd)
+{
+ if (fd != -1)
+ TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
+ return -1;
+}
+
/* Sends a notfound message and prepares a notfound dataset to write to the
cache. Returns true if there was enough memory to allocate the dataset and
returns the dataset in DATASETP, total bytes to write in TOTALP and the
@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
total = sizeof (notfound);
timeout = time (NULL) + db->negtimeout;
- if (fd != -1)
- TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
+ send_notfound (fd);
dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
/* If we cannot permanently store the result, so be it. */
@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
return cacheable;
}
+struct addgetnetgrentX_scratch
+{
+ /* This is the result that the caller should use. It can be NULL,
+ point into buffer, or it can be in the cache. */
+ struct dataset *dataset;
+
+ struct scratch_buffer buffer;
+
+ /* Used internally in addgetnetgrentX as a staging area. */
+ struct scratch_buffer tmp;
+
+ /* Number of bytes in buffer that are actually used. */
+ size_t buffer_used;
+};
+
+static void
+addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch->dataset = NULL;
+ scratch_buffer_init (&scratch->buffer);
+ scratch_buffer_init (&scratch->tmp);
+
+ /* Reserve space for the header. */
+ scratch->buffer_used = sizeof (struct dataset);
+ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
+ "initial buffer space");
+ memset (scratch->tmp.data, 0, sizeof (struct dataset));
+}
+
+static void
+addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
+{
+ scratch_buffer_free (&scratch->buffer);
+ scratch_buffer_free (&scratch->tmp);
+}
+
+/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
+ could not be resized, otherwise a pointer to the copy. */
+static char *
+addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
+ const char *s, size_t length)
+{
+ while (true)
+ {
+ size_t remaining = scratch->buffer.length - scratch->buffer_used;
+ if (remaining >= length)
+ break;
+ if (!scratch_buffer_grow_preserve (&scratch->buffer))
+ return NULL;
+ }
+ char *copy = scratch->buffer.data + scratch->buffer_used;
+ memcpy (copy, s, length);
+ scratch->buffer_used += length;
+ return copy;
+}
+
+/* Copy S into SCRATCH, including its null terminator. Returns false
+ if SCRATCH could not be resized. */
+static bool
+addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
+{
+ if (s == NULL)
+ s = "";
+ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
+}
+
+/* Caller must initialize and free *SCRATCH. If the return value is
+ negative, this function has sent a notfound response. */
static time_t
addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
- struct datahead *dh, struct dataset **resultp,
- void **tofreep)
+ struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
{
if (__glibc_unlikely (debug_level > 0))
{
@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
char *key_copy = NULL;
struct __netgrent data;
- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
- size_t buffilled = sizeof (*dataset);
- char *buffer = NULL;
size_t nentries = 0;
size_t group_len = strlen (key) + 1;
struct name_list *first_needed
= alloca (sizeof (struct name_list) + group_len);
- *tofreep = NULL;
if (netgroup_database == NULL
&& __nss_database_lookup2 ("netgroup", NULL, NULL, &netgroup_database))
@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
memset (&data, '\0', sizeof (data));
- buffer = xmalloc (buflen);
- *tofreep = buffer;
first_needed->next = first_needed;
memcpy (first_needed->name, key, group_len);
data.needed_groups = first_needed;
@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
while (1)
{
int e;
- status = getfct.f (&data, buffer + buffilled,
- buflen - buffilled - req->key_len, &e);
+ status = getfct.f (&data, scratch->tmp.data,
+ scratch->tmp.length, &e);
if (status == NSS_STATUS_SUCCESS)
{
if (data.type == triple_val)
@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
const char *nhost = data.val.triple.host;
const char *nuser = data.val.triple.user;
const char *ndomain = data.val.triple.domain;
-
- size_t hostlen = strlen (nhost ?: "") + 1;
- size_t userlen = strlen (nuser ?: "") + 1;
- size_t domainlen = strlen (ndomain ?: "") + 1;
-
- if (nhost == NULL || nuser == NULL || ndomain == NULL
- || nhost > nuser || nuser > ndomain)
- {
- const char *last = nhost;
- if (last == NULL
- || (nuser != NULL && nuser > last))
- last = nuser;
- if (last == NULL
- || (ndomain != NULL && ndomain > last))
- last = ndomain;
-
- size_t bufused
- = (last == NULL
- ? buffilled
- : last + strlen (last) + 1 - buffer);
-
- /* We have to make temporary copies. */
- size_t needed = hostlen + userlen + domainlen;
-
- if (buflen - req->key_len - bufused < needed)
- {
- buflen += MAX (buflen, 2 * needed);
- /* Save offset in the old buffer. We don't
- bother with the NULL check here since
- we'll do that later anyway. */
- size_t nhostdiff = nhost - buffer;
- size_t nuserdiff = nuser - buffer;
- size_t ndomaindiff = ndomain - buffer;
-
- char *newbuf = xrealloc (buffer, buflen);
- /* Fix up the triplet pointers into the new
- buffer. */
- nhost = (nhost ? newbuf + nhostdiff
- : NULL);
- nuser = (nuser ? newbuf + nuserdiff
- : NULL);
- ndomain = (ndomain ? newbuf + ndomaindiff
- : NULL);
- *tofreep = buffer = newbuf;
- }
-
- nhost = memcpy (buffer + bufused,
- nhost ?: "", hostlen);
- nuser = memcpy ((char *) nhost + hostlen,
- nuser ?: "", userlen);
- ndomain = memcpy ((char *) nuser + userlen,
- ndomain ?: "", domainlen);
- }
-
- char *wp = buffer + buffilled;
- wp = memmove (wp, nhost ?: "", hostlen);
- wp += hostlen;
- wp = memmove (wp, nuser ?: "", userlen);
- wp += userlen;
- wp = memmove (wp, ndomain ?: "", domainlen);
- wp += domainlen;
- buffilled = wp - buffer;
+ if (!(addgetnetgrentX_append (scratch, nhost)
+ && addgetnetgrentX_append (scratch, nuser)
+ && addgetnetgrentX_append (scratch, ndomain)))
+ return send_notfound (fd);
++nentries;
}
else
@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
{
- buflen *= 2;
- *tofreep = buffer = xrealloc (buffer, buflen);
+ if (!scratch_buffer_grow (&scratch->tmp))
+ return send_notfound (fd);
}
else if (status == NSS_STATUS_RETURN
|| status == NSS_STATUS_NOTFOUND
@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
goto maybe_cache_add;
}
- total = buffilled;
+ /* Capture the result size without the key appended. */
+ total = scratch->buffer_used;
+
+ /* Make a copy of the key. The scratch buffer must not move after
+ this point. */
+ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
+ if (key_copy == NULL)
+ return send_notfound (fd);
/* Fill in the dataset. */
- dataset = (struct dataset *) buffer;
+ dataset = scratch->buffer.data;
timeout = datahead_init_pos (&dataset->head, total + req->key_len,
total - offsetof (struct dataset, resp),
he == NULL ? 0 : dh->nreloads + 1,
@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
dataset->resp.version = NSCD_VERSION;
dataset->resp.found = 1;
dataset->resp.nresults = nentries;
- dataset->resp.result_len = buffilled - sizeof (*dataset);
-
- assert (buflen - buffilled >= req->key_len);
- key_copy = memcpy (buffer + buffilled, key, req->key_len);
- buffilled += req->key_len;
+ dataset->resp.result_len = total - sizeof (*dataset);
/* Now we can determine whether on refill we have to create a new
record or not. */
@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
if (__glibc_likely (newp != NULL))
{
/* Adjust pointer into the memory block. */
- key_copy = (char *) newp + (key_copy - buffer);
+ key_copy = (char *) newp + (key_copy - (char *) dataset);
dataset = memcpy (newp, dataset, total + req->key_len);
cacheable = true;
@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
}
out:
- *resultp = dataset;
+ scratch->dataset = dataset;
return timeout;
}
@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
if (user != NULL)
key = (char *) rawmemchr (key, '\0') + 1;
const char *domain = *key++ ? key : NULL;
+ struct addgetnetgrentX_scratch scratch;
+
+ addgetnetgrentX_scratch_init (&scratch);
if (__glibc_unlikely (debug_level > 0))
{
@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
group, group_len,
db, uid);
time_t timeout;
- void *tofree;
if (result != NULL)
- {
- timeout = result->head.timeout;
- tofree = NULL;
- }
+ timeout = result->head.timeout;
else
{
request_header req_get =
@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
.key_len = group_len
};
timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
- &result, &tofree);
+ &scratch);
+ result = scratch.dataset;
+ if (timeout < 0)
+ goto out;
}
struct indataset
@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
}
out:
- free (tofree);
+ addgetnetgrentX_scratch_free (&scratch);
return timeout;
}
@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
const char *key, uid_t uid, struct hashentry *he,
struct datahead *dh)
{
- struct dataset *ignore;
- void *tofree;
- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
- &ignore, &tofree);
- free (tofree);
+ struct addgetnetgrentX_scratch scratch;
+ addgetnetgrentX_scratch_init (&scratch);
+ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
+ addgetnetgrentX_scratch_free (&scratch);
+ if (timeout < 0)
+ timeout = 0;
return timeout;
}
@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
.key_len = he->len
};
- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
+ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
+ he, dh);
+ if (timeout < 0)
+ timeout = 0;
+ return timeout;
}
This diff is collapsed.
......@@ -171,7 +171,3 @@ any/git-ld.so-cache-endianness-markup.diff
any/local-CVE-2021-33574-mq_notify-use-after-free.diff
any/local-CVE-2023-4911.patch
any/local-qsort-memory-corruption.patch
any/local-CVE-2024-2961-iso-2022-cn-ext.patch
any/local-CVE-2024-33599-nscd.patch
any/local-CVE-2024-33600-nscd.patch
any/local-CVE-2024-33601-33602-nscd.patch
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment