From patchwork Fri Oct 2 13:00:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Riku Voipio X-Patchwork-Id: 54429 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f198.google.com (mail-lb0-f198.google.com [209.85.217.198]) by patches.linaro.org (Postfix) with ESMTPS id 65A4A23009 for ; Fri, 2 Oct 2015 13:45:03 +0000 (UTC) Received: by lbwr8 with SMTP id r8sf16736405lbw.0 for ; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding:cc :subject:precedence:list-id:list-unsubscribe:list-archive:list-post :list-help:list-subscribe:errors-to:sender:x-original-sender :x-original-authentication-results:mailing-list; bh=rk+X9bGvOwwwRrTH+ZBnJxiMsT2tyDTBC880bdAuz0w=; b=A5ElSH+exlLoyLv4+2Mcre9XC38+EVcONwqZig4rk4Kglj0iinfLve0IHy6ypzafU9 9G30A0gtcVd19ggDNPGhM7Xr8G7noTPS/8i+9+ND+q6fYyz8GmmquAOCwAc9akcZMKqh PVaEQoB0M9EfkN0jrORSP6vwb93L7DgTFXtJqqOzhZAp+ALCaevBwQ8W5gFPwOzhE7JJ iHBkYDi7VjiRmDl8+/GJqSWC2kuHFPINzF1WimPnEMBs/jf4kn/9GqZVLkcfuwDc5kIv zihbAdBUX5O4ySn7PRM8XiFsC/iOf+FI55stCHeZEVH64uIYYto0NftWAe+sieEnLQJ8 caRg== X-Gm-Message-State: ALoCoQkC7sHxNr8yz9lnAREUAUXMfQzUosJOa2vunHc9Nw8Ln++Tw0r9pJdGVRcL4ean++fKq30B X-Received: by 10.112.202.165 with SMTP id kj5mr2603935lbc.5.1443793502377; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.25.22.162 with SMTP id 34ls229906lfw.11.gmail; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) X-Received: by 10.112.155.195 with SMTP id vy3mr5804877lbb.9.1443793502226; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) Received: from mail-lb0-f182.google.com (mail-lb0-f182.google.com. [209.85.217.182]) by mx.google.com with ESMTPS id wk2si6286482lbb.42.2015.10.02.06.45.02 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Oct 2015 06:45:02 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.182 as permitted sender) client-ip=209.85.217.182; Received: by lbbmp1 with SMTP id mp1so26754992lbb.1 for ; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) X-Received: by 10.25.40.130 with SMTP id o124mr3626887lfo.41.1443793502100; Fri, 02 Oct 2015 06:45:02 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp1255009lbq; Fri, 2 Oct 2015 06:45:00 -0700 (PDT) X-Received: by 10.55.204.144 with SMTP id n16mr19571089qkl.43.1443793484746; Fri, 02 Oct 2015 06:44:44 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id 79si10294127qhs.124.2015.10.02.06.44.44 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Fri, 02 Oct 2015 06:44:44 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:59863 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zi0dg-0000rU-7q for patch@linaro.org; Fri, 02 Oct 2015 09:44:44 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37332) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zhzxj-0005Nn-7e for qemu-devel@nongnu.org; Fri, 02 Oct 2015 09:01:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Zhzxe-0000dd-PK for qemu-devel@nongnu.org; Fri, 02 Oct 2015 09:01:23 -0400 Received: from mail-lb0-f182.google.com ([209.85.217.182]:33769) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Zhzxe-0000cp-68 for qemu-devel@nongnu.org; Fri, 02 Oct 2015 09:01:18 -0400 Received: by lbos8 with SMTP id s8so25981528lbo.0 for ; Fri, 02 Oct 2015 06:01:17 -0700 (PDT) X-Received: by 10.25.145.132 with SMTP id t126mr3547839lfd.88.1443790877445; Fri, 02 Oct 2015 06:01:17 -0700 (PDT) Received: from localhost.localdomain (91-157-196-38.elisa-laajakaista.fi. [91.157.196.38]) by smtp.gmail.com with ESMTPSA id w143sm1514751lfd.2.2015.10.02.06.01.16 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 02 Oct 2015 06:01:16 -0700 (PDT) From: riku.voipio@linaro.org To: qemu-devel@nongnu.org Date: Fri, 2 Oct 2015 16:00:59 +0300 Message-Id: <59baae9a626396a3a05840279084c4bf2beb8f40.1443790691.git.riku.voipio@linaro.org> X-Mailer: git-send-email 2.5.3 In-Reply-To: References: MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 209.85.217.182 Cc: =?UTF-8?q?Stefan=20Br=C3=BCns?= Subject: [Qemu-devel] [PULL 07/13] linux-user: remove MAX_ARG_PAGES limit X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: , List-Help: , List-Subscribe: , Errors-To: qemu-devel-bounces+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: riku.voipio@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.182 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 From: Stefan Brüns Instead of creating a temporary copy for the whole environment and the arguments, directly copy everything to the target stack. For this to work, we have to change the order of stack creation and copying the arguments. Reviewed-by: Peter Maydell Signed-off-by: Stefan Brüns Signed-off-by: Riku Voipio --- linux-user/elfload.c | 110 ++++++++++++++++++++++++------------------------- linux-user/flatload.c | 2 +- linux-user/linuxload.c | 7 ---- linux-user/qemu.h | 7 ---- linux-user/syscall.c | 6 --- 5 files changed, 56 insertions(+), 76 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ad46530..fdae6a6 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1373,66 +1373,69 @@ static bool elf_check_ehdr(struct elfhdr *ehdr) * to be put directly into the top of new user memory. * */ -static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, - abi_ulong p) +static abi_ulong copy_elf_strings(int argc, char **argv, char *scratch, + abi_ulong p, abi_ulong stack_limit) { - char *tmp, *tmp1, *pag = NULL; - int len, offset = 0; + char *tmp; + int len, offset; + abi_ulong top = p; if (!p) { return 0; /* bullet-proofing */ } + + offset = ((p - 1) % TARGET_PAGE_SIZE) + 1; + while (argc-- > 0) { tmp = argv[argc]; if (!tmp) { fprintf(stderr, "VFS: argc is wrong"); exit(-1); } - tmp1 = tmp; - while (*tmp++); - len = tmp - tmp1; - if (p < len) { /* this shouldn't happen - 128kB */ + len = strlen(tmp) + 1; + tmp += len; + + if (len > (p - stack_limit)) { return 0; } while (len) { - --p; --tmp; --len; - if (--offset < 0) { - offset = p % TARGET_PAGE_SIZE; - pag = (char *)page[p/TARGET_PAGE_SIZE]; - if (!pag) { - pag = g_try_malloc0(TARGET_PAGE_SIZE); - page[p/TARGET_PAGE_SIZE] = pag; - if (!pag) - return 0; - } - } - if (len == 0 || offset == 0) { - *(pag + offset) = *tmp; - } - else { - int bytes_to_copy = (len > offset) ? offset : len; - tmp -= bytes_to_copy; - p -= bytes_to_copy; - offset -= bytes_to_copy; - len -= bytes_to_copy; - memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); + int bytes_to_copy = (len > offset) ? offset : len; + tmp -= bytes_to_copy; + p -= bytes_to_copy; + offset -= bytes_to_copy; + len -= bytes_to_copy; + + memcpy_fromfs(scratch + offset, tmp, bytes_to_copy); + + if (offset == 0) { + memcpy_to_target(p, scratch, top - p); + top = p; + offset = TARGET_PAGE_SIZE; } } } + if (offset) { + memcpy_to_target(p, scratch + offset, top - p); + } + return p; } -static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, +/* Older linux kernels provide up to MAX_ARG_PAGES (default: 32) of + * argument/environment space. Newer kernels (>2.6.33) allow more, + * dependent on stack size, but guarantee at least 32 pages for + * backwards compatibility. + */ +#define STACK_LOWER_LIMIT (32 * TARGET_PAGE_SIZE) + +static abi_ulong setup_arg_pages(struct linux_binprm *bprm, struct image_info *info) { - abi_ulong stack_base, size, error, guard; - int i; + abi_ulong size, error, guard; - /* Create enough stack to hold everything. If we don't use - it for args, we'll use it for something else. */ size = guest_stack_size; - if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) { - size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; + if (size < STACK_LOWER_LIMIT) { + size = STACK_LOWER_LIMIT; } guard = TARGET_PAGE_SIZE; if (guard < qemu_real_host_page_size) { @@ -1450,18 +1453,8 @@ static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, target_mprotect(error, guard, PROT_NONE); info->stack_limit = error + guard; - stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; - p += stack_base; - - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { - if (bprm->page[i]) { - /* FIXME - check return value of memcpy_to_target() for failure */ - memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); - g_free(bprm->page[i]); - } - stack_base += TARGET_PAGE_SIZE; - } - return p; + + return info->stack_limit + size - sizeof(void *); } /* Map and zero the bss. We need to explicitly zero any fractional pages @@ -2203,6 +2196,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) struct image_info interp_info; struct elfhdr elf_ex; char *elf_interpreter = NULL; + char *scratch; info->start_mmap = (abi_ulong)ELF_START_MMAP; @@ -2214,18 +2208,24 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) when we load the interpreter. */ elf_ex = *(struct elfhdr *)bprm->buf; - bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); - bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); - bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); + /* Do this so that we can load the interpreter, if need be. We will + change some of these later */ + bprm->p = setup_arg_pages(bprm, info); + + scratch = g_new0(char, TARGET_PAGE_SIZE); + bprm->p = copy_elf_strings(1, &bprm->filename, scratch, + bprm->p, info->stack_limit); + bprm->p = copy_elf_strings(bprm->envc, bprm->envp, scratch, + bprm->p, info->stack_limit); + bprm->p = copy_elf_strings(bprm->argc, bprm->argv, scratch, + bprm->p, info->stack_limit); + g_free(scratch); + if (!bprm->p) { fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); exit(-1); } - /* Do this so that we can load the interpreter, if need be. We will - change some of these later */ - bprm->p = setup_arg_pages(bprm->p, bprm, info); - if (elf_interpreter) { load_elf_interp(elf_interpreter, &interp_info, bprm->buf); diff --git a/linux-user/flatload.c b/linux-user/flatload.c index 566a7a8..ceacb98 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -707,7 +707,7 @@ static int load_flat_shared_library(int id, struct lib_info *libs) int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) { struct lib_info libinfo[MAX_SHARED_LIBS]; - abi_ulong p = bprm->p; + abi_ulong p; abi_ulong stack_len; abi_ulong start_addr; abi_ulong sp; diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index 506e837..dbaf0ec 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -135,10 +135,7 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, struct linux_binprm *bprm) { int retval; - int i; - bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); - memset(bprm->page, 0, sizeof(bprm->page)); bprm->fd = fdexec; bprm->filename = (char *)filename; bprm->argc = count(argv); @@ -172,9 +169,5 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp, return retval; } - /* Something went wrong, return the inode and free the argument pages*/ - for (i=0 ; ipage[i]); - } return(retval); } diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 678e5d6..bd90cc3 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -143,12 +143,6 @@ extern const char *qemu_uname_release; extern unsigned long mmap_min_addr; /* ??? See if we can avoid exposing so much of the loader internals. */ -/* - * MAX_ARG_PAGES defines the number of pages allocated for arguments - * and envelope for the new program. 32 should suffice, this gives - * a maximum env+arg of 128kB w/4KB pages! - */ -#define MAX_ARG_PAGES 33 /* Read a good amount of data initially, to hopefully get all the program headers loaded. */ @@ -160,7 +154,6 @@ extern unsigned long mmap_min_addr; */ struct linux_binprm { char buf[BPRM_BUF_SIZE] __attribute__((aligned)); - void *page[MAX_ARG_PAGES]; abi_ulong p; int fd; int e_uid, e_gid; diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d1d3eb2..7fbaa8b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5808,12 +5808,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } *q = NULL; - /* This case will not be caught by the host's execve() if its - page size is bigger than the target's. */ - if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) { - ret = -TARGET_E2BIG; - goto execve_end; - } if (!(p = lock_user_string(arg1))) goto execve_efault; ret = get_errno(execve(p, argp, envp));