rtld: Fix fd leak with parallel dlopen and fork/exec.

Rtld did not set FD_CLOEXEC on its internal file descriptors; therefore,
such a file descriptor may be passed to a process created by another thread
running in parallel to dlopen() or fdlopen().

No other threads are expected to be running during parsing of the hints
and libmap files but the file descriptors need not be passed to child
processes so add O_CLOEXEC there as well.

This change will break fdlopen() (as used by OpenPAM) on kernels without
F_DUPFD_CLOEXEC (added in July). Note that running new userland on old
kernels is not supported.

Reviewed by:	kib
This commit is contained in:
Jilles Tjoelker 2012-11-04 21:42:24 +00:00
parent 4cc5fc9a0c
commit e194282943
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=242587
2 changed files with 4 additions and 4 deletions

View File

@ -121,7 +121,7 @@ lmc_parse_file(char *path)
}
}
fd = open(rpath, O_RDONLY);
fd = open(rpath, O_RDONLY | O_CLOEXEC);
if (fd == -1) {
dbg("lm_parse_file: open(\"%s\") failed, %s", rpath,
rtld_strerror(errno));

View File

@ -1598,7 +1598,7 @@ gethints(bool nostdlib)
/* Keep from trying again in case the hints file is bad. */
hints = "";
if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
if ((fd = open(ld_elf_hints_path, O_RDONLY | O_CLOEXEC)) == -1)
return (NULL);
if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
hdr.magic != ELFHINTS_MAGIC ||
@ -2046,13 +2046,13 @@ load_object(const char *name, int fd_u, const Obj_Entry *refobj, int flags)
*/
fd = -1;
if (fd_u == -1) {
if ((fd = open(path, O_RDONLY)) == -1) {
if ((fd = open(path, O_RDONLY | O_CLOEXEC)) == -1) {
_rtld_error("Cannot open \"%s\"", path);
free(path);
return (NULL);
}
} else {
fd = dup(fd_u);
fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0);
if (fd == -1) {
_rtld_error("Cannot dup fd");
free(path);