diff --git a/src/util/vircommand.c b/src/util/vircommand.c index 867f45b57b..5f094c625a 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -527,10 +527,10 @@ virCommandMassCloseGetFDsGeneric(virCommand *cmd G_GNUC_UNUSED, # endif /* !__linux__ */ static int -virCommandMassClose(virCommand *cmd, - int childin, - int childout, - int childerr) +virCommandMassCloseFrom(virCommand *cmd, + int childin, + int childout, + int childerr) { g_autoptr(virBitmap) fds = NULL; int openmax = sysconf(_SC_OPEN_MAX); @@ -597,6 +597,75 @@ virCommandMassClose(virCommand *cmd, } +static int +virCommandMassCloseRange(virCommand *cmd, + int childin, + int childout, + int childerr) +{ + g_autoptr(virBitmap) fds = virBitmapNew(0); + ssize_t first; + ssize_t last; + size_t i; + + virBitmapSetBitExpand(fds, childin); + virBitmapSetBitExpand(fds, childout); + virBitmapSetBitExpand(fds, childerr); + + for (i = 0; i < cmd->npassfd; i++) { + int fd = cmd->passfd[i].fd; + + virBitmapSetBitExpand(fds, fd); + + if (virSetInherit(fd, true) < 0) { + virReportSystemError(errno, _("failed to preserve fd %1$d"), fd); + return -1; + } + } + + first = 2; + while ((last = virBitmapNextSetBit(fds, first)) >= 0) { + if (first + 1 == last) { + first = last; + continue; + } + + /* Preserve @first and @last and close everything in between. */ + if (virCloseRange(first + 1, last - 1) < 0) { + virReportSystemError(errno, + _("Unable to mass close FDs (first=%1$zd, last=%2$zd)"), + first + 1, last - 1); + return -1; + } + + first = last; + } + + if (virCloseRange(first + 1, ~0U) < 0) { + virReportSystemError(errno, + _("Unable to mass close FDs (first=%1$zd, last=%2$d"), + first + 1, ~0U); + return -1; + } + + return 0; +} + + + +static int +virCommandMassClose(virCommand *cmd, + int childin, + int childout, + int childerr) +{ + if (virCloseRangeIsSupported()) + return virCommandMassCloseRange(cmd, childin, childout, childerr); + + return virCommandMassCloseFrom(cmd, childin, childout, childerr); +} + + /* * virExec: * @cmd virCommand * containing all information about the program to diff --git a/tests/commandtest.c b/tests/commandtest.c index 688cf59160..aa108ce583 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -1247,6 +1247,8 @@ mymain(void) setpgid(0, 0); ignore_value(setsid()); + virCloseRangeInit(); + /* Our test expects particular fd values; to get that, we must not * leak fds that we inherited from a lazy parent. At the same * time, virInitialize may open some fds (perhaps via third-party