Hurd: fix port leak in TLS
authorRichard Braun <rbraun@sceen.net>
Sun, 3 Jul 2016 19:59:34 +0000 (19:59 +0000)
committerAurelien Jarno <aurel32@debian.org>
Sun, 3 Jul 2016 19:59:34 +0000 (19:59 +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 665b6cc4e73f8957f9ca5edf49c2f78e244c2391..f07b1f519810b6f88cc9e006569e2862658e3ae5 100644 (file)
@@ -108,36 +108,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