Skip to content
Snippets Groups Projects
Commit 19dbc1a9 authored by Rocky Automation's avatar Rocky Automation :tv:
Browse files

import glibc-2.34-125.el9_5.1

parent c3b44e5b
No related branches found
Tags imports/r9/glibc-2.34-125.el9_5.1
No related merge requests found
Showing
with 3543 additions and 0 deletions
commit 3a83f79024cc023a74c3892a1673542e8e972485
Author: Sergey Kolosov <skolosov@redhat.com>
Date: Wed Apr 10 17:58:05 2024 +0200
socket: Add new test for connect
This commit adds a simple bind/accept/connect test for an IPv4 TCP
connection to a local process via the loopback interface.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
diff -Nrup a/socket/Makefile b/socket/Makefile
--- a/socket/Makefile 2024-05-19 21:52:59.775055152 -0400
+++ b/socket/Makefile 2024-05-19 22:05:27.717703460 -0400
@@ -33,8 +33,9 @@ routines := accept bind connect getpeern
tests := \
tst-accept4 \
- tst-sockopt \
tst-cmsghdr \
+ tst-connect \
+ tst-sockopt \
# tests
tests-internal := \
diff -Nrup a/socket/tst-connect.c b/socket/tst-connect.c
--- a/socket/tst-connect.c 1969-12-31 19:00:00.000000000 -0500
+++ b/socket/tst-connect.c 2024-05-19 21:58:22.069058144 -0400
@@ -0,0 +1,113 @@
+/* Test the connect function.
+ 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 <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <support/check.h>
+#include <support/xsocket.h>
+#include <support/xunistd.h>
+#include <sys/socket.h>
+#include <stdio.h>
+
+static struct sockaddr_in server_address;
+
+int
+open_socket_inet_tcp (void)
+{
+ int fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (fd < 0)
+ {
+ if (errno == EAFNOSUPPORT)
+ FAIL_UNSUPPORTED ("The host does not support IPv4");
+ else
+ FAIL_EXIT1 ("socket (AF_INET, SOCK_STREAM, IPPROTO_TCP): %m\n");
+ }
+ return fd;
+}
+
+static pid_t
+start_server (void)
+{
+ server_address.sin_family = AF_INET;
+ server_address.sin_port = 0;
+ server_address.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+
+ int server_sock = open_socket_inet_tcp ();
+
+ xbind (server_sock, (struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ socklen_t sa_len = sizeof (server_address);
+ xgetsockname (server_sock, (struct sockaddr *) &server_address, &sa_len);
+ xlisten (server_sock, 5);
+
+ pid_t my_pid = xfork ();
+ if (my_pid > 0)
+ {
+ xclose (server_sock);
+ return my_pid;
+ }
+
+ struct sockaddr_in client_address;
+ socklen_t ca_len = sizeof (server_address);
+ int client_sock = xaccept (server_sock, (struct sockaddr *) &client_address,
+ &ca_len);
+ printf ("socket accepted %d\n", client_sock);
+
+ _exit (0);
+}
+
+static int
+do_test (void)
+{
+ pid_t serv_pid;
+ struct sockaddr_in peer;
+ socklen_t peer_len;
+
+ serv_pid = start_server ();
+ int client_sock = open_socket_inet_tcp ();
+ xconnect (client_sock, (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+
+ /* A second connect with same arguments should fail with EISCONN. */
+ int result = connect (client_sock,
+ (const struct sockaddr *) &server_address,
+ sizeof (server_address));
+ if (result == 0 || errno != EISCONN)
+ FAIL_EXIT1 ("Second connect (%d), should fail with EISCONN: %m",
+ client_sock);
+
+ peer_len = sizeof (peer);
+ xgetpeername (client_sock, (struct sockaddr *) &peer, &peer_len);
+ TEST_COMPARE (peer_len, sizeof (peer));
+ TEST_COMPARE (peer.sin_port, server_address.sin_port);
+ TEST_COMPARE_BLOB (&peer.sin_addr, sizeof (peer.sin_addr),
+ &server_address.sin_addr,
+ sizeof (server_address.sin_addr));
+
+ int status;
+ xwaitpid (serv_pid, &status, 0);
+ TEST_COMPARE (status, 0);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
commit 6687a6e3f962759536a8019d31c68c1009ccd6eb
Author: Sergey Kolosov <skolosov@redhat.com>
Date: Wed Apr 10 17:58:04 2024 +0200
libsupport: Add xgetpeername
The patch adds redirections for getpeername.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
diff -Nrup a/support/Makefile b/support/Makefile
--- a/support/Makefile 2024-05-19 23:27:12.379362736 -0400
+++ b/support/Makefile 2024-05-19 23:29:28.668182089 -0400
@@ -126,6 +126,7 @@ libsupport-routines = \
xfork \
xftruncate \
xgetline \
+ xgetpeername \
xgetsockname \
xlisten \
xlseek \
diff -Nrup a/support/xgetpeername.c b/support/xgetpeername.c
--- a/support/xgetpeername.c 1969-12-31 19:00:00.000000000 -0500
+++ b/support/xgetpeername.c 2024-05-19 23:30:31.852561947 -0400
@@ -0,0 +1,30 @@
+/* getpeername with error checking.
+ 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 <support/xsocket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+void
+xgetpeername (int fd, struct sockaddr *sa, socklen_t *plen)
+{
+ if (getpeername (fd, sa, plen) != 0)
+ FAIL_EXIT1 ("getpeername (%d): %m", fd);
+}
diff -Nrup a/support/xsocket.h b/support/xsocket.h
--- a/support/xsocket.h 2021-08-01 21:33:43.000000000 -0400
+++ b/support/xsocket.h 2024-05-19 23:31:24.541878715 -0400
@@ -26,6 +26,7 @@
int xsocket (int, int, int);
void xsetsockopt (int, int, int, const void *, socklen_t);
void xgetsockname (int, struct sockaddr *, socklen_t *);
+void xgetpeername (int, struct sockaddr *, socklen_t *);
void xconnect (int, const struct sockaddr *, socklen_t);
void xbind (int, const struct sockaddr *, socklen_t);
void xlisten (int, int);
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 0c6e46f15c..f227dc7fa2 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -502,12 +502,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 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 c18fe111f3..e22ffa5884 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -511,14 +511,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;
@@ -566,7 +567,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 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 f227dc7fa2..c18fe111f3 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -147,7 +147,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));
@@ -348,7 +348,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;
@@ -410,14 +410,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. */
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 -Nrup glibc-2.34/nscd/netgroupcache.c b/nscd/netgroupcache.c
--- glibc-2.34/nscd/netgroupcache.c 2024-06-13 13:55:16.406511485 -0400
+++ b/nscd/netgroupcache.c 2024-06-13 13:34:45.523345077 -0400
@@ -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, in
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, in
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
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_get (nss_database_netgroup, &netgroup_database))
@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db
}
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
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
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
}
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
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
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
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
}
out:
- *resultp = dataset;
+ scratch->dataset = dataset;
return timeout;
}
@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, in
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, in
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, in
.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, in
}
out:
- free (tofree);
+ addgetnetgrentX_scratch_free (&scratch);
return timeout;
}
@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_
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, s
.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;
}
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 4b35498e3f..5fdcf4204e 100644
--- a/nscd/netgroupcache.c
+++ b/nscd/netgroupcache.c
@@ -680,8 +680,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;
commit fe06fb313bddf7e4530056897d4a706606e49377
Author: Florian Weimer <fweimer@redhat.com>
Date: Thu Aug 1 23:31:23 2024 +0200
elf: Clarify and invert second argument of _dl_allocate_tls_init
Also remove an outdated comment: _dl_allocate_tls_init is
called as part of pthread_create.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff -Nrup a/elf/dl-tls.c b/elf/dl-tls.c
--- a/elf/dl-tls.c 2024-08-27 22:51:44.720953314 -0400
+++ b/elf/dl-tls.c 2024-08-27 22:51:07.686759191 -0400
@@ -558,9 +558,14 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_m
/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage
for the TLS space. The DTV may be resized, and so this function may
call malloc to allocate that space. The loader's GL(dl_load_tls_lock)
- is taken when manipulating global TLS-related data in the loader. */
+ is taken when manipulating global TLS-related data in the loader.
+
+ If MAIN_THREAD, this is the first call during process
+ initialization. In this case, TLS initialization for secondary
+ (audit) namespaces is skipped because that has already been handled
+ by dlopen. */
void *
-_dl_allocate_tls_init (void *result, bool init_tls)
+_dl_allocate_tls_init (void *result, bool main_thread)
{
if (result == NULL)
/* The memory allocation failed. */
@@ -639,7 +644,7 @@ _dl_allocate_tls_init (void *result, boo
because it would already be set by the audit setup. However,
subsequent thread creation would need to follow the default
behaviour. */
- if (map->l_ns != LM_ID_BASE && !init_tls)
+ if (map->l_ns != LM_ID_BASE && main_thread)
continue;
memset (__mempcpy (dest, map->l_tls_initimage,
map->l_tls_initimage_size), '\0',
@@ -667,7 +672,7 @@ _dl_allocate_tls (void *mem)
{
return _dl_allocate_tls_init (mem == NULL
? _dl_allocate_tls_storage ()
- : allocate_dtv (mem), true);
+ : allocate_dtv (mem), false);
}
rtld_hidden_def (_dl_allocate_tls)
diff -Nrup a/elf/rtld.c b/elf/rtld.c
--- a/elf/rtld.c 2024-08-27 22:51:44.720953314 -0400
+++ b/elf/rtld.c 2024-08-27 22:54:51.136930475 -0400
@@ -2485,7 +2485,7 @@ dl_main (const ElfW(Phdr) *phdr,
into the main thread's TLS area, which we allocated above.
Note: thread-local variables must only be accessed after completing
the next step. */
- _dl_allocate_tls_init (tcbp, false);
+ _dl_allocate_tls_init (tcbp, true);
/* And finally install it for the main thread. */
if (! tls_init_tp_called)
diff -Nrup a/nptl/allocatestack.c b/nptl/allocatestack.c
--- a/nptl/allocatestack.c 2024-08-27 22:51:43.922949131 -0400
+++ b/nptl/allocatestack.c 2024-08-27 22:51:07.687759197 -0400
@@ -137,7 +137,7 @@ get_cached_stack (size_t *sizep, void **
memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
/* Re-initialize the TLS. */
- _dl_allocate_tls_init (TLS_TPADJ (result), true);
+ _dl_allocate_tls_init (TLS_TPADJ (result), false);
return result;
}
diff -Nrup a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
--- a/sysdeps/generic/ldsodefs.h 2024-08-27 22:51:44.720953314 -0400
+++ b/sysdeps/generic/ldsodefs.h 2024-08-27 22:56:44.425524320 -0400
@@ -1258,10 +1258,8 @@ extern void _dl_get_tls_static_info (siz
extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
-/* These are internal entry points to the two halves of _dl_allocate_tls,
- only used within rtld.c itself at startup time. */
extern void *_dl_allocate_tls_storage (void) attribute_hidden;
-extern void *_dl_allocate_tls_init (void *, bool);
+extern void *_dl_allocate_tls_init (void *result, bool main_thread);
rtld_hidden_proto (_dl_allocate_tls_init)
/* Deallocate memory allocated with _dl_allocate_tls. */
This diff is collapsed.
Author: Patsy Griffin <patsy@redhat.com>
Fix a typo in naming tst-dlopen-tlsreinit1.out
diff -Nrup a/elf/Makefile b/elf/Makefile
--- a/elf/Makefile 2024-08-16 13:27:00.700921146 -0400
+++ b/elf/Makefile 2024-08-16 13:29:12.951628406 -0400
@@ -2802,7 +2802,7 @@ $(objpfx)tst-dlopen-tlsreinit4: \
# tst-dlopen-tlsreinitmod3.so. The dependency is provided via
# $(objpfx)tst-dlopen-tlsreinitmod1.so.
tst-dlopen-tlsreinitmod2.so-no-z-defs = yes
-$(objpfx)tst-dlopen-tlsreinit.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
+$(objpfx)tst-dlopen-tlsreinit1.out: $(objpfx)tst-dlopen-tlsreinitmod1.so \
$(objpfx)tst-dlopen-tlsreinitmod2.so $(objpfx)tst-dlopen-tlsreinitmod3.so
# Reuse an audit module which provides ample debug logging.
$(objpfx)tst-dlopen-tlsreinit3.out: $(objpfx)tst-auditmod1.so
This diff is collapsed.
This diff is collapsed.
commit cf0ca8d52e1653d4aa4311a4649af8dc541ce6b4
Author: Joseph Myers <josmyers@redhat.com>
Date: Mon May 20 13:10:31 2024 +0000
Update syscall lists for Linux 6.9
Linux 6.9 has no new syscalls. Update the version number in
syscall-names.list to reflect that it is still current for 6.9.
Tested with build-many-glibcs.py.
Modified for RHEL by: Patsy Griffin <patsy@redhat.com>
diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list
index 6557bcfde4..672d39eaad 100644
--- a/sysdeps/unix/sysv/linux/syscall-names.list
+++ b/sysdeps/unix/sysv/linux/syscall-names.list
@@ -21,8 +21,8 @@
# This file can list all potential system calls. The names are only
# used if the installed kernel headers also provide them.
-# The list of system calls is current as of Linux 6.8.
-kernel 6.8
+# The list of system calls is current as of Linux 6.9.
+kernel 6.9
FAST_atomic_update
FAST_cmpxchg
From cb8c78b2ffa0b77ae453b2d328d7e2fe5186ef2a Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue, 31 Oct 2023 13:32:35 -0300
Subject: linux: Add MMAP_ABOVE4G from Linux 6.6 to sys/mman.h
x86 added the flag (29f890d1050fc099f) for CET enabled.
Also update tst-mman-consts.py test.
Conflicts:
sysdeps/unix/sysv/linux/tst-mman-consts.py
(removed patch to keep alerting about kernel differences)
sysdeps/unix/sysv/linux/x86/bits/mman.h
(adapted to missing __USE_MISC conditional upstream)
diff -rup a/sysdeps/unix/sysv/linux/x86/bits/mman.h b/sysdeps/unix/sysv/linux/x86/bits/mman.h
--- a/sysdeps/unix/sysv/linux/x86/bits/mman.h 2021-08-01 21:33:43.000000000 -0400
+++ b/sysdeps/unix/sysv/linux/x86/bits/mman.h 2024-05-29 14:03:12.426182715 -0400
@@ -26,6 +26,7 @@
/* Other flags. */
#ifdef __USE_MISC
# define MAP_32BIT 0x40 /* Only give out 32-bit addresses. */
+# define MAP_ABOVE4G 0x80 /* Only map above 4GB. */
#endif
#include <bits/mman-map-flags-generic.h>
commit afe42e935b3ee97bac9a7064157587777259c60e
Author: Florian Weimer <fweimer@redhat.com>
Date: Mon Jun 3 10:49:40 2024 +0200
elf: Avoid some free (NULL) calls in _dl_update_slotinfo
This has been confirmed to work around some interposed mallocs. Here
is a discussion of the impact test ust/libc-wrapper/test_libc-wrapper
in lttng-tools:
New TLS usage in libgcc_s.so.1, compatibility impact
<https://inbox.sourceware.org/libc-alpha/8734v1ieke.fsf@oldenburg.str.redhat.com/>
Reportedly, this patch also papers over a similar issue when tcmalloc
2.9.1 is not compiled with -ftls-model=initial-exec. Of course the
goal really should be to compile mallocs with the initial-exec TLS
model, but this commit appears to be a useful interim workaround.
Fixes commit d2123d68275acc0f061e73d5f86ca504e0d5a344 ("elf: Fix slow
tls access after dlopen [BZ #19924]").
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 7b3dd9ab60..670dbc42fc 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -819,7 +819,14 @@ _dl_update_slotinfo (unsigned long int req_modid, size_t new_gen)
dtv entry free it. Note: this is not AS-safe. */
/* XXX Ideally we will at some point create a memory
pool. */
- free (dtv[modid].pointer.to_free);
+ /* Avoid calling free on a null pointer. Some mallocs
+ incorrectly use dynamic TLS, and depending on how the
+ free function was compiled, it could call
+ __tls_get_addr before the null pointer check in the
+ free implementation. Checking here papers over at
+ least some dynamic TLS usage by interposed mallocs. */
+ if (dtv[modid].pointer.to_free != NULL)
+ free (dtv[modid].pointer.to_free);
dtv[modid].pointer.val = TLS_DTV_UNALLOCATED;
dtv[modid].pointer.to_free = NULL;
This diff is collapsed.
commit 0e16db440cc73d2cdd94e439c0efa1ec43d92b2a
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 13 15:52:34 2024 +0200
manual: Document generic printf error codes
Describe EOVERFLOW, ENOMEN, EILSEQ.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 567f6780011f9db1..41298b87a4a6c7d9 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2318,6 +2318,29 @@ the easiest way to make sure you have all the right prototypes is to
just include @file{stdio.h}.
@pindex stdio.h
+The @code{printf} family shares the error codes listed below.
+Individual functions may report additional @code{errno} values if they
+fail.
+
+@table @code
+@item EOVERFLOW
+The number of written bytes would have exceeded @code{INT_MAX}, and thus
+could not be represented in the return type @code{int}.
+
+@item ENOMEM
+The function could not allocate memory during processing. Long argument
+lists and certain floating point conversions may require memory
+allocation, as does initialization of an output stream upon first use.
+
+@item EILSEQ
+POSIX specifies this error code should be used if a wide character is
+encountered that does not have a matching valid character. @Theglibc{}
+always performs transliteration, using a replacement character if
+necessary, so this error condition cannot occur on output. However,
+@theglibc{} uses @code{EILSEQ} to indicate that an input character
+sequence (wide or multi-byte) could not be converted successfully.
+@end table
+
@deftypefun int printf (const char *@var{template}, @dots{})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{@mtslocale{}}@asunsafe{@asucorrupt{} @ascuheap{}}@acunsafe{@acsmem{} @aculock{} @acucorrupt{}}}
commit 2be0572f3a41d5d5a8bb3b2b04244b7c01ac0f58
Author: Florian Weimer <fweimer@redhat.com>
Date: Tue Aug 13 15:52:34 2024 +0200
manual: Document dprintf and vdprintf
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 41298b87a4a6c7d9..d3d855fc62b8768b 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -2483,6 +2483,26 @@ store the result in which case @code{-1} is returned. This was
changed in order to comply with the @w{ISO C99} standard.
@end deftypefun
+@deftypefun dprintf (int @var{fd}, @var{template}, ...)
+@standards{POSIX, stdio.h}
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+This function formats its arguments according to @var{template} and
+writes the result to the file descriptor @var{fd}, using the
+@code{write} function. It returns the number of bytes written, or a
+negative value if there was an error. In the error case, @code{errno}
+is set appropriately. The possible @code{errno} values depend on the
+type of the file descriptor @var{fd}, in addition to the general
+@code{printf} error codes.
+
+The number of calls to @code{write} is unspecified, and some @code{write}
+calls may have happened even if @code{dprintf} returns with an error.
+
+@strong{Portability Note:} POSIX does not require that this function is
+async-signal-safe, and @theglibc{} implementation is not. However, some
+other systems offer this function as an async-signal-safe alternative to
+@code{fprintf}. @xref{POSIX Safety Concepts}.
+@end deftypefun
+
@node Dynamic Output
@subsection Dynamically Allocating Formatted Output
@@ -2696,6 +2716,13 @@ The @code{obstack_vprintf} function is the equivalent of
as for @code{vprintf}.@refill
@end deftypefun
+@deftypefun int vdprintf (int @var{fd}, const char *@var{template}, va_list @var{ap})
+@standards{POSIX, stdio.h}
+@safety{@mtsafe{@mtslocale{}}@asunsafe{@ascuheap{}}@acunsafe{@acsmem{}}}
+The @code{vdprintf} is the equivalent of @code{dprintf}, but processes
+an argument list.
+@end deftypefun
+
Here's an example showing how you might use @code{vfprintf}. This is a
function that prints error messages to the stream @code{stderr}, along
with a prefix indicating the name of the program
commit 10de4a47ef3f481592e3c62eb07bcda23e9fde4d
Author: Arjun Shankar <arjun@redhat.com>
Date: Mon Jul 29 14:30:59 2024 +0200
manual/stdio: Clarify putc and putwc
The manual entry for `putc' described what "most systems" do instead of
describing the glibc implementation and its guarantees. This commit
fixes that by warning that putc may be implemented as a macro that
double-evaluates `stream', and removing the performance claim.
Even though the current `putc' implementation does not double-evaluate
`stream', offering this obscure guarantee as an extension to what
POSIX allows does not seem very useful.
The entry for `putwc' is also edited to bring it in line with `putc'.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index fd7ed0cedc7c1a59..0c9a7ce4a9df4c05 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -903,21 +903,21 @@ This function is a GNU extension.
@deftypefun int putc (int @var{c}, FILE *@var{stream})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputc}, except that most systems implement it as
+This is just like @code{fputc}, except that it may be implemented as
a macro, making it faster. One consequence is that it may evaluate the
@var{stream} argument more than once, which is an exception to the
-general rule for macros. @code{putc} is usually the best function to
-use for writing a single character.
+general rule for macros. Therefore, @var{stream} should never be an
+expression with side-effects.
@end deftypefun
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
-This is just like @code{fputwc}, except that it can be implement as
+This is just like @code{fputwc}, except that it may be implemented as
a macro, making it faster. One consequence is that it may evaluate the
@var{stream} argument more than once, which is an exception to the
-general rule for macros. @code{putwc} is usually the best function to
-use for writing a single wide character.
+general rule for macros. Therefore, @var{stream} should never be an
+expression with side-effects.
@end deftypefun
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
commit 942670c81dc8071dd75d6213e771daa5d2084cb6
Author: Arjun Shankar <arjun@redhat.com>
Date: Tue Jul 30 11:37:57 2024 +0200
manual/stdio: Further clarify putc, putwc, getc, and getwc
This is a follow-up to 10de4a47ef3f481592e3c62eb07bcda23e9fde4d that
reworded the manual entries for putc and putwc and removed any
performance claims.
This commit further clarifies these entries and brings getc and getwc in
line with the descriptions of putc and putwc, removing any performance
claims from them as well.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
diff --git a/manual/stdio.texi b/manual/stdio.texi
index 0c9a7ce4a9df4c05..567f6780011f9db1 100644
--- a/manual/stdio.texi
+++ b/manual/stdio.texi
@@ -904,20 +904,16 @@ This function is a GNU extension.
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
This is just like @code{fputc}, except that it may be implemented as
-a macro, making it faster. One consequence is that it may evaluate the
-@var{stream} argument more than once, which is an exception to the
-general rule for macros. Therefore, @var{stream} should never be an
-expression with side-effects.
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun wint_t putwc (wchar_t @var{wc}, FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@acucorrupt{} @aculock{}}}
This is just like @code{fputwc}, except that it may be implemented as
-a macro, making it faster. One consequence is that it may evaluate the
-@var{stream} argument more than once, which is an exception to the
-general rule for macros. Therefore, @var{stream} should never be an
-expression with side-effects.
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun int putc_unlocked (int @var{c}, FILE *@var{stream})
@@ -1110,20 +1106,17 @@ This function is a GNU extension.
@deftypefun int getc (FILE *@var{stream})
@standards{ISO, stdio.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
-This is just like @code{fgetc}, except that it is permissible (and
-typical) for it to be implemented as a macro that evaluates the
-@var{stream} argument more than once. @code{getc} is often highly
-optimized, so it is usually the best function to use to read a single
-character.
+This is just like @code{fgetc}, except that it may be implemented as
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun wint_t getwc (FILE *@var{stream})
@standards{ISO, wchar.h}
@safety{@prelim{}@mtsafe{}@asunsafe{@asucorrupt{}}@acunsafe{@aculock{} @acucorrupt{}}}
-This is just like @code{fgetwc}, except that it is permissible for it to
-be implemented as a macro that evaluates the @var{stream} argument more
-than once. @code{getwc} can be highly optimized, so it is usually the
-best function to use to read a single wide character.
+This is just like @code{fgetwc}, except that it may be implemented as
+a macro and may evaluate the @var{stream} argument more than once.
+Therefore, @var{stream} should never be an expression with side-effects.
@end deftypefun
@deftypefun int getc_unlocked (FILE *@var{stream})
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