summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2021-06-08 10:23:47 +0900
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2021-07-20 17:48:11 +0200
commit1f5600df9cf5c3dcd4b4ff822e2de916d137e5e2 (patch)
tree070454cc5b3085cb2031165144c56c34fd2fbdea
parente8e2c93ed92b6cace68a4fd46bb6d6404a4f1353 (diff)
downloadsystemd-1f5600df9cf5c3dcd4b4ff822e2de916d137e5e2.tar.gz
core/socket: do not assign another fd to SocketPort which already has a fd on deserialization
Otherwise, if a socket address is duplicated, then the previous fd is closed. Fixes #19843. (cherry picked from commit 3da0caf5bbf3c8cab716c4d7adf0eb25907dc951) (cherry picked from commit 11acee8a00f1e04952f86088078041849d8f9819)
-rw-r--r--src/core/socket.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/src/core/socket.c b/src/core/socket.c
index 7f8ac4eae9..13d4020509 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2634,13 +2634,6 @@ static int socket_serialize(Unit *u, FILE *f, FDSet *fds) {
return 0;
}
-static void socket_port_take_fd(SocketPort *p, FDSet *fds, int fd) {
- assert(p);
-
- safe_close(p->fd);
- p->fd = fdset_remove(fds, fd);
-}
-
static int socket_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
Socket *s = SOCKET(u);
@@ -2702,13 +2695,20 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse fifo value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_FIFO &&
+ if (p->fd < 0 &&
+ p->type == SOCKET_FIFO &&
path_equal_or_files_same(p->path, value+skip, 0)) {
- socket_port_take_fd(p, fds, fd);
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching fifo socket found: %s", value+skip);
+ }
} else if (streq(key, "special")) {
int fd, skip = 0;
@@ -2716,13 +2716,20 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse special value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_SPECIAL &&
+ if (p->fd < 0 &&
+ p->type == SOCKET_SPECIAL &&
path_equal_or_files_same(p->path, value+skip, 0)) {
- socket_port_take_fd(p, fds, fd);
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching special socket found: %s", value+skip);
+ }
} else if (streq(key, "mqueue")) {
int fd, skip = 0;
@@ -2730,13 +2737,20 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse mqueue value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_MQUEUE &&
+ if (p->fd < 0 &&
+ p->type == SOCKET_MQUEUE &&
streq(p->path, value+skip)) {
- socket_port_take_fd(p, fds, fd);
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching mqueue socket found: %s", value+skip);
+ }
} else if (streq(key, "socket")) {
int fd, type, skip = 0;
@@ -2744,12 +2758,20 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %i %n", &fd, &type, &skip) < 2 || fd < 0 || type < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (socket_address_is(&p->address, value+skip, type)) {
- socket_port_take_fd(p, fds, fd);
+ if (p->fd < 0 &&
+ socket_address_is(&p->address, value+skip, type)) {
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching %s socket found: %s",
+ socket_address_type_to_string(type), value+skip);
+ }
} else if (streq(key, "netlink")) {
int fd, skip = 0;
@@ -2757,12 +2779,19 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse socket value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (socket_address_is_netlink(&p->address, value+skip)) {
- socket_port_take_fd(p, fds, fd);
+ if (p->fd < 0 &&
+ socket_address_is_netlink(&p->address, value+skip)) {
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching netlink socket found: %s", value+skip);
+ }
} else if (streq(key, "ffs")) {
int fd, skip = 0;
@@ -2770,13 +2799,20 @@ static int socket_deserialize_item(Unit *u, const char *key, const char *value,
if (sscanf(value, "%i %n", &fd, &skip) < 1 || fd < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse ffs value: %s", value);
- else
+ else {
+ bool found = false;
+
LIST_FOREACH(port, p, s->ports)
- if (p->type == SOCKET_USB_FUNCTION &&
+ if (p->fd < 0 &&
+ p->type == SOCKET_USB_FUNCTION &&
path_equal_or_files_same(p->path, value+skip, 0)) {
- socket_port_take_fd(p, fds, fd);
+ p->fd = fdset_remove(fds, fd);
+ found = true;
break;
}
+ if (!found)
+ log_unit_debug(u, "No matching ffs socket found: %s", value+skip);
+ }
} else
log_unit_debug(UNIT(s), "Unknown serialization key: %s", key);