kern/169260: libkvm to use O_CLOEXEC to avoid file descriptor leaks
in threaded code
Jukka Ukkonen
jau at iki.fi
Wed Jun 20 07:50:09 UTC 2012
>Number: 169260
>Category: kern
>Synopsis: libkvm to use O_CLOEXEC to avoid file descriptor leaks in threaded code
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jun 20 07:50:09 UTC 2012
>Closed-Date:
>Last-Modified:
>Originator: Jukka Ukkonen
>Release: FreeBSD 9.0-STABLE
>Organization:
-----
>Environment:
FreeBSD sleipnir 9.0-STABLE FreeBSD 9.0-STABLE #0: Tue Jun 19 22:26:46 EEST 2012 root at sleipnir:/usr/obj/usr/src/sys/Sleipnir amd64
>Description:
In libkvm files have been opened using a call sequence...
xxxfd = open (...);
fcntl (xxxfd, F_SETFD, FD_CLOEXEC);
In threaded code this could lead to the newly opened fd leaking to a child
program, if another thread happened to call exec() during the short time window
between open() and fcntl().
Now that there is O_CLOEXEC available, there is an atomic alternative...
xxxfd = open (..., O_CLOEXEC);
>How-To-Repeat:
See full description.
>Fix:
Apply the attached patch.
Patch attached with submission follows:
--- lib/libkvm/kvm.c.orig 2012-06-17 17:48:21.000000000 +0300
+++ lib/libkvm/kvm.c 2012-06-17 17:55:25.000000000 +0300
@@ -166,7 +166,7 @@
if (mf == 0)
mf = _PATH_MEM;
- if ((kd->pmfd = open(mf, flag, 0)) < 0) {
+ if ((kd->pmfd = open(mf, (flag | O_CLOEXEC), 0)) < 0) {
_kvm_syserr(kd, kd->program, "%s", mf);
goto failed;
}
@@ -179,10 +179,7 @@
_kvm_syserr(kd, kd->program, "empty file");
goto failed;
}
- if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) {
- _kvm_syserr(kd, kd->program, "%s", mf);
- goto failed;
- }
+
if (S_ISCHR(st.st_mode)) {
/*
* If this is a character special device, then check that
@@ -191,17 +188,16 @@
* case you're working with a live kernel.)
*/
if (strcmp(mf, _PATH_DEVNULL) == 0) {
- kd->vmfd = open(_PATH_DEVNULL, O_RDONLY);
+ kd->vmfd = open(_PATH_DEVNULL,
+ (O_RDONLY | O_CLOEXEC));
return (kd);
} else if (strcmp(mf, _PATH_MEM) == 0) {
- if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
- _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
- goto failed;
- }
- if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) {
+ if ((kd->vmfd = open(_PATH_KMEM,
+ (flag | O_CLOEXEC))) < 0) {
_kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
goto failed;
}
+
return (kd);
}
}
@@ -210,14 +206,11 @@
* Initialize the virtual address translation machinery,
* but first setup the namelist fd.
*/
- if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
- _kvm_syserr(kd, kd->program, "%s", uf);
- goto failed;
- }
- if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) {
+ if ((kd->nlfd = open(uf, (O_RDONLY | O_CLOEXEC), 0)) < 0) {
_kvm_syserr(kd, kd->program, "%s", uf);
goto failed;
}
+
if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0)
kd->rawdump = 1;
if (_kvm_initvtop(kd) < 0)
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list