From 436b38fd89fe4324d2342084ef477a7a8809a001 Mon Sep 17 00:00:00 2001
From: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Date: Sun, 26 Mar 2023 12:49:32 +0300
Subject: libcamera: Open files with O_CLOEXEC

Files opened internally in libcamera without the O_CLOEXEC file will
remain open upon a call to one of the exec(3) functions. As exec()
doesn't destroy local or global objects, this can lead to various side
effects. Avoid this by opening file descriptors with O_CLOEXEC for all
internal files.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Umang Jain <umang.jain@ideasonboard.com>
Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 src/ipa/vimc/vimc.cpp                            | 2 +-
 src/libcamera/base/file.cpp                      | 5 ++++-
 src/libcamera/media_device.cpp                   | 2 +-
 src/libcamera/pipeline/raspberrypi/dma_heaps.cpp | 2 +-
 4 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/ipa/vimc/vimc.cpp b/src/ipa/vimc/vimc.cpp
index d5fabaf1..2c255778 100644
--- a/src/ipa/vimc/vimc.cpp
+++ b/src/ipa/vimc/vimc.cpp
@@ -168,7 +168,7 @@ void IPAVimc::initTrace()
 	if (ret)
 		return;
 
-	ret = ::open(ipa::vimc::VimcIPAFIFOPath.c_str(), O_WRONLY);
+	ret = ::open(ipa::vimc::VimcIPAFIFOPath.c_str(), O_WRONLY | O_CLOEXEC);
 	if (ret < 0) {
 		ret = errno;
 		LOG(IPAVimc, Error) << "Failed to open vimc IPA test FIFO: "
diff --git a/src/libcamera/base/file.cpp b/src/libcamera/base/file.cpp
index fb3e276d..d1ab1aa5 100644
--- a/src/libcamera/base/file.cpp
+++ b/src/libcamera/base/file.cpp
@@ -163,6 +163,9 @@ bool File::exists() const
  * attempt to create the file with initial permissions set to 0666 (modified by
  * the process' umask).
  *
+ * The file is opened with the O_CLOEXEC flag, and will be closed automatically
+ * when a new binary is executed with one of the exec(3) functions.
+ *
  * The error() status is updated.
  *
  * \return True on success, false otherwise
@@ -178,7 +181,7 @@ bool File::open(File::OpenMode mode)
 	if (mode & OpenModeFlag::WriteOnly)
 		flags |= O_CREAT;
 
-	fd_ = UniqueFD(::open(name_.c_str(), flags, 0666));
+	fd_ = UniqueFD(::open(name_.c_str(), flags | O_CLOEXEC, 0666));
 	if (!fd_.isValid()) {
 		error_ = -errno;
 		return false;
diff --git a/src/libcamera/media_device.cpp b/src/libcamera/media_device.cpp
index 52c8e66e..2949816b 100644
--- a/src/libcamera/media_device.cpp
+++ b/src/libcamera/media_device.cpp
@@ -477,7 +477,7 @@ int MediaDevice::open()
 		return -EBUSY;
 	}
 
-	fd_ = UniqueFD(::open(deviceNode_.c_str(), O_RDWR));
+	fd_ = UniqueFD(::open(deviceNode_.c_str(), O_RDWR | O_CLOEXEC));
 	if (!fd_.isValid()) {
 		int ret = -errno;
 		LOG(MediaDevice, Error)
diff --git a/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
index 6b644406..317b1fc1 100644
--- a/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
+++ b/src/libcamera/pipeline/raspberrypi/dma_heaps.cpp
@@ -37,7 +37,7 @@ namespace RPi {
 DmaHeap::DmaHeap()
 {
 	for (const char *name : heapNames) {
-		int ret = ::open(name, O_RDWR, 0);
+		int ret = ::open(name, O_RDWR | O_CLOEXEC, 0);
 		if (ret < 0) {
 			ret = errno;
 			LOG(RPI, Debug) << "Failed to open " << name << ": "
-- 
cgit v1.2.1