From 5c3b6929dfbef30dd1d92bbf3da16340bfd4ce06 Mon Sep 17 00:00:00 2001 From: Yunjong Jeong Date: Mon, 14 Oct 2019 02:46:58 +0900 Subject: [PATCH] [LibOS] Reorder argv in initial user stack Even though the SysV ABI does not specify the order of argv strings, some applications (notably Node.js's libuv) assume the compact encoding of argv where (1) all strings are located adjacently and (2) in increasing order. This commit reorders argv strings in the initial user stack in this way. --- LibOS/shim/src/shim_init.c | 12 +++++++++++- LibOS/shim/test/regression/bootstrap.c | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/LibOS/shim/src/shim_init.c b/LibOS/shim/src/shim_init.c index 94cca41a..4139b58c 100644 --- a/LibOS/shim/src/shim_init.c +++ b/LibOS/shim/src/shim_init.c @@ -326,10 +326,20 @@ static int populate_user_stack (void * stack, size_t stack_size, new_argv = stack_bottom; while (argv) { + /* Even though the SysV ABI does not specify the order of argv strings, + some applications (notably Node.js's libuv) assume the compact + encoding of argv where (1) all strings are located adjacently and + (2) in increasing order. */ + int argv_size = 0; + for (const char ** a = argv ; *a ; a++) + argv_size += strlen(*a) + 1; + char * argv_bottom = ALLOCATE_TOP(argv_size); + for (const char ** a = argv ; *a ; a++) { const char ** t = ALLOCATE_BOTTOM(sizeof(const char *)); int len = strlen(*a) + 1; - char * abuf = ALLOCATE_TOP(len); + char * abuf = argv_bottom; + argv_bottom += len; memcpy(abuf, *a, len); *t = abuf; } diff --git a/LibOS/shim/test/regression/bootstrap.c b/LibOS/shim/test/regression/bootstrap.c index 7c479277..6689a3ca 100644 --- a/LibOS/shim/test/regression/bootstrap.c +++ b/LibOS/shim/test/regression/bootstrap.c @@ -1,4 +1,5 @@ #include +#include int main(int argc, const char** argv, const char** envp) { printf("User Program Started\n"); @@ -9,5 +10,18 @@ int main(int argc, const char** argv, const char** envp) { printf("argv[%d] = %s\n", i, argv[i]); } + /* Make sure argv strings follow the compact encoding where (1) all strings + are located adjacently and (2) in increasing order. */ + size_t sum_len = 0; + for (int i = 0; i < argc; i++) { + sum_len += strlen(argv[i]) + 1; + } + + size_t chunk_len = argv[argc - 1] + strlen(argv[argc - 1]) - argv[0]; + if (sum_len != chunk_len + 1) { + printf("argv strings are not adjacent or not in increasing order\n"); + return 1; + } + return 0; }