linux/check_native: Always close socket on return

Message ID 20210512035030.404349-1-siddhesh@sourceware.org
State Superseded
Headers show
Series
  • linux/check_native: Always close socket on return
Related show

Commit Message

Samuel Thibault via Libc-alpha May 12, 2021, 3:50 a.m.
The error paths of __check_native would leave the socket FD open on
return, resulting in an FD leak.  Rework function exit paths so that
the fd is always closed on return.
---
 sysdeps/unix/sysv/linux/check_native.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

-- 
2.31.1

Comments

Andreas Schwab May 12, 2021, 7:16 a.m. | #1
On Mai 12 2021, Siddhesh Poyarekar via Libc-alpha wrote:

> @@ -166,12 +168,9 @@ __check_native (uint32_t a1_index, int *a1_native,

>      }

>    while (! done);

>  

> - out:

> +out:

>    __close_nocancel_nostatus (fd);

>  

> -  return;

> -

> -out_fail:

>    if (use_malloc)


use_malloc is used uninitialized.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."

Patch

diff --git a/sysdeps/unix/sysv/linux/check_native.c b/sysdeps/unix/sysv/linux/check_native.c
index e4e6e80dbc..47b339b629 100644
--- a/sysdeps/unix/sysv/linux/check_native.c
+++ b/sysdeps/unix/sysv/linux/check_native.c
@@ -49,11 +49,13 @@  __check_native (uint32_t a1_index, int *a1_native,
 
   socklen_t addr_len = sizeof (nladdr);
 
-  if (fd < 0
-      || __bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0
-      || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0)
+  if (fd < 0)
     return;
 
+  if (__bind (fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) != 0
+      || __getsockname (fd, (struct sockaddr *) &nladdr, &addr_len) != 0)
+    goto out;
+
   pid_t pid = nladdr.nl_pid;
   struct req
   {
@@ -96,7 +98,7 @@  __check_native (uint32_t a1_index, int *a1_native,
       if (buf != NULL)
 	use_malloc = true;
       else
-	goto out_fail;
+	goto out;
     }
 
   struct iovec iov = { buf, buf_size };
@@ -104,7 +106,7 @@  __check_native (uint32_t a1_index, int *a1_native,
   if (TEMP_FAILURE_RETRY (__sendto (fd, (void *) &req, sizeof (req), 0,
 				    (struct sockaddr *) &nladdr,
 				    sizeof (nladdr))) < 0)
-    goto out_fail;
+    goto out;
 
   bool done = false;
   do
@@ -123,10 +125,10 @@  __check_native (uint32_t a1_index, int *a1_native,
       ssize_t read_len = TEMP_FAILURE_RETRY (__recvmsg (fd, &msg, 0));
       __netlink_assert_response (fd, read_len);
       if (read_len < 0)
-	goto out_fail;
+	goto out;
 
       if (msg.msg_flags & MSG_TRUNC)
-	goto out_fail;
+	goto out;
 
       struct nlmsghdr *nlmh;
       for (nlmh = (struct nlmsghdr *) buf;
@@ -166,12 +168,9 @@  __check_native (uint32_t a1_index, int *a1_native,
     }
   while (! done);
 
- out:
+out:
   __close_nocancel_nostatus (fd);
 
-  return;
-
-out_fail:
   if (use_malloc)
     free (buf);
 }