SDL: Make sure SDL file descriptors don't leak into child processes

From bf97c5a22f948c055c3580a57f1d8ec342ec6134 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 8 Sep 2021 14:47:40 -0700
Subject: [PATCH] Make sure SDL file descriptors don't leak into child
 processes

---
 src/audio/SDL_audiodev.c                 |  2 +-
 src/audio/dsp/SDL_dspaudio.c             |  2 +-
 src/audio/netbsd/SDL_netbsdaudio.c       |  2 +-
 src/core/freebsd/SDL_evdev_kbd_freebsd.c |  4 ++--
 src/core/linux/SDL_evdev.c               |  2 +-
 src/core/linux/SDL_evdev_kbd.c           |  2 +-
 src/core/openbsd/SDL_wscons_kbd.c        |  2 +-
 src/core/openbsd/SDL_wscons_mouse.c      |  2 +-
 src/cpuinfo/SDL_cpuinfo.c                |  4 ++--
 src/haptic/linux/SDL_syshaptic.c         | 10 +++++-----
 src/hidapi/linux/hid.c                   |  2 +-
 src/joystick/bsd/SDL_bsdjoystick.c       |  4 ++--
 src/joystick/linux/SDL_sysjoystick.c     |  4 ++--
 src/power/haiku/SDL_syspower.c           |  2 +-
 src/power/linux/SDL_syspower.c           |  4 ++--
 15 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/src/audio/SDL_audiodev.c b/src/audio/SDL_audiodev.c
