libbinder: replace dup() with fcntl(F_DUPFD_CLOEXEC)
Replace calls to dup() with fcntl(F_DUPFD_CLOEXEC). The only difference
between the two is that O_CLOEXEC is set on the newly duped file
descriptor. This helps address file descriptor leaks crossing an exec()
boundary in multi-threaded processes, and potentially fixes the following
non-reproducible SELinux denials which may be occurring because of FD
leakage from netd to clatd/dnsmasq.
avc: denied { use } for comm="clatd" path="socket:[860297]" dev="sockfs"
ino=860297 scontext=u:r:clatd:s0 tcontext=u:r:untrusted_app:s0:c512,c768
tclass=fd permissive=0
avc: denied { read write } for comm="clatd" path="socket:[1414454]"
dev="sockfs" ino=1414454 scontext=u:r:clatd:s0
tcontext=u:r:system_server:s0 tclass=tcp_socket permissive=0
avc: denied { use } for comm="clatd" path="socket:[681600]" dev="sockfs"
ino=681600 scontext=u:r:clatd:s0 tcontext=u:r:priv_app:s0:c512,c768
tclass=fd permissive=0
Test: Device boots and no obvious problems
Change-Id: I9dcd9911a093f329c6f12e39d2c49ef3df651ae5
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 15c441e..a6ccb53 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -539,7 +539,7 @@
// If this is a file descriptor, we need to dup it so the
// new Parcel now owns its own fd, and can declare that we
// officially know we have fds.
- flat->handle = dup(flat->handle);
+ flat->handle = fcntl(flat->handle, F_DUPFD_CLOEXEC, 0);
flat->cookie = 1;
mHasFds = mFdsKnown = true;
if (!mAllowFds) {
@@ -1142,7 +1142,7 @@
status_t Parcel::writeDupFileDescriptor(int fd)
{
- int dupFd = dup(fd);
+ int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
if (dupFd < 0) {
return -errno;
}
@@ -1972,7 +1972,7 @@
}
for (int i=0 ; err==NO_ERROR && i<numFds ; i++) {
- h->data[i] = dup(readFileDescriptor());
+ h->data[i] = fcntl(readFileDescriptor(), F_DUPFD_CLOEXEC, 0);
if (h->data[i] < 0) {
for (int j = 0; j < i; j++) {
close(h->data[j]);
@@ -2020,7 +2020,7 @@
return BAD_TYPE;
}
- val->reset(dup(got));
+ val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
if (val->get() < 0) {
return BAD_VALUE;
@@ -2095,9 +2095,9 @@
status_t err = NO_ERROR;
for (size_t i=0 ; i<fd_count && err==NO_ERROR ; i++) {
int fd = this->readFileDescriptor();
- if (fd < 0 || ((fds[i] = dup(fd)) < 0)) {
+ if (fd < 0 || ((fds[i] = fcntl(fd, F_DUPFD_CLOEXEC, 0)) < 0)) {
err = BAD_VALUE;
- ALOGE("dup() failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
+ ALOGE("fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is %zu, fds[i] is %d, fd_count is %zu, error: %s",
i, fds[i], fd_count, strerror(fd < 0 ? -fd : errno));
// Close all the file descriptors that were dup-ed.
for (size_t j=0; j<i ;j++) {