Pre Merge pull request !64 from 小龙/a7_distro_sig_20240613095925
This commit is contained in:
commit
9146d38d4e
16 changed files with 1190 additions and 1 deletions
1
dist
Normal file
1
dist
Normal file
|
@ -0,0 +1 @@
|
||||||
|
an7_9
|
2
download
Normal file
2
download
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
29a8b5d3298e42d7fc3dd74407812f26 glibc-2.17-c758a686-releng.tar.gz
|
||||||
|
d91ac2e9667310fa815c2316d542567e glibc-2.17-c758a686.tar.gz
|
Binary file not shown.
Binary file not shown.
208
glibc-RHEL-31803.patch
Normal file
208
glibc-RHEL-31803.patch
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
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>
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
iconvdata/Makefile
|
||||||
|
(usual tests conflict)
|
||||||
|
|
||||||
|
diff --git a/iconvdata/Makefile b/iconvdata/Makefile
|
||||||
|
index 6f440e3f6122f56a..f8886d0f76cdac30 100644
|
||||||
|
--- a/iconvdata/Makefile
|
||||||
|
+++ b/iconvdata/Makefile
|
||||||
|
@@ -72,7 +72,8 @@ endif
|
||||||
|
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-iconv10 bug-iconv11 bug-iconv12 bug-iconv13 \
|
||||||
|
+ tst-iconv-iso-2022-cn-ext
|
||||||
|
ifeq ($(have-thread-library),yes)
|
||||||
|
tests += bug-iconv3
|
||||||
|
endif
|
||||||
|
@@ -306,6 +307,8 @@ $(objpfx)tst-iconv4.out: $(objpfx)gconv-modules \
|
||||||
|
$(addprefix $(objpfx),$(modules.so))
|
||||||
|
$(objpfx)tst-iconv7.out: $(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 c86d8616d417f21b..661a55f1785c2bea 100644
|
||||||
|
--- a/iconvdata/iso-2022-cn-ext.c
|
||||||
|
+++ b/iconvdata/iso-2022-cn-ext.c
|
||||||
|
@@ -564,6 +564,12 @@ enum
|
||||||
|
{ \
|
||||||
|
const char *escseq; \
|
||||||
|
\
|
||||||
|
+ if (outptr + 4 > outend) \
|
||||||
|
+ { \
|
||||||
|
+ result = __GCONV_FULL_OUTPUT; \
|
||||||
|
+ break; \
|
||||||
|
+ } \
|
||||||
|
+ \
|
||||||
|
assert (used == CNS11643_2_set); /* XXX */ \
|
||||||
|
escseq = "*H"; \
|
||||||
|
*outptr++ = ESC; \
|
||||||
|
@@ -577,6 +583,12 @@ enum
|
||||||
|
{ \
|
||||||
|
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 0000000000000000..96a8765fd5369681
|
||||||
|
--- /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>
|
25
glibc-RHEL-34263-1.patch
Normal file
25
glibc-RHEL-34263-1.patch
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
commit 83e43bf0b756065dc640680d90fa6f0b39425182
|
||||||
|
Author: Allan McRae <allan@archlinux.org>
|
||||||
|
Date: Mon Sep 9 20:23:35 2013 +1000
|
||||||
|
|
||||||
|
Fix nesting of ifdefs in netgroupcache.c
|
||||||
|
|
||||||
|
Fixes unclosed '{' if HAVE_SENDFILE is defined (BZ #15895).
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 5262d5e53ae7ce74..4fce79283a9badb3 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -619,10 +619,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
+#endif
|
||||||
|
{
|
||||||
|
-# ifndef __ASSUME_SENDFILE
|
||||||
|
+#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE
|
||||||
|
use_write:
|
||||||
|
-# endif
|
||||||
|
#endif
|
||||||
|
writeall (fd, &dataset->resp, sizeof (innetgroup_response_header));
|
||||||
|
}
|
30
glibc-RHEL-34263-10.patch
Normal file
30
glibc-RHEL-34263-10.patch
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
commit 4bbca1a44691a6e9adcee5c6798a707b626bc331
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu May 2 17:06:19 2024 +0200
|
||||||
|
|
||||||
|
nscd: Use time_t for return type of addgetnetgrentX
|
||||||
|
|
||||||
|
Using int may give false results for future dates (timeouts after the
|
||||||
|
year 2028).
|
||||||
|
|
||||||
|
Fixes commit 04a21e050d64a1193a6daab872bca2528bda44b ("CVE-2024-33601,
|
||||||
|
CVE-2024-33602: nscd: netgroup: Use two buffers in addgetnetgrentX
|
||||||
|
(bug 31680)").
|
||||||
|
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 7f78d21065ec832c..e5fa919c419c52d2 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -681,8 +681,8 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
|
||||||
|
.key_len = he->len
|
||||||
|
};
|
||||||
|
|
||||||
|
- int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
|
||||||
|
- he, dh);
|
||||||
|
+ time_t timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
|
||||||
|
+ he, dh);
|
||||||
|
if (timeout < 0)
|
||||||
|
timeout = 0;
|
||||||
|
return timeout;
|
134
glibc-RHEL-34263-2.patch
Normal file
134
glibc-RHEL-34263-2.patch
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
Partial backport of the sendfile removal. This backport only
|
||||||
|
updates nscd/netgroupcache.c, to avoid future conflicts.
|
||||||
|
|
||||||
|
commit 8c78faa9ef5c6cae455739f162e4b9d690e32eca
|
||||||
|
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||||
|
Date: Wed May 16 10:51:15 2018 -0300
|
||||||
|
|
||||||
|
Fix concurrent changes on nscd aware files (BZ #23178)
|
||||||
|
|
||||||
|
As indicated by BZ#23178, concurrent access on some files read by nscd
|
||||||
|
may result non expected data send through service requisition. This is
|
||||||
|
due 'sendfile' Linux implementation where for sockets with zero-copy
|
||||||
|
support, callers must ensure the transferred portions of the the file
|
||||||
|
reffered by input file descriptor remain unmodified until the reader
|
||||||
|
on the other end of socket has consumed the transferred data.
|
||||||
|
|
||||||
|
I could not find any explicit documentation stating this behaviour on
|
||||||
|
Linux kernel documentation. However man-pages sendfile entry [1] states
|
||||||
|
in NOTES the aforementioned remark. It was initially pushed on man-pages
|
||||||
|
with an explicit testcase [2] that shows changing the file used in
|
||||||
|
'sendfile' call prior the socket input data consumption results in
|
||||||
|
previous data being lost.
|
||||||
|
|
||||||
|
From commit message it stated on tested Linux version (3.15) only TCP
|
||||||
|
socket showed this issues, however on recent kernels (4.4) I noticed the
|
||||||
|
same behaviour for local sockets as well.
|
||||||
|
|
||||||
|
Since sendfile on HURD is a read/write operation and the underlying
|
||||||
|
issue on Linux, the straightforward fix is just remove sendfile use
|
||||||
|
altogether. I am really skeptical it is hitting some hotstop (there
|
||||||
|
are indication over internet that sendfile is helpfull only for large
|
||||||
|
files, more than 10kb) here to justify that extra code complexity or
|
||||||
|
to pursuit other possible fix (through memory or file locks for
|
||||||
|
instance, which I am not sure it is doable).
|
||||||
|
|
||||||
|
Checked on x86_64-linux-gnu.
|
||||||
|
|
||||||
|
[BZ #23178]
|
||||||
|
* nscd/nscd-client.h (sendfileall): Remove prototype.
|
||||||
|
* nscd/connections.c [HAVE_SENDFILE] (sendfileall): Remove function.
|
||||||
|
(handle_request): Use writeall instead of sendfileall.
|
||||||
|
* nscd/aicache.c (addhstaiX): Likewise.
|
||||||
|
* nscd/grpcache.c (cache_addgr): Likewise.
|
||||||
|
* nscd/hstcache.c (cache_addhst): Likewise.
|
||||||
|
* nscd/initgrcache.c (addinitgroupsX): Likewise.
|
||||||
|
* nscd/netgroupcache.c (addgetnetgrentX, addinnetgrX): Likewise.
|
||||||
|
* nscd/pwdcache.c (cache_addpw): Likewise.
|
||||||
|
* nscd/servicescache.c (cache_addserv): Likewise.
|
||||||
|
* sysdeps/unix/sysv/linux/Makefile [$(subdir) == nscd]
|
||||||
|
(sysdep-CFLAGS): Remove -DHAVE_SENDFILE.
|
||||||
|
* sysdeps/unix/sysv/linux/kernel-features.h (__ASSUME_SENDFILE):
|
||||||
|
Remove define.
|
||||||
|
|
||||||
|
[1] http://man7.org/linux/man-pages/man2/sendfile.2.html
|
||||||
|
[2] https://github.com/mkerrisk/man-pages/commit/7b6a3299776b5c1c4f169a591434a855d50c68b4#diff-efd6af3a70f0f07c578e85b51e83b3c3
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 4fce79283a9badb3..7ee0c284ed58d1e3 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -415,33 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
since while inserting this thread might block and so would
|
||||||
|
unnecessarily let the receiver wait. */
|
||||||
|
writeout:
|
||||||
|
-#ifdef HAVE_SENDFILE
|
||||||
|
- if (__builtin_expect (db->mmap_used, 1) && cacheable)
|
||||||
|
- {
|
||||||
|
- assert (db->wr_fd != -1);
|
||||||
|
- assert ((char *) &dataset->resp > (char *) db->data);
|
||||||
|
- assert ((char *) dataset - (char *) db->head + total
|
||||||
|
- <= (sizeof (struct database_pers_head)
|
||||||
|
- + db->head->module * sizeof (ref_t)
|
||||||
|
- + db->head->data_size));
|
||||||
|
-# ifndef __ASSUME_SENDFILE
|
||||||
|
- ssize_t written =
|
||||||
|
-# endif
|
||||||
|
- sendfileall (fd, db->wr_fd, (char *) &dataset->resp
|
||||||
|
- - (char *) db->head, dataset->head.recsize);
|
||||||
|
-# ifndef __ASSUME_SENDFILE
|
||||||
|
- if (written == -1 && errno == ENOSYS)
|
||||||
|
- goto use_write;
|
||||||
|
-# endif
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
-#endif
|
||||||
|
- {
|
||||||
|
-#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE
|
||||||
|
- use_write:
|
||||||
|
-#endif
|
||||||
|
- writeall (fd, &dataset->resp, dataset->head.recsize);
|
||||||
|
- }
|
||||||
|
+ writeall (fd, &dataset->resp, dataset->head.recsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheable)
|
||||||
|
@@ -596,36 +570,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
/* 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. */
|
||||||
|
- assert (fd != -1);
|
||||||
|
+ assert (fd != -1);
|
||||||
|
|
||||||
|
-#ifdef HAVE_SENDFILE
|
||||||
|
- if (__builtin_expect (db->mmap_used, 1) && cacheable)
|
||||||
|
- {
|
||||||
|
- assert (db->wr_fd != -1);
|
||||||
|
- assert ((char *) &dataset->resp > (char *) db->data);
|
||||||
|
- assert ((char *) dataset - (char *) db->head + sizeof (*dataset)
|
||||||
|
- <= (sizeof (struct database_pers_head)
|
||||||
|
- + db->head->module * sizeof (ref_t)
|
||||||
|
- + db->head->data_size));
|
||||||
|
-# ifndef __ASSUME_SENDFILE
|
||||||
|
- ssize_t written =
|
||||||
|
-# endif
|
||||||
|
- sendfileall (fd, db->wr_fd,
|
||||||
|
- (char *) &dataset->resp - (char *) db->head,
|
||||||
|
- sizeof (innetgroup_response_header));
|
||||||
|
-# ifndef __ASSUME_SENDFILE
|
||||||
|
- if (written == -1 && errno == ENOSYS)
|
||||||
|
- goto use_write;
|
||||||
|
-# endif
|
||||||
|
- }
|
||||||
|
- else
|
||||||
|
-#endif
|
||||||
|
- {
|
||||||
|
-#if defined HAVE_SENDFILE && !defined __ASSUME_SENDFILE
|
||||||
|
- use_write:
|
||||||
|
-#endif
|
||||||
|
- writeall (fd, &dataset->resp, sizeof (innetgroup_response_header));
|
||||||
|
- }
|
||||||
|
+ writeall (fd, &dataset->resp, sizeof (innetgroup_response_header));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheable)
|
61
glibc-RHEL-34263-3.patch
Normal file
61
glibc-RHEL-34263-3.patch
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
Partial backport of the following commit, restricted to the
|
||||||
|
netgroup changes:
|
||||||
|
|
||||||
|
commit c6dfed243e0310bc3294c0fdf1816fceab024e9b
|
||||||
|
Author: Roland McGrath <roland@hack.frob.com>
|
||||||
|
Date: Wed Oct 22 13:17:20 2014 -0700
|
||||||
|
|
||||||
|
Rework some nscd code not to use variable-length struct types.
|
||||||
|
|
||||||
|
diff --git a/inet/netgroup.h b/inet/netgroup.h
|
||||||
|
index f3797a698d126157..fa1732762e32c2c0 100644
|
||||||
|
--- a/inet/netgroup.h
|
||||||
|
+++ b/inet/netgroup.h
|
||||||
|
@@ -26,7 +26,7 @@
|
||||||
|
struct name_list
|
||||||
|
{
|
||||||
|
struct name_list *next;
|
||||||
|
- char name[0];
|
||||||
|
+ char name[];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 7ee0c284ed58d1e3..7d7269a8edf1b99d 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -21,6 +21,7 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
+#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
@@ -136,11 +137,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
char *buffer = NULL;
|
||||||
|
size_t nentries = 0;
|
||||||
|
size_t group_len = strlen (key) + 1;
|
||||||
|
- union
|
||||||
|
- {
|
||||||
|
- struct name_list elem;
|
||||||
|
- char mem[sizeof (struct name_list) + group_len];
|
||||||
|
- } first_needed;
|
||||||
|
+ struct name_list *first_needed
|
||||||
|
+ = alloca (sizeof (struct name_list) + group_len);
|
||||||
|
|
||||||
|
if (netgroup_database == NULL
|
||||||
|
&& __nss_database_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
||||||
|
@@ -153,9 +151,9 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
|
||||||
|
memset (&data, '\0', sizeof (data));
|
||||||
|
buffer = xmalloc (buflen);
|
||||||
|
- first_needed.elem.next = &first_needed.elem;
|
||||||
|
- memcpy (first_needed.elem.name, key, group_len);
|
||||||
|
- data.needed_groups = &first_needed.elem;
|
||||||
|
+ first_needed->next = first_needed;
|
||||||
|
+ memcpy (first_needed->name, key, group_len);
|
||||||
|
+ data.needed_groups = first_needed;
|
||||||
|
|
||||||
|
while (data.needed_groups != NULL)
|
||||||
|
{
|
133
glibc-RHEL-34263-4.patch
Normal file
133
glibc-RHEL-34263-4.patch
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
commit 745664bd798ec8fd50438605948eea594179fba1
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Tue Aug 28 13:19:27 2018 +0200
|
||||||
|
|
||||||
|
nscd: Fix use-after-free in addgetnetgrentX [BZ #23520]
|
||||||
|
|
||||||
|
addinnetgrX may use the heap-allocated buffer, so free the buffer
|
||||||
|
in this function.
|
||||||
|
|
||||||
|
Conflicts:
|
||||||
|
nscd/netgroupcache.c
|
||||||
|
(different backport order)
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 7d7269a8edf1b99d..d234eb5ac48c73f2 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -113,7 +113,8 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
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)
|
||||||
|
+ struct datahead *dh, struct dataset **resultp,
|
||||||
|
+ void **tofreep)
|
||||||
|
{
|
||||||
|
if (__builtin_expect (debug_level > 0, 0))
|
||||||
|
{
|
||||||
|
@@ -139,6 +140,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
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_lookup ("netgroup", NULL, NULL, &netgroup_database))
|
||||||
|
@@ -151,6 +153,7 @@ 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;
|
||||||
|
@@ -439,8 +442,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
- free (buffer);
|
||||||
|
-
|
||||||
|
*resultp = dataset;
|
||||||
|
|
||||||
|
return timeout;
|
||||||
|
@@ -477,8 +478,12 @@ 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;
|
||||||
|
+ {
|
||||||
|
+ timeout = result->head.timeout;
|
||||||
|
+ tofree = NULL;
|
||||||
|
+ }
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request_header req_get =
|
||||||
|
@@ -487,7 +492,7 @@ 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);
|
||||||
|
+ &result, &tofree);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct indataset
|
||||||
|
@@ -559,8 +564,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
dh->ttl = dataset->head.ttl;
|
||||||
|
++dh->nreloads;
|
||||||
|
if (cacheable)
|
||||||
|
- pthread_rwlock_unlock (&db->lock);
|
||||||
|
- return timeout;
|
||||||
|
+ pthread_rwlock_unlock (&db->lock);
|
||||||
|
+ goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (he == NULL)
|
||||||
|
@@ -596,17 +601,30 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
dh->usable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ out:
|
||||||
|
+ free (tofree);
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
+static time_t
|
||||||
|
+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);
|
||||||
|
+ return timeout;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
void
|
||||||
|
addgetnetgrent (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
void *key, uid_t uid)
|
||||||
|
{
|
||||||
|
- struct dataset *ignore;
|
||||||
|
-
|
||||||
|
- addgetnetgrentX (db, fd, req, key, uid, NULL, NULL, &ignore);
|
||||||
|
+ addgetnetgrentX_ignore (db, fd, req, key, uid, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -619,10 +637,8 @@ readdgetnetgrent (struct database_dyn *db, struct hashentry *he,
|
||||||
|
.type = GETNETGRENT,
|
||||||
|
.key_len = he->len
|
||||||
|
};
|
||||||
|
- struct dataset *ignore;
|
||||||
|
-
|
||||||
|
- return addgetnetgrentX (db, -1, &req, db->data + he->key, he->owner, he, dh,
|
||||||
|
- &ignore);
|
||||||
|
+ return addgetnetgrentX_ignore
|
||||||
|
+ (db, -1, &req, db->data + he->key, he->owner, he, dh);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
39
glibc-RHEL-34263-5.patch
Normal file
39
glibc-RHEL-34263-5.patch
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
commit dca565886b5e8bd7966e15f0ca42ee5cff686673
|
||||||
|
Author: DJ Delorie <dj@redhat.com>
|
||||||
|
Date: Thu Feb 25 16:08:21 2021 -0500
|
||||||
|
|
||||||
|
nscd: Fix double free in netgroupcache [BZ #27462]
|
||||||
|
|
||||||
|
In commit 745664bd798ec8fd50438605948eea594179fba1 a use-after-free
|
||||||
|
was fixed, but this led to an occasional double-free. This patch
|
||||||
|
tracks the "live" allocation better.
|
||||||
|
|
||||||
|
Tested manually by a third party.
|
||||||
|
|
||||||
|
Related: RHBZ 1927877
|
||||||
|
|
||||||
|
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||||
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index d234eb5ac48c73f2..e388ff91fea46e0c 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -248,7 +248,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
: NULL);
|
||||||
|
ndomain = (ndomain ? newbuf + ndomaindiff
|
||||||
|
: NULL);
|
||||||
|
- buffer = newbuf;
|
||||||
|
+ *tofreep = buffer = newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
nhost = memcpy (buffer + bufused,
|
||||||
|
@@ -319,7 +319,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
|
||||||
|
else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
|
||||||
|
{
|
||||||
|
buflen *= 2;
|
||||||
|
- buffer = xrealloc (buffer, buflen);
|
||||||
|
+ *tofreep = buffer = xrealloc (buffer, buflen);
|
||||||
|
}
|
||||||
|
else if (status == NSS_STATUS_RETURN
|
||||||
|
|| status == NSS_STATUS_NOTFOUND
|
31
glibc-RHEL-34263-6.patch
Normal file
31
glibc-RHEL-34263-6.patch
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
commit 87801a8fd06db1d654eea3e4f7626ff476a9bdaa
|
||||||
|
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>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index e388ff91fea46e0c..0a9d864109cdd8cd 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 (__builtin_expect (dataset == NULL, 0))
|
||||||
|
{
|
||||||
|
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,
|
52
glibc-RHEL-34263-7.patch
Normal file
52
glibc-RHEL-34263-7.patch
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
commit 7835b00dbce53c3c87bbbb1754a95fb5e58187aa
|
||||||
|
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>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 0a9d864109cdd8cd..d53c473c3e5139b8 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. */
|
53
glibc-RHEL-34263-8.patch
Normal file
53
glibc-RHEL-34263-8.patch
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
commit b048a482f088e53144d26a61c390bed0210f49f2
|
||||||
|
Author: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Thu Apr 25 15:01:07 2024 +0200
|
||||||
|
|
||||||
|
CVE-2024-33600: nscd: Avoid null pointer crashes after notfound response (bug 31678)
|
||||||
|
|
||||||
|
The addgetnetgrentX call in addinnetgrX may have failed to produce
|
||||||
|
a result, so the result variable in addinnetgrX can be NULL.
|
||||||
|
Use db->negtimeout as the fallback value if there is no result data;
|
||||||
|
the timeout is also overwritten below.
|
||||||
|
|
||||||
|
Also avoid sending a second not-found response. (The client
|
||||||
|
disconnects after receiving the first response, so the data stream did
|
||||||
|
not go out of sync even without this fix.) It is still beneficial to
|
||||||
|
add the negative response to the mapping, so that the client can get
|
||||||
|
it from there in the future, instead of going through the socket.
|
||||||
|
|
||||||
|
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index d53c473c3e5139b8..07f23a75d76e652c 100644
|
||||||
|
--- a/nscd/netgroupcache.c
|
||||||
|
+++ b/nscd/netgroupcache.c
|
||||||
|
@@ -512,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;
|
||||||
|
|
||||||
|
@@ -567,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
|
383
glibc-RHEL-34263-9.patch
Normal file
383
glibc-RHEL-34263-9.patch
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
commit c04a21e050d64a1193a6daab872bca2528bda44b
|
||||||
|
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>
|
||||||
|
|
||||||
|
diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
|
||||||
|
index 07f23a75d76e652c..7f78d21065ec832c 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, ¬found, 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, ¬found, 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 (__builtin_expect (debug_level > 0, 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_lookup ("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 (__builtin_expect (newp != NULL, 1))
|
||||||
|
{
|
||||||
|
/* 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 (__builtin_expect (debug_level > 0, 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;
|
||||||
|
}
|
39
glibc.spec
39
glibc.spec
|
@ -125,7 +125,7 @@
|
||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
Name: glibc
|
Name: glibc
|
||||||
Version: %{glibcversion}
|
Version: %{glibcversion}
|
||||||
Release: %{glibcrelease}
|
Release: %{glibcrelease}.3
|
||||||
# GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
|
# GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
|
||||||
# Things that are linked directly into dynamically linked programs
|
# Things that are linked directly into dynamically linked programs
|
||||||
# and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
|
# and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
|
||||||
|
@ -1644,6 +1644,17 @@ Patch2861: glibc-rh1927536.patch
|
||||||
Patch2862: glibc-rh1993930.patch
|
Patch2862: glibc-rh1993930.patch
|
||||||
Patch2863: glibc-rh2065058-1.patch
|
Patch2863: glibc-rh2065058-1.patch
|
||||||
Patch2864: glibc-rh2065058-2.patch
|
Patch2864: glibc-rh2065058-2.patch
|
||||||
|
Patch20671: glibc-RHEL-31803.patch
|
||||||
|
Patch20672: glibc-RHEL-34263-1.patch
|
||||||
|
Patch20673: glibc-RHEL-34263-2.patch
|
||||||
|
Patch20674: glibc-RHEL-34263-3.patch
|
||||||
|
Patch20675: glibc-RHEL-34263-4.patch
|
||||||
|
Patch20676: glibc-RHEL-34263-5.patch
|
||||||
|
Patch20677: glibc-RHEL-34263-6.patch
|
||||||
|
Patch20678: glibc-RHEL-34263-7.patch
|
||||||
|
Patch20679: glibc-RHEL-34263-8.patch
|
||||||
|
Patch20680: glibc-RHEL-34263-9.patch
|
||||||
|
Patch20681: glibc-RHEL-34263-10.patch
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# End of glibc patches.
|
# End of glibc patches.
|
||||||
|
@ -3018,6 +3029,17 @@ package or when debugging this package.
|
||||||
%patch2862 -p1
|
%patch2862 -p1
|
||||||
%patch2863 -p1
|
%patch2863 -p1
|
||||||
%patch2864 -p1
|
%patch2864 -p1
|
||||||
|
%patch -P 20671 -p1
|
||||||
|
%patch -P 20672 -p1
|
||||||
|
%patch -P 20673 -p1
|
||||||
|
%patch -P 20674 -p1
|
||||||
|
%patch -P 20675 -p1
|
||||||
|
%patch -P 20676 -p1
|
||||||
|
%patch -P 20677 -p1
|
||||||
|
%patch -P 20678 -p1
|
||||||
|
%patch -P 20679 -p1
|
||||||
|
%patch -P 20680 -p1
|
||||||
|
%patch -P 20681 -p1
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
# %%prep - Additional prep required...
|
# %%prep - Additional prep required...
|
||||||
|
@ -4205,6 +4227,21 @@ rm -f *.filelist*
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu May 2 2024 Florian Weimer <fweimer@redhat.com> - 2.17-326.3
|
||||||
|
- nscd: Fix timeout type in netgroup cache (RHEL-34263)
|
||||||
|
|
||||||
|
* Tue Apr 30 2024 Florian Weimer <fweimer@redhat.com> - 2.17-326.2
|
||||||
|
- nscd: Do not use sendfile for the netgroup cache
|
||||||
|
- nscd: Use-after-free in netgroup cache
|
||||||
|
- CVE-2021-27645: nscd: double-free in netgroup cache
|
||||||
|
- CVE-2024-33599: nscd: buffer overflow in netgroup cache (RHEL-34263)
|
||||||
|
- CVE-2024-33600: nscd: null pointer dereferences in netgroup cache
|
||||||
|
- CVE-2024-33601: nscd: crash on out-of-memory condition
|
||||||
|
- CVE-2024-33602: nscd: memory corruption with NSS netgroup modules
|
||||||
|
|
||||||
|
* Tue Apr 16 2024 Florian Weimer <fweimer@redhat.com> - 2.17-326.1
|
||||||
|
- CVE-2024-2961: Out of bounds write in iconv conversion to ISO-2022-CN-EXT (RHEL-31803)
|
||||||
|
|
||||||
* Fri Mar 18 2022 DJ Delorie <dj@redhat.com> - 2.17-326
|
* Fri Mar 18 2022 DJ Delorie <dj@redhat.com> - 2.17-326
|
||||||
- resolv: Handle DNS transaction ID collisions (#2065058)
|
- resolv: Handle DNS transaction ID collisions (#2065058)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue