Merge pull request #23339 from poettering/sockaddr-size-limit

tree-wide: add support for connecting to AF_UNIX sockets in the file system beyond the 108ch limit
This commit is contained in:
Luca Boccassi
2022-05-21 15:09:04 +01:00
committed by GitHub
13 changed files with 123 additions and 125 deletions
+9 -11
View File
@@ -1,4 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <fcntl.h>
#include <poll.h>
#include "fd-util.h"
@@ -18,17 +20,12 @@ struct nscdInvalidateRequest {
char dbname[];
};
static const union sockaddr_union nscd_sa = {
.un.sun_family = AF_UNIX,
.un.sun_path = "/run/nscd/socket",
};
static int nscd_flush_cache_one(const char *database, usec_t end) {
size_t req_size, has_written = 0, has_read = 0, l;
struct nscdInvalidateRequest *req;
_cleanup_close_ int fd = -1;
int32_t resp;
int events;
int events, r;
assert(database);
@@ -60,11 +57,12 @@ static int nscd_flush_cache_one(const char *database, usec_t end) {
* nice way to connect() to a server synchronously with a time limit that would also cover dealing with the
* backlog limit. After all SO_RCVTIMEO and SR_SNDTIMEO don't apply to connect(), and alarm() is frickin' ugly
* and not really reasonably usable from threads-aware code.) */
if (connect(fd, &nscd_sa.sa, SOCKADDR_UN_LEN(nscd_sa.un)) < 0) {
if (errno == EAGAIN)
return log_debug_errno(errno, "nscd is overloaded (backlog limit reached) and refuses to take further connections: %m");
if (errno != EINPROGRESS)
return log_debug_errno(errno, "Failed to connect to nscd socket: %m");
r = connect_unix_path(fd, AT_FDCWD, "/run/nscd/socket");
if (r < 0) {
if (r == -EAGAIN)
return log_debug_errno(r, "nscd is overloaded (backlog limit reached) and refuses to take further connections: %m");
if (r != -EINPROGRESS)
return log_debug_errno(r, "Failed to connect to nscd socket: %m");
/* Continue in case of EINPROGRESS, but don't bother with send() or recv() until being notified that
* establishing the connection is complete. */
+15 -9
View File
@@ -271,17 +271,11 @@ static int varlink_new(Varlink **ret) {
int varlink_connect_address(Varlink **ret, const char *address) {
_cleanup_(varlink_unrefp) Varlink *v = NULL;
union sockaddr_union sockaddr;
socklen_t sockaddr_len;
int r;
assert_return(ret, -EINVAL);
assert_return(address, -EINVAL);
r = sockaddr_un_set_path(&sockaddr.un, address);
if (r < 0)
return log_debug_errno(r, "Failed to set socket address '%s': %m", address);
sockaddr_len = r;
r = varlink_new(&v);
if (r < 0)
return log_debug_errno(r, "Failed to create varlink object: %m");
@@ -292,9 +286,21 @@ int varlink_connect_address(Varlink **ret, const char *address) {
v->fd = fd_move_above_stdio(v->fd);
if (connect(v->fd, &sockaddr.sa, sockaddr_len) < 0) {
if (!IN_SET(errno, EAGAIN, EINPROGRESS))
return log_debug_errno(errno, "Failed to connect to %s: %m", address);
r = sockaddr_un_set_path(&sockaddr.un, address);
if (r < 0) {
if (r != -ENAMETOOLONG)
return log_debug_errno(r, "Failed to set socket address '%s': %m", address);
/* This is a file system path, and too long to fit into sockaddr_un. Let's connect via O_PATH
* to this socket. */
r = connect_unix_path(v->fd, AT_FDCWD, address);
} else
r = RET_NERRNO(connect(v->fd, &sockaddr.sa, r));
if (r < 0) {
if (!IN_SET(r, -EAGAIN, -EINPROGRESS))
return log_debug_errno(r, "Failed to connect to %s: %m", address);
v->connecting = true; /* We are asynchronously connecting, i.e. the connect() is being
* processed in the background. As long as that's the case the socket