diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2021-06-08 10:23:47 +0900 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2021-07-20 17:48:11 +0200 |
commit | 1f5600df9cf5c3dcd4b4ff822e2de916d137e5e2 (patch) | |
tree | 070454cc5b3085cb2031165144c56c34fd2fbdea | |
parent | e8e2c93ed92b6cace68a4fd46bb6d6404a4f1353 (diff) | |
download | systemd-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.c | 86 |
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); |