Explorar o código

Fixes from PuTTY 0.76

– Avoid crash in MIT Kerberos for Windows on session restart (PuTTY commit d599e3e6)
– Close all thread handles returned from CreateThread (ea45d7dc)

Source commit: b6e962fefe881e305b84a26001d14642aeed62ba
Martin Prikryl %!s(int64=4) %!d(string=hai) anos
pai
achega
c378381791
Modificáronse 2 ficheiros con 56 adicións e 5 borrados
  1. 44 1
      source/putty/windows/wingss.c
  2. 12 4
      source/putty/windows/winhandl.c

+ 44 - 1
source/putty/windows/wingss.c

@@ -98,6 +98,28 @@ const char *gsslogmsg = NULL;
 
 static void ssh_sspi_bind_fns(struct ssh_gss_library *lib);
 
+static tree234 *libraries_to_never_unload;
+static int library_to_never_unload_cmp(void *av, void *bv)
+{
+    uintptr_t a = (uintptr_t)av, b = (uintptr_t)bv;
+    return a < b ? -1 : a > b ? +1 : 0;
+}
+static void ensure_library_tree_exists(void)
+{
+    if (!libraries_to_never_unload)
+        libraries_to_never_unload = newtree234(library_to_never_unload_cmp);
+}
+static bool library_is_in_never_unload_tree(HMODULE module)
+{
+    ensure_library_tree_exists();
+    return find234(libraries_to_never_unload, module, NULL);
+}
+static void add_library_to_never_unload_tree(HMODULE module)
+{
+    ensure_library_tree_exists();
+    add234(libraries_to_never_unload, module);
+}
+
 struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
 {
     HMODULE module;
@@ -148,6 +170,23 @@ struct ssh_gss_liblist *ssh_gss_setup(Conf *conf, LogContext *logctx) // MPEXT
                                         LOAD_LIBRARY_SEARCH_SYSTEM32 |
                                         LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR |
                                         LOAD_LIBRARY_SEARCH_USER_DIRS);
+
+                /*
+                 * The MIT Kerberos DLL suffers an internal segfault
+                 * for some reason if you unload and reload one within
+                 * the same process. So, make sure that after we load
+                 * this library, we never free it.
+                 *
+                 * Or rather: after we've loaded it once, if any
+                 * _further_ load returns the same module handle, we
+                 * immediately free it again (to prevent the Windows
+                 * API's internal reference count growing without
+                 * bound). But on the other hand we never free it in
+                 * ssh_gss_cleanup.
+                 */
+                if (library_is_in_never_unload_tree(module))
+                    FreeLibrary(module);
+                add_library_to_never_unload_tree(module);
             }
             sfree(buffer);
         }
@@ -291,7 +330,11 @@ void ssh_gss_cleanup(struct ssh_gss_liblist *list)
      * another SSH instance still using it.
      */
     for (i = 0; i < list->nlibraries; i++) {
-        FreeLibrary((HMODULE)list->libraries[i].handle);
+        if (list->libraries[i].id != 0) {
+            HMODULE module = (HMODULE)list->libraries[i].handle;
+            if (!library_is_in_never_unload_tree(module))
+                FreeLibrary(module);
+        }
         if (list->libraries[i].id == 2) {
             /* The 'custom' id involves a dynamically allocated message.
              * Note that we must cast away the 'const' to free it. */

+ 12 - 4
source/putty/windows/winhandl.c

@@ -451,11 +451,15 @@ struct handle *handle_input_new(HANDLE handle, handle_inputfn_t gotdata,
         handles_by_evtomain = newtree234(handle_cmp_evtomain);
     add234(handles_by_evtomain, h);
 
-    CreateThread(NULL, 0, handle_input_threadfunc,
-                 &h->u.i, 0, &in_threadid);
+    { // WINSCP
+    HANDLE hThread = CreateThread(NULL, 0, handle_input_threadfunc,
+                                  &h->u.i, 0, &in_threadid);
+    if (hThread)
+        CloseHandle(hThread);          /* we don't need the thread handle */
     h->u.i.busy = true;
 
     return h;
+    } // WINSCP
 }
 
 struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
@@ -482,10 +486,14 @@ struct handle *handle_output_new(HANDLE handle, handle_outputfn_t sentdata,
         handles_by_evtomain = newtree234(handle_cmp_evtomain);
     add234(handles_by_evtomain, h);
 
-    CreateThread(NULL, 0, handle_output_threadfunc,
-                 &h->u.o, 0, &out_threadid);
+    { // WINSCP
+    HANDLE hThread = CreateThread(NULL, 0, handle_output_threadfunc,
+                                  &h->u.o, 0, &out_threadid);
+    if (hThread)
+        CloseHandle(hThread);          /* we don't need the thread handle */
 
     return h;
+    } // WINSCP
 }
 
 struct handle *handle_add_foreign_event(HANDLE event,