Bladeren bron

[LibOS] Fix memory leak in shim_do_execve_rtld()

__libcc_tcb_t is leaked. It should be allocated from stack.
Isaku Yamahata 4 jaren geleden
bovenliggende
commit
bc715c2081
3 gewijzigde bestanden met toevoegingen van 26 en 12 verwijderingen
  1. 1 1
      LibOS/shim/include/shim_thread.h
  2. 4 3
      LibOS/shim/src/shim_init.c
  3. 21 8
      LibOS/shim/src/sys/shim_exec.c

+ 1 - 1
LibOS/shim/include/shim_thread.h

@@ -350,6 +350,6 @@ bool check_on_stack (struct shim_thread * cur_thread, void * mem)
 
 int init_stack (const char ** argv, const char ** envp,
                 int ** argcpp, const char *** argpp,
-                elf_auxv_t ** auxpp);
+                elf_auxv_t ** auxpp, size_t reserve);
 
 #endif /* _SHIM_THREAD_H_ */

+ 4 - 3
LibOS/shim/src/shim_init.c

@@ -358,7 +358,7 @@ copy_envp:
 
 int init_stack (const char ** argv, const char ** envp,
                 int ** argcpp, const char *** argpp,
-                elf_auxv_t ** auxpp)
+                elf_auxv_t ** auxpp, size_t reserve)
 {
     uint64_t stack_size = get_rlimit_cur(RLIMIT_STACK);
 
@@ -382,7 +382,8 @@ int init_stack (const char ** argv, const char ** envp,
     if (initial_envp)
         envp = initial_envp;
 
-    int ret = populate_user_stack(stack, stack_size, auxpp, argcpp, &argv, &envp);
+    int ret = populate_user_stack(stack, stack_size - reserve,
+                                  auxpp, argcpp, &argv, &envp);
     if (ret < 0)
         return ret;
 
@@ -755,7 +756,7 @@ noreturn void* shim_init (int argc, void * args)
     RUN_INIT(init_mount);
     RUN_INIT(init_important_handles);
     RUN_INIT(init_async);
-    RUN_INIT(init_stack, argv, envp, &argcp, &argp, &auxp);
+    RUN_INIT(init_stack, argv, envp, &argcp, &argp, &auxp, 0);
     RUN_INIT(init_loader);
     RUN_INIT(init_ipc_helper);
     RUN_INIT(init_signal);

+ 21 - 8
LibOS/shim/src/sys/shim_exec.c

@@ -87,6 +87,19 @@ noreturn static void __shim_do_execve_rtld (struct execve_rtld_arg * __arg)
     struct shim_thread * cur_thread = get_cur_thread();
     int ret = 0;
 
+#ifdef SHIM_TCB_USE_GS
+    /* libc tcb is not needed because PAL provides storage for shim_tcb */
+    __libc_tcb_t* tcb = NULL;
+#else
+# define LIBC_TCB_ALLOC_SIZE    (sizeof(__libc_tcb_t) + __alignof__(__libc_tcb_t))
+    __libc_tcb_t* tcb = ALIGN_UP_PTR(
+        cur_thread->stack_top - LIBC_TCB_ALLOC_SIZE,
+        __alignof__(*tcb));
+    memset(tcb, 0, sizeof(*tcb));
+#endif
+    populate_tls(tcb, false);
+    debug("set tcb to %p\n", tcb);
+
     UPDATE_PROFILE_INTERVAL();
 
     DkVirtualMemoryFree(old_stack, old_stack_top - old_stack);
@@ -189,13 +202,6 @@ static int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
 
     SAVE_PROFILE_INTERVAL(close_CLOEXEC_files_for_exec);
 
-    void * tcb = malloc(sizeof(__libc_tcb_t));
-    if (!tcb)
-        return -ENOMEM;
-
-    populate_tls(tcb, false);
-    debug("set tcb to %p\n", tcb);
-
     put_handle(cur_thread->exec);
     get_handle(hdl);
     cur_thread->exec = hdl;
@@ -214,7 +220,14 @@ static int shim_do_execve_rtld (struct shim_handle * hdl, const char ** argv,
     int * new_argcp = &new_argc;
     const char ** new_argp;
     elf_auxv_t * new_auxp;
-    if ((ret = init_stack(argv, envp, &new_argcp, &new_argp, &new_auxp)) < 0)
+#ifdef SHIM_TCB_USE_GS
+    size_t reserve = 0;
+#else
+    /* reserve __libc_tcb_t for startup use. see __shim_do_execve_rtld() */
+    size_t reserve = LIBC_TCB_ALLOC_SIZE;
+#endif
+    if ((ret = init_stack(argv, envp, &new_argcp, &new_argp, &new_auxp,
+                          reserve)) < 0)
         return ret;
 
     __disable_preempt(shim_get_tls()); // Temporarily disable preemption