index dc1daee1ae..46530e24c7 100644
--- a/src/audio/SDL_audiodev.c
+++ b/src/audio/SDL_audiodev.c
@@ -51,7 +51,7 @@ test_device(const int iscapture, const char *fname, int flags, int (*test) (int
 {
     struct stat sb;
     if ((stat(fname, &sb) == 0) && (S_ISCHR(sb.st_mode))) {
-        const int audio_fd = open(fname, flags, 0);
+        const int audio_fd = open(fname, flags | O_CLOEXEC, 0);
         if (audio_fd >= 0) {
             const int okay = test(audio_fd);
             close(audio_fd);
diff --git a/src/audio/dsp/SDL_dspaudio.c b/src/audio/dsp/SDL_dspaudio.c
index 2124dcc1f9..f2efaf3f76 100644
--- a/src/audio/dsp/SDL_dspaudio.c
+++ b/src/audio/dsp/SDL_dspaudio.c
@@ -103,7 +103,7 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_zerop(this->hidden);
 
     /* Open the audio device */
-    this->hidden->audio_fd = open(devname, flags, 0);
+    this->hidden->audio_fd = open(devname, flags | O_CLOEXEC, 0);
     if (this->hidden->audio_fd < 0) {
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
     }
diff --git a/src/audio/netbsd/SDL_netbsdaudio.c b/src/audio/netbsd/SDL_netbsdaudio.c
index 32817abf43..38b15020ac 100644
--- a/src/audio/netbsd/SDL_netbsdaudio.c
+++ b/src/audio/netbsd/SDL_netbsdaudio.c
@@ -226,7 +226,7 @@ NETBSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
     SDL_zerop(this->hidden);
 
     /* Open the audio device */
-    this->hidden->audio_fd = open(devname, iscapture ? O_RDONLY : O_WRONLY);
+    this->hidden->audio_fd = open(devname, (iscapture ? O_RDONLY : O_WRONLY) | O_CLOEXEC);
     if (this->hidden->audio_fd < 0) {
         return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
     }
diff --git a/src/core/freebsd/SDL_evdev_kbd_freebsd.c b/src/core/freebsd/SDL_evdev_kbd_freebsd.c
index 48fab58895..24910355e6 100644
--- a/src/core/freebsd/SDL_evdev_kbd_freebsd.c
+++ b/src/core/freebsd/SDL_evdev_kbd_freebsd.c
@@ -238,7 +238,7 @@ SDL_EVDEV_kbd_init(void)
     kbd->npadch = -1;
 
     /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
-    kbd->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY);
+    kbd->keyboard_fd = kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
 
     kbd->shift_state = 0;
 
@@ -274,7 +274,7 @@ SDL_EVDEV_kbd_init(void)
              */
             ioctl(kbd->console_fd, CONS_RELKBD, 1ul);
             asprintf(&devicePath, "/dev/kbd%d", kbd->kbInfo->kb_index);         
-            kbd->keyboard_fd = open(devicePath, O_WRONLY);
+            kbd->keyboard_fd = open(devicePath, O_WRONLY | O_CLOEXEC);
             if (kbd->keyboard_fd == -1)
             {
                 // Give keyboard back.
diff --git a/src/core/linux/SDL_evdev.c b/src/core/linux/SDL_evdev.c
index bd4fcf6cd8..36359201d2 100644
--- a/src/core/linux/SDL_evdev.c
+++ b/src/core/linux/SDL_evdev.c
@@ -725,7 +725,7 @@ SDL_EVDEV_device_added(const char *dev_path, int udev_class)
         return SDL_OutOfMemory();
     }
 
-    item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
+    item->fd = open(dev_path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
     if (item->fd < 0) {
         SDL_free(item);
         return SDL_SetError("Unable to open %s", dev_path);
diff --git a/src/core/linux/SDL_evdev_kbd.c b/src/core/linux/SDL_evdev_kbd.c
index 506e24df56..4ea6b149b5 100644
--- a/src/core/linux/SDL_evdev_kbd.c
+++ b/src/core/linux/SDL_evdev_kbd.c
@@ -354,7 +354,7 @@ SDL_EVDEV_kbd_init(void)
     kbd->npadch = -1;
 
     /* This might fail if we're not connected to a tty (e.g. on the Steam Link) */
-    kbd->console_fd = open("/dev/tty", O_RDONLY);
+    kbd->console_fd = open("/dev/tty", O_RDONLY | O_CLOEXEC);
 
     if (ioctl(kbd->console_fd, TIOCLINUX, shift_state) == 0) {
         kbd->shift_state = *shift_state;
diff --git a/src/core/openbsd/SDL_wscons_kbd.c b/src/core/openbsd/SDL_wscons_kbd.c
index 8d62a6cc86..a507b6faf1 100644
--- a/src/core/openbsd/SDL_wscons_kbd.c
+++ b/src/core/openbsd/SDL_wscons_kbd.c
@@ -416,7 +416,7 @@ static SDL_WSCONS_input_data* SDL_WSCONS_Init_Keyboard(const char* dev)
     if (!input) {
         return input;
     }
-    input->fd = open(dev,O_RDWR | O_NONBLOCK);
+    input->fd = open(dev,O_RDWR | O_NONBLOCK | O_CLOEXEC);
     if (input->fd == -1) {
         free(input);
         input = NULL;
diff --git a/src/core/openbsd/SDL_wscons_mouse.c b/src/core/openbsd/SDL_wscons_mouse.c
index da8e9e2858..72510502ee 100644
--- a/src/core/openbsd/SDL_wscons_mouse.c
+++ b/src/core/openbsd/SDL_wscons_mouse.c
@@ -43,7 +43,7 @@ SDL_WSCONS_mouse_input_data* SDL_WSCONS_Init_Mouse()
     SDL_WSCONS_mouse_input_data* mouseInputData = SDL_calloc(1, sizeof(SDL_WSCONS_mouse_input_data));
 
     if (!mouseInputData) return NULL;
-    mouseInputData->fd = open("/dev/wsmouse",O_RDWR | O_NONBLOCK);
+    mouseInputData->fd = open("/dev/wsmouse",O_RDWR | O_NONBLOCK | O_CLOEXEC);
     if (mouseInputData->fd == -1) {free(mouseInputData); return NULL; }
 #ifdef WSMOUSEIO_SETMODE
     ioctl(mouseInputData->fd, WSMOUSEIO_SETMODE, WSMOUSE_COMPAT);
diff --git a/src/cpuinfo/SDL_cpuinfo.c b/src/cpuinfo/SDL_cpuinfo.c
index ded6cd5e52..0205729ae4 100644
--- a/src/cpuinfo/SDL_cpuinfo.c
+++ b/src/cpuinfo/SDL_cpuinfo.c
@@ -361,7 +361,7 @@ CPU_haveARMSIMD(void)
     int arm_simd = 0;
     int fd;
 
-    fd = open("/proc/self/auxv", O_RDONLY);
+    fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
     if (fd >= 0)
     {
         Elf32_auxv_t aux;
@@ -417,7 +417,7 @@ readProcAuxvForNeon(void)
     int neon = 0;
     int fd;
 
-    fd = open("/proc/self/auxv", O_RDONLY);
+    fd = open("/proc/self/auxv", O_RDONLY | O_CLOEXEC);
     if (fd >= 0)
     {
         Elf32_auxv_t aux;
diff --git a/src/haptic/linux/SDL_syshaptic.c b/src/haptic/linux/SDL_syshaptic.c
index 515aa9d747..b183ca7277 100644
--- a/src/haptic/linux/SDL_syshaptic.c
+++ b/src/haptic/linux/SDL_syshaptic.c
@@ -260,7 +260,7 @@ MaybeAddDevice(const char *path)
     }
 
     /* try to open */
-    fd = open(path, O_RDWR, 0);
+    fd = open(path, O_RDWR | O_CLOEXEC, 0);
     if (fd < 0) {
         return -1;
     }
@@ -375,7 +375,7 @@ SDL_SYS_HapticName(int index)
     item = HapticByDevIndex(index);
     /* Open the haptic device. */
     name = NULL;
-    fd = open(item->fname, O_RDONLY, 0);
+    fd = open(item->fname, O_RDONLY | O_CLOEXEC, 0);
 
     if (fd >= 0) {
 
@@ -453,7 +453,7 @@ SDL_SYS_HapticOpen(SDL_Haptic * haptic)
 
     item = HapticByDevIndex(haptic->index);
     /* Open the character device */
-    fd = open(item->fname, O_RDWR, 0);
+    fd = open(item->fname, O_RDWR | O_CLOEXEC, 0);
     if (fd < 0) {
         return SDL_SetError("Haptic: Unable to open %s: %s",
                             item->fname, strerror(errno));
@@ -483,7 +483,7 @@ SDL_SYS_HapticMouse(void)
 
     for (item = SDL_hapticlist; item; item = item->next) {
         /* Open the device. */
-        fd = open(item->fname, O_RDWR, 0);
+        fd = open(item->fname, O_RDWR | O_CLOEXEC, 0);
         if (fd < 0) {
             return SDL_SetError("Haptic: Unable to open %s: %s",
                                 item->fname, strerror(errno));
@@ -570,7 +570,7 @@ SDL_SYS_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
         return SDL_SetError("Haptic: Joystick doesn't have Haptic capabilities");
     }
 
-    fd = open(joystick->hwdata->fname, O_RDWR, 0);
+    fd = open(joystick->hwdata->fname, O_RDWR | O_CLOEXEC, 0);
     if (fd < 0) {
         return SDL_SetError("Haptic: Unable to open %s: %s",
                             joystick->hwdata->fname, strerror(errno));
diff --git a/src/hidapi/linux/hid.c b/src/hidapi/linux/hid.c
index b9544156d4..418dc0adb4 100644
--- a/src/hidapi/linux/hid.c
+++ b/src/hidapi/linux/hid.c
@@ -716,7 +716,7 @@ hid_device * HID_API_EXPORT hid_open_path(const char *path, int bExclusive)
 	dev = new_hid_device();
 
 	/* OPEN HERE */
-	dev->device_handle = open(path, O_RDWR);
+	dev->device_handle = open(path, O_RDWR | O_CLOEXEC);
 
 	/* If we have a good handle, return it. */
 	if (dev->device_handle >= 0) {
diff --git a/src/joystick/bsd/SDL_bsdjoystick.c b/src/joystick/bsd/SDL_bsdjoystick.c
index 8735b4dff3..e0bf2a1a16 100644
--- a/src/joystick/bsd/SDL_bsdjoystick.c
+++ b/src/joystick/bsd/SDL_bsdjoystick.c
@@ -240,7 +240,7 @@ BSD_JoystickInit(void)
     }
     for (i = 0; i < MAX_JOY_JOYS; i++) {
         SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
-        fd = open(s, O_RDONLY);
+        fd = open(s, O_RDONLY | O_CLOEXEC);
         if (fd != -1) {
             joynames[numjoysticks++] = SDL_strdup(s);
             close(fd);
@@ -357,7 +357,7 @@ BSD_JoystickOpen(SDL_Joystick *joy, int device_index)
     int fd;
     int i;
 
-    fd = open(path, O_RDONLY);
+    fd = open(path, O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
         return SDL_SetError("%s: %s", path, strerror(errno));
     }
diff --git a/src/joystick/linux/SDL_sysjoystick.c b/src/joystick/linux/SDL_sysjoystick.c
index a3936e6391..88aea5708b 100644
--- a/src/joystick/linux/SDL_sysjoystick.c
+++ b/src/joystick/linux/SDL_sysjoystick.c
@@ -302,7 +302,7 @@ MaybeAddDevice(const char *path)
         }
     }
 
-    fd = open(path, O_RDONLY, 0);
+    fd = open(path, O_RDONLY | O_CLOEXEC, 0);
     if (fd < 0) {
         return -1;
     }
@@ -963,7 +963,7 @@ PrepareJoystickHwdata(SDL_Joystick *joystick, SDL_joylist_item *item)
                                      &joystick->naxes,
                                      &joystick->nhats);
     } else {
-        const int fd = open(item->path, O_RDWR, 0);
+        const int fd = open(item->path, O_RDWR | O_CLOEXEC, 0);
         if (fd < 0) {
             return SDL_SetError("Unable to open %s", item->path);
         }
diff --git a/src/power/haiku/SDL_syspower.c b/src/power/haiku/SDL_syspower.c
index cb47aa960c..87167b91cb 100644
--- a/src/power/haiku/SDL_syspower.c
+++ b/src/power/haiku/SDL_syspower.c
@@ -45,7 +45,7 @@
 SDL_bool
 SDL_GetPowerInfo_Haiku(SDL_PowerState * state, int *seconds, int *percent)
 {
-    const int fd = open("/dev/misc/apm", O_RDONLY);
+    const int fd = open("/dev/misc/apm", O_RDONLY | O_CLOEXEC);
     SDL_bool need_details = SDL_FALSE;
     uint16 regs[6];
     uint8 ac_status;
diff --git a/src/power/linux/SDL_syspower.c b/src/power/linux/SDL_syspower.c
index fa2aaee80e..dee691d7d6 100644
--- a/src/power/linux/SDL_syspower.c
+++ b/src/power/linux/SDL_syspower.c
@@ -51,7 +51,7 @@ open_power_file(const char *base, const char *node, const char *key)
     }
 
     snprintf(path, pathlen, "%s/%s/%s", base, node, key);
-    return open(path, O_RDONLY);
+    return open(path, O_RDONLY | O_CLOEXEC);
 }
 
 
@@ -330,7 +330,7 @@ SDL_GetPowerInfo_Linux_proc_apm(SDL_PowerState * state,
     int battery_flag = 0;
     int battery_percent = 0;
     int battery_time = 0;
-    const int fd = open(proc_apm_path, O_RDONLY);
+    const int fd = open(proc_apm_path, O_RDONLY | O_CLOEXEC);
     char buf[128];
     char *ptr = &buf[0];
     char *str = NULL;