From 474a6e64f2c3c17718b853b9d70e054ee8d26f37 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Mon, 20 Apr 2020 12:53:08 -0500 Subject: [PATCH] tools: Fix use of fcntl(F_SETFD) during socket activation Blindly setting FD_CLOEXEC without a read-modify-write will inadvertently clear any other intentionally-set bits, such as a proposed new bit for designating a fd that must behave in 32-bit mode. However, we cannot use our wrapper qemu_set_cloexec(), because that wrapper intentionally abort()s on failure, whereas the probe here intentionally tolerates failure to deal with incorrect socket activation gracefully. Instead, fix the code to do the proper read-modify-write. Signed-off-by: Eric Blake Message-Id: <20200420175309.75894-3-eblake@redhat.com> Reviewed-by: Peter Maydell --- util/systemd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/util/systemd.c b/util/systemd.c index 1dd0367d9a..5bcac9b401 100644 --- a/util/systemd.c +++ b/util/systemd.c @@ -23,6 +23,7 @@ unsigned int check_socket_activation(void) unsigned long nr_fds; unsigned int i; int fd; + int f; int err; s = getenv("LISTEN_PID"); @@ -54,7 +55,8 @@ unsigned int check_socket_activation(void) /* So the file descriptors don't leak into child processes. */ for (i = 0; i < nr_fds; ++i) { fd = FIRST_SOCKET_ACTIVATION_FD + i; - if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) { + f = fcntl(fd, F_GETFD); + if (f == -1 || fcntl(fd, F_SETFD, f | FD_CLOEXEC) == -1) { /* If we cannot set FD_CLOEXEC then it probably means the file * descriptor is invalid, so socket activation has gone wrong * and we should exit.