On Wed, Jun 21, 2023 at 04:09:09PM +0200, Michal Privoznik wrote: > As of commit v5.9-rc1~160^2~3 the Linux kernel has close_range() > syscall, which closes not just one FD but whole range. Then, in > its commit glibc-2.34~115 glibc introduced closefrom() which is > just a wrapper over close_range(), but it allows us to use > FreeBSD-only implementation on Linux too, as both OS-es now have > the same function. > > Signed-off-by: Michal Privoznik <mprivozn@xxxxxxxxxx> > --- > meson.build | 1 + > src/util/vircommand.c | 124 ++++++++++++++++++++++-------------------- > 2 files changed, 66 insertions(+), 59 deletions(-) > > diff --git a/meson.build b/meson.build > index aa391e7178..a4b52b6156 100644 > --- a/meson.build > +++ b/meson.build > @@ -573,6 +573,7 @@ libvirt_export_dynamic = cc.first_supported_link_argument([ > # check availability of various common functions (non-fatal if missing) > > functions = [ > + 'closefrom', > 'elf_aux_info', > 'explicit_bzero', > 'fallocate', > diff --git a/src/util/vircommand.c b/src/util/vircommand.c > index 49abb53c28..b8b8d48f92 100644 > --- a/src/util/vircommand.c > +++ b/src/util/vircommand.c > @@ -479,7 +479,68 @@ virExecCommon(virCommand *cmd, gid_t *groups, int ngroups) > return 0; > } > > -# ifdef __linux__ > +# ifdef WITH_CLOSEFROM > +# define USE_CLOSEFROM > +# else > +# define USE_GENERIC > +# endif > + > + > +# ifdef USE_CLOSEFROM > +static int > +virCommandMassClose(virCommand *cmd, > + int childin, > + int childout, > + int childerr) > +{ > + int lastfd = -1; > + int fd = -1; > + size_t i; > + > + /* > + * Two phases of closing. > + * > + * The first (inefficient) phase iterates over FDs, > + * preserving certain FDs we need to pass down, and > + * closing others. The number of iterations is bounded > + * to the number of the biggest FD we need to preserve. > + * > + * The second (speedy) phase uses closefrom() to cull > + * all remaining FDs in the process. > + * > + * Usually the first phase will be fairly quick only > + * processing a handful of low FD numbers, and thus using > + * closefrom() is a massive win for high ulimit() NFILES > + * values. > + */ > + lastfd = MAX(lastfd, childin); > + lastfd = MAX(lastfd, childout); > + lastfd = MAX(lastfd, childerr); > + > + for (i = 0; i < cmd->npassfd; i++) > + lastfd = MAX(lastfd, cmd->passfd[i].fd); > + > + for (fd = 0; fd <= lastfd; fd++) { > + if (fd == childin || fd == childout || fd == childerr) > + continue; > + if (!virCommandFDIsSet(cmd, fd)) { > + int tmpfd = fd; > + VIR_MASS_CLOSE(tmpfd); > + } else if (virSetInherit(fd, true) < 0) { > + virReportSystemError(errno, _("failed to preserve fd %1$d"), fd); > + return -1; > + } > + } > + > + closefrom(lastfd + 1); GLibC might have closefrom() but be in a container running on an older kernel that lacks close_range syscall. We could ignore return value on FreeBSD, but now on Linux we must check the return value and fallback to the old codepath(s). With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|