From 525b90d028d7ab8f487804c1fd4e90c70c0d212c Mon Sep 17 00:00:00 2001 From: Dominique Martinet Date: Tue, 16 Oct 2018 10:52:39 +0900 Subject: [PATCH] flatten_string/process env: realign env and clear trailing bits envs are stuck after args which are now possibly unaligned, and used from a non-aligned pointer in prepare_process_ranges_args_envs (env) The memory immediately after args/envs is copied anyway with memcpy_long, so make sure the bits are initialized and realign env correctly Fixes: 70e52faf36 ("flatten_strings: do not return unused trailing bits") Change-Id: Ic747e947d151c0eea65dec36bc9c888cf6e0c394 --- executer/user/mcexec.c | 8 ++++++-- kernel/host.c | 16 +++++++++++----- lib/string.c | 7 +++++-- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 282381e3..f74bc47f 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -1012,7 +1012,7 @@ void print_flat(char *flat) */ int flatten_strings(char *pre_strings, char **strings, char **flat) { - int full_len, i; + int full_len, len, i; int nr_strings; int pre_strings_count = 0; int pre_strings_len = 0; @@ -1076,7 +1076,11 @@ int flatten_strings(char *pre_strings, char **strings, char **flat) _flat[nr_strings + pre_strings_count + 1] = p - (char *)_flat; *flat = (char *)_flat; - return p - (char *)_flat; + len = p - (char *)_flat; + if (len < full_len) + memset(p, 0, full_len - len); + + return len; } //#define NUM_HANDLER_THREADS 248 diff --git a/kernel/host.c b/kernel/host.c index adad70bc..1f015f1d 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -75,7 +75,7 @@ int prepare_process_ranges_args_envs(struct thread *thread, char *envs, int envs_len) { char *args_envs, *args_envs_r; - unsigned long args_envs_p, args_envs_rp; + unsigned long args_envs_p, args_envs_rp, envs_offset; unsigned long s, e, up; char **argv; int i, n, argc, envc, args_envs_npages; @@ -336,7 +336,13 @@ int prepare_process_ranges_args_envs(struct thread *thread, dkprintf("envs copy, nr: %d\n", *((long *)args_envs_r)); - memcpy_long(args_envs + p->args_len, args_envs_r, p->envs_len + sizeof(long) - 1); + /* p->args_len is not necessarily long-aligned, even if the memory + * below exists and is zeroed out - env must start aligned + */ + envs_offset = (p->args_len + sizeof(long) - 1) & ~(sizeof(long) - 1); + + memcpy_long(args_envs + envs_offset, args_envs_r, + p->envs_len + sizeof(long) - 1); /* Only map remote address if it wasn't specified as an argument */ if (!envs) { @@ -375,12 +381,12 @@ int prepare_process_ranges_args_envs(struct thread *thread, argv[i] = (char *)addr + (unsigned long)argv[i]; } - envc = *((long *)(args_envs + p->args_len)); + envc = *((long *)(args_envs + envs_offset)); dkprintf("envc: %d\n", envc); - env = (char **)(args_envs + p->args_len + sizeof(long)); + env = (char **)(args_envs + envs_offset + sizeof(long)); for (i = 0; i < envc; i++) { - env[i] = addr + p->args_len + env[i]; + env[i] = addr + envs_offset + env[i]; } dkprintf("env OK\n"); diff --git a/lib/string.c b/lib/string.c index eb1559f5..f5ac044e 100644 --- a/lib/string.c +++ b/lib/string.c @@ -234,7 +234,7 @@ int memcmp(const void *s1, const void *s2, size_t n) */ int flatten_strings_from_user(char *pre_strings, char **strings, char **flat) { - int full_len, i; + int full_len, len, i; int nr_strings = 0; int pre_strings_count = 0; int pre_strings_len = 0; @@ -333,5 +333,8 @@ int flatten_strings_from_user(char *pre_strings, char **strings, char **flat) _flat[nr_strings + pre_strings_count + 1] = p - (char *)_flat; *flat = (char *)_flat; - return p - (char *)_flat; + len = p - (char *)_flat; + if (len < full_len) + memset(p, 0, full_len - len); + return len; }