Hurd: fix port leak in TLS
authorRichard Braun <rbraun@sceen.net>
Sun, 14 Jan 2018 10:24:48 +0000 (10:24 +0000)
committerAurelien Jarno <aurel32@debian.org>
Sun, 14 Jan 2018 10:24:48 +0000 (10:24 +0000)
Depending on whether the thread is the main thread or not, the threading
library can have trouble determining whether the thread reference in the
TCB is valid. The simple solution is to let the threading library
initialize the TCB, and use a temporary reference when initializing TLS.

* sysdeps/mach/hurd/i386/tls.h (_hurd_tls_init): Use a temporary thread
reference.

Gbp-Pq: Topic hurd-i386
Gbp-Pq: Name tg-tls_thread_leak.diff

sysdeps/mach/hurd/i386/tls.h

index 1df4cc8f9fae08197168ea3b91c4dfaa9de7c831..20382dfdaa4a9a42c68b9c4daa5b9fa1bde65922 100644 (file)
@@ -107,36 +107,41 @@ static inline const char * __attribute__ ((unused))
 _hurd_tls_init (tcbhead_t *tcb)
 {
   HURD_TLS_DESC_DECL (desc, tcb);
+  thread_t self = __mach_thread_self ();
+  const char *msg = NULL;
 
   /* This field is used by TLS accesses to get our "thread pointer"
      from the TLS point of view.  */
   tcb->tcb = tcb;
 
-  /* Cache our thread port.  */
-  tcb->self = __mach_thread_self ();
-
   /* Get the first available selector.  */
   int sel = -1;
-  kern_return_t err = __i386_set_gdt (tcb->self, &sel, desc);
+  kern_return_t err = __i386_set_gdt (self, &sel, desc);
   if (err == MIG_BAD_ID)
     {
       /* Old kernel, use a per-thread LDT.  */
       sel = 0x27;
-      err = __i386_set_ldt (tcb->self, sel, &desc, 1);
+      err = __i386_set_ldt (self, sel, &desc, 1);
       assert_perror (err);
       if (err)
-       return "i386_set_ldt failed";
+       {
+         msg = "i386_set_ldt failed";
+         goto out;
+       }
     }
   else if (err)
     {
       assert_perror (err); /* Separate from above with different line #. */
-      return "i386_set_gdt failed";
+      msg = "i386_set_gdt failed";
+      goto out;
     }
 
   /* Now install the new selector.  */
   asm volatile ("mov %w0, %%gs" :: "q" (sel));
 
-  return 0;
+out:
+  __mach_port_deallocate (__mach_task_self (), self);
+  return msg;
 }
 
 /* Code to initially initialize the thread pointer.  This might need