gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [libmicrohttpd] GNU libmicrohttpd branch master updated. 22


From: gitolite
Subject: [GNUnet-SVN] [libmicrohttpd] GNU libmicrohttpd branch master updated. 22a5fb5239fa471c97e81f93e5058e7fb7143eaa
Date: Mon, 17 Oct 2016 00:25:28 +0200 (CEST)

The branch, master has been updated
       via  22a5fb5239fa471c97e81f93e5058e7fb7143eaa (commit)
      from  5b2a9f1cbdb0cfc12cc56d3c345be440c5657be0 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 22a5fb5239fa471c97e81f93e5058e7fb7143eaa
Author: Evgeny Grin (Karlson2k) <address@hidden>
Date:   Mon Oct 17 01:14:08 2016 +0300

    upgrade: fixed double-free, fixed use-after-free

-----------------------------------------------------------------------

Summary of changes:
 src/microhttpd/daemon.c   | 116 ++++++++++++++++++++++++++--------------------
 src/microhttpd/internal.h |  18 +++++--
 src/microhttpd/response.c |  14 ++----
 3 files changed, 83 insertions(+), 65 deletions(-)

diff --git a/src/microhttpd/daemon.c b/src/microhttpd/daemon.c
index 722937e..9da7508 100644
--- a/src/microhttpd/daemon.c
+++ b/src/microhttpd/daemon.c
@@ -912,65 +912,80 @@ call_handlers (struct MHD_Connection *con,
 }
 
 
-#if HTTPS_SUPPORT
 /**
- * This function finishes the process of closing the
- * connection associated with the @a urh.  It should
- * be called if the `was_closed` flag is set and the
- * buffer has been drained.
- *
- * @param urh handle to the upgraded response we are finished with
+ * Finally cleanup upgrade-related resources. It should
+ * be called when TLS buffers have been drained and
+ * application signaled MHD by #MHD_UPGRADE_ACTION_CLOSE.
+ * @param connection handle to the upgraded connection to clean
  */
-static void
-finish_upgrade_close (struct MHD_UpgradeResponseHandle *urh)
+void
+cleanup_upgraded_connection (struct MHD_Connection *connection)
 {
-  struct MHD_Connection *connection = urh->connection;
-  struct MHD_Daemon *daemon = connection->daemon;
+  struct MHD_Daemon *daemon;
+  struct MHD_UpgradeResponseHandle *urh;
+  if (NULL == connection)
+    return;
+  daemon = connection->daemon;
+  urh = connection->urh;
+  if (NULL == urh)
+    return;
 
-  DLL_remove (daemon->urh_head,
-              daemon->urh_tail,
-              urh);
-#if EPOLL_SUPPORT
-  if (0 != (daemon->options & MHD_USE_EPOLL))
+#if HTTPS_SUPPORT
+  if (0 != (daemon->options && MHD_USE_TLS))
     {
-      /* epoll documentation suggests that closing a FD
-         automatically removes it from the epoll set; however,
-         this is not true as if we fail to do manually remove it,
-         we are still seeing an event for this fd in epoll,
-         causing grief (use-after-free...) --- at least on my
-         system. */
-      if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
-                          EPOLL_CTL_DEL,
-                          connection->socket_fd,
-                          NULL))
-        MHD_PANIC (_("Failed to remove FD from epoll set\n"));
-    }
-#endif
-  if (MHD_INVALID_SOCKET != urh->mhd.socket)
-    {
-      /* epoll documentation suggests that closing a FD
-         automatically removes it from the epoll set; however,
-         this is not true as if we fail to do manually remove it,
-         we are still seeing an event for this fd in epoll,
-         causing grief (use-after-free...) --- at least on my
-         system. */
+      if (0 == (daemon->options && MHD_USE_THREAD_PER_CONNECTION))
+        DLL_remove (daemon->urh_head,
+                    daemon->urh_tail,
+                    urh);
 #if EPOLL_SUPPORT
-      if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
-           (0 != epoll_ctl (daemon->epoll_upgrade_fd,
-                            EPOLL_CTL_DEL,
-                            urh->mhd.socket,
-                            NULL)) )
-        MHD_PANIC (_("Failed to remove FD from epoll set\n"));
-#endif
-      MHD_socket_close_chk_ (urh->mhd.socket);
+      if (0 != (daemon->options & MHD_USE_EPOLL))
+        {
+          /* epoll documentation suggests that closing a FD
+             automatically removes it from the epoll set; however,
+             this is not true as if we fail to do manually remove it,
+             we are still seeing an event for this fd in epoll,
+             causing grief (use-after-free...) --- at least on my
+             system. */
+          if (0 != epoll_ctl (daemon->epoll_upgrade_fd,
+                              EPOLL_CTL_DEL,
+                              connection->socket_fd,
+                              NULL))
+            MHD_PANIC (_("Failed to remove FD from epoll set\n"));
+        }
+#endif /* EPOLL_SUPPORT */
+      if (MHD_INVALID_SOCKET != urh->mhd.socket)
+        {
+          /* epoll documentation suggests that closing a FD
+             automatically removes it from the epoll set; however,
+             this is not true as if we fail to do manually remove it,
+             we are still seeing an event for this fd in epoll,
+             causing grief (use-after-free...) --- at least on my
+             system. */
+#if EPOLL_SUPPORT
+          if ( (0 != (daemon->options & MHD_USE_EPOLL)) &&
+               (0 != epoll_ctl (daemon->epoll_upgrade_fd,
+                                EPOLL_CTL_DEL,
+                                urh->mhd.socket,
+                                NULL)) )
+            MHD_PANIC (_("Failed to remove FD from epoll set\n"));
+#endif /* EPOLL_SUPPORT */
+          MHD_socket_close_chk_ (urh->mhd.socket);
+        }
+      if (MHD_INVALID_SOCKET != urh->app.socket)
+        MHD_socket_close_chk_ (urh->app.socket);
     }
