From patchwork Mon Jun 20 06:43:13 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: vincent X-Patchwork-Id: 101038 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 376FBB6FDD for ; Mon, 20 Jun 2011 16:48:20 +1000 (EST) Received: from localhost ([::1]:39711 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QYYHP-0005z9-9c for incoming@patchwork.ozlabs.org; Mon, 20 Jun 2011 02:48:15 -0400 Received: from eggs.gnu.org ([140.186.70.92]:41993) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QYYFV-0005yz-D3 for qemu-devel@nongnu.org; Mon, 20 Jun 2011 02:46:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QYYFU-0001PZ-35 for qemu-devel@nongnu.org; Mon, 20 Jun 2011 02:46:17 -0400 Received: from eu1sys200aog118.obsmtp.com ([207.126.144.145]:36759) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QYYFT-0001PG-Ok for qemu-devel@nongnu.org; Mon, 20 Jun 2011 02:46:16 -0400 Received: from beta.dmz-eu.st.com ([164.129.1.35]) (using TLSv1) by eu1sys200aob118.postini.com ([207.126.147.11]) with SMTP ID DSNKTf7sr5iy0s6yE4vXBRztUAIcN/kQazTU@postini.com; Mon, 20 Jun 2011 06:46:15 UTC Received: from zeta.dmz-eu.st.com (ns2.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id BF8CEC5; Mon, 20 Jun 2011 06:45:52 +0000 (GMT) Received: from Webmail-eu.st.com (safex1hubcas2.st.com [10.75.90.16]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id 8677919E6; Mon, 20 Jun 2011 06:45:52 +0000 (GMT) Received: from localhost.localdomain (164.129.122.152) by webmail-eu.st.com (10.75.90.13) with Microsoft SMTP Server (TLS) id 8.2.234.1; Mon, 20 Jun 2011 08:45:51 +0200 From: =?UTF-8?q?C=C3=A9dric=20VINCENT?= To: Date: Mon, 20 Jun 2011 08:43:13 +0200 Message-ID: <1308552193-16815-1-git-send-email-cedric.vincent@st.com> X-Mailer: git-send-email 1.7.5.1 In-Reply-To: <4DE65BE3.1040004@twiddle.net> References: <4DE65BE3.1040004@twiddle.net> MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) X-Received-From: 207.126.144.145 Cc: Laurent ALFONSI , =?UTF-8?q?C=C3=A9dric=20VINCENT?= , Riku Voipio , Richard Henderson Subject: [Qemu-devel] [PATCH v3] linux-user: Define AT_RANDOM to support target stack protection mechanism. 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+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Laurent ALFONSI Note that the support for the command-line argument requires: 1. add the new field "uint8_t rand_bytes[16]" to "struct image_info" since only the variable "info" lives both in main() and in create_elf_tables() 2. write a dedicated parser to convert the command-line to fill rand_bytes[] These two steps aren't really hard to achieve but I finally think they are a little bit overkill regarding the purpose of these 16 bytes. Maybe we could always fill the 16 bytes pointed to by AT_RANDOM with zero if we really want to get reproducibility. Regards, Cédric. 8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<----8<---- The dynamic linker from the GNU C library v2.10+ uses the ELF auxiliary vector AT_RANDOM [1] as a pointer to 16 bytes with random values to initialize the stack protection mechanism. Technically the emulated GNU dynamic linker crashes due to a NULL pointer derefencement if it is built with stack protection enabled and if AT_RANDOM is not defined by the QEMU ELF loader. [1] This ELF auxiliary vector was introduced in Linux v2.6.29. This patch can be tested with the code above: #include /* Elf*_auxv_t, AT_RANDOM, */ #include /* printf(3), */ #include /* exit(3), EXIT_*, */ #include /* uint8_t, */ #include /* memcpy(3), */ #if defined(__LP64__) || defined(__ILP64__) || defined(__LLP64__) # define Elf_auxv_t Elf64_auxv_t #else # define Elf_auxv_t Elf32_auxv_t #endif main(int argc, char* argv[], char* envp[]) { Elf_auxv_t *auxv; /* *envp = NULL marks end of envp. */ while (*envp++ != NULL); /* auxv->a_type = AT_NULL marks the end of auxv. */ for (auxv = (Elf_auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { if (auxv->a_type == AT_RANDOM) { int i; uint8_t rand_bytes[16]; printf("AT_RANDOM is: 0x%x\n", auxv->a_un.a_val); memcpy(rand_bytes, (const uint8_t *)auxv->a_un.a_val, sizeof(rand_bytes)); printf("it points to: "); for (i = 0; i < 16; i++) { printf("0x%02x ", rand_bytes[i]); } printf("\n"); exit(EXIT_SUCCESS); } } exit(EXIT_FAILURE); } Changes introduced in v2 and v3: * Fix typos + thinko (AT_RANDOM is used for stack canary, not for ASLR) * AT_RANDOM points to 16 random bytes stored inside the user stack. * Add a small test program. Signed-off-by: Cédric VINCENT Signed-off-by: Laurent ALFONSI --- linux-user/elfload.c | 21 ++++++++++++++++++++- 1 files changed, 20 insertions(+), 1 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index dcfeb7a..23c69d9 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -927,7 +927,7 @@ struct exec #define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1)) #define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) -#define DLINFO_ITEMS 12 +#define DLINFO_ITEMS 13 static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) { @@ -1202,6 +1202,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, { abi_ulong sp; int size; + int i; + abi_ulong u_rand_bytes; + uint8_t k_rand_bytes[16]; abi_ulong u_platform; const char *k_platform; const int n = sizeof(elf_addr_t); @@ -1231,6 +1234,20 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, /* FIXME - check return value of memcpy_to_target() for failure */ memcpy_to_target(sp, k_platform, len); } + + /* + * Generate 16 random bytes for userspace PRNG seeding (not + * cryptically secure but it's not the aim of QEMU). + */ + srand((unsigned int) time(NULL)); + for (i = 0; i < 16; i++) { + k_rand_bytes[i] = rand(); + } + sp -= 16; + u_rand_bytes = sp; + /* FIXME - check return value of memcpy_to_target() for failure */ + memcpy_to_target(sp, k_rand_bytes, 16); + /* * Force 16 byte _final_ alignment here for generality. */ @@ -1271,6 +1288,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); + NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); + if (k_platform) NEW_AUX_ENT(AT_PLATFORM, u_platform); #ifdef ARCH_DLINFO