Skip to content

Commit f09a15d

Browse files
Laurent Bercotnavi-desu
authored andcommitted
start-stop-daemon.c: fix failure case on --notify fd:4
When the created notified pipe (often on 4) is the same number as the notification fd target, dup2() does not clear the FD_CLOEXEC flag, so the fd gets closed right when exec'ing the daemon, reporting readiness failure. Fix this by explicitly testing for the case and clearing the flag when necessary. Note that this happens because of a call to close_range() right before the test. close_range() is the real problem, it should never be used and this bug is a perfect illustration of why; but getting rid of close_range() is a much more invasive change that I don't want to commit to right now, especially since navi's plan is to eventually deprecate start-stop-daemon.
1 parent aa456f3 commit f09a15d

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

src/start-stop-daemon/start-stop-daemon.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1130,13 +1130,25 @@ int main(int argc, char **argv)
11301130
|| rc_yesno(getenv("EINFO_QUIET")))
11311131
dup2(stderr_fd, STDERR_FILENO);
11321132

1133-
cloexec_fds_from(3);
1133+
cloexec_fds_from(3); /* FIXME: this is problematic, see right below */
11341134

11351135
if (notify.type == NOTIFY_FD) {
11361136
if (close(notify.pipe[0]) == -1)
11371137
eerrorx("%s: failed to close notify pipe[0]: %s", applet, strerror(errno));
11381138
if (dup2(notify.pipe[1], notify.fd) == -1)
11391139
eerrorx("%s: failed to initialize notify fd: %s", applet, strerror(errno));
1140+
1141+
/* if notify.pipe[1] == notify.fd then the FD_CLOEXEC flag is not cleared by dup2,
1142+
leading to failure. The workaround here is to clear it manually, but the
1143+
real fix is that we should never close/cloexec fds in bulk like this */
1144+
if (notify.pipe[1] == notify.fd) {
1145+
int flags = fcntl(notify.fd, F_GETFD, 0);
1146+
if (flags == -1)
1147+
eerrorx("%s: failed to get flags for notify fd: %s", applet, strerror(errno));
1148+
if (fcntl(notify.fd, F_SETFD, flags & ~FD_CLOEXEC) == -1)
1149+
eerrorx("%s: failed to set flags for notify fd: %s", applet, strerror(errno));
1150+
}
1151+
11401152
}
11411153

11421154
if (scheduler != NULL) {

0 commit comments

Comments
 (0)