-  MHD_resume_connection (connection);
+#endif /* HTTPS_SUPPORT */
+  if (0 == (daemon->options && MHD_USE_THREAD_PER_CONNECTION))
+    MHD_resume_connection (connection);
+
   MHD_connection_close_ (connection,
                          MHD_REQUEST_TERMINATED_COMPLETED_OK);
+  connection->urh = NULL;
   free (urh);
 }
 
 
+#if HTTPS_SUPPORT
 /**
  * Performs bi-directional forwarding on upgraded HTTPS connections
  * based on the readyness state stored in the @a urh handle.
@@ -1109,10 +1124,6 @@ process_urh (struct MHD_UpgradeResponseHandle *urh)
           urh->out_buffer_off = 0;
         }
     }
-  if ( (fin_read) &&
-       (0 == urh->out_buffer_off) &&
-       (MHD_YES == urh->was_closed) )
-    finish_upgrade_close (urh);
 }
 #endif
 
@@ -1256,7 +1267,7 @@ thread_main_connection_upgrade (struct MHD_Connection 
*con)
   MHD_semaphore_down (con->upgrade_sem);
   MHD_semaphore_destroy (con->upgrade_sem);
   con->upgrade_sem = NULL;
-  free (urh);
+  cleanup_upgraded_connection(con);
 }
 
 
@@ -2773,6 +2784,9 @@ MHD_run_from_select (struct MHD_Daemon *daemon,
                       write_fd_set);
       /* call generic forwarding function for passing data */
       process_urh (urh);
+      /* cleanup connection if it was closed and all data was sent */
+      if (MHD_YES == urh->was_closed && 0 == urh->out_buffer_off)
+        cleanup_upgraded_connection (urh->connection);
     }
 #endif
   MHD_cleanup_connections (daemon);
diff --git a/src/microhttpd/internal.h b/src/microhttpd/internal.h
index be751c2..9c5ac90 100644
--- a/src/microhttpd/internal.h
+++ b/src/microhttpd/internal.h
@@ -1059,14 +1059,13 @@ struct MHD_UpgradeResponseHandle
    */
   char e_buf[RESERVE_EBUF_SIZE];
 
+#endif /* HTTPS_SUPPORT */
+
   /**
-   * Set to #MHD_YES after the application closed the socket
-   * via #MHD_UPGRADE_ACTION_CLOSE.
+   * Set to #MHD_YES after the application finished with the socket
+   * by #MHD_UPGRADE_ACTION_CLOSE.
    */
   int was_closed;
-
-#endif
-
 };
 
 
@@ -1724,4 +1723,13 @@ MHD_parse_arguments_ (struct MHD_Connection *connection,
                      unsigned int *num_headers);
 
 
+/**
+ * Finally cleanup upgrade-related resources. It should
+ * be called when TLS buffers have been drained and
+ * application signaled MHD by #MHD_UPGRADE_ACTION_CLOSE.
+ * @param connection handle to the upgraded connection to clean
+ */
+void
+cleanup_upgraded_connection (struct MHD_Connection *connection);
+
 #endif
diff --git a/src/microhttpd/response.c b/src/microhttpd/response.c
index afeccb5..0831840 100644
--- a/src/microhttpd/response.c
+++ b/src/microhttpd/response.c
@@ -647,24 +647,20 @@ MHD_upgrade_action (struct MHD_UpgradeResponseHandle *urh,
 #endif
         /* need to signal the thread that we are done */
         MHD_semaphore_up (connection->upgrade_sem);
+        /* connection and urh cleanup will be done in connection's thread */
         return MHD_YES;
       }
 #if HTTPS_SUPPORT
     if (0 != (daemon->options & MHD_USE_TLS) )
       {
         urh->was_closed = MHD_YES;
-        if (MHD_INVALID_SOCKET != urh->app.socket)
-          {
-            MHD_socket_close_chk_ (urh->app.socket);
-            urh->app.socket = MHD_INVALID_SOCKET;
-          }
+        /* connection and urh cleanup will be done as soon as outgoing
+         * data will be sent and 'was_closed' is detected */
         return MHD_YES;
       }
 #endif
-    MHD_resume_connection (connection);
-    MHD_connection_close_ (connection,
-                           MHD_REQUEST_TERMINATED_COMPLETED_OK);
-    free (urh);
+    /* 'upgraded' resources are not needed anymore - cleanup now */
+    cleanup_upgraded_connection (connection);
     return MHD_YES;
   default:
     /* we don't understand this one */


hooks/post-receive
-- 
GNU libmicrohttpd



reply via email to

[Prev in Thread] Current Thread [Next in Thread]