From patchwork Fri Oct 28 13:05:09 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 688386 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3t53s45lnjz9snk for ; Sat, 29 Oct 2016 00:05:28 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.b=BPZDwKID; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; q=dns; s=default; b= Dh+j3vW8+RkoIc6SfU2pN70kAPC53FYnte45YEPfKajGO7enXGUc7ow+MvjXyUC9 tdQ1rS2GlY+Q0cHIAN3B8UZrAKNHhSd5eemlaks+l1ft8+YfYFX6DHtKYP881PV1 mJ5yg7FjK3OCOay0tzMgEZvTlelmWL/UYjX/ci0fLFY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:date:to:subject:mime-version:content-type :content-transfer-encoding:message-id:from; s=default; bh=dmmIsp lUMlWa4D1JWE7ssrnNOY4=; b=BPZDwKIDnGlpWIoRRe3be2BIvtBJ7M6yUKPw27 kDATEz2Gwc8cVBlgY9KZ3FLEiDHGMSUVWyXFpWjX9KtKGVunueECTateZA6IFq7b OpG6v/jBWsooS115bZmkUGfkxWxVNAI+vijdoY1kLTtcnaAhCl84/kiMAFY6DJGh QENVA= Received: (qmail 113797 invoked by alias); 28 Oct 2016 13:05:22 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 113780 invoked by uid 89); 28 Oct 2016 13:05:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.3 required=5.0 tests=BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=checkers, protecting, leakage, 2114 X-HELO: mx1.redhat.com Date: Fri, 28 Oct 2016 15:05:09 +0200 To: libc-alpha@sourceware.org Subject: [PATCH] Generate additional secret keys for the heap protector User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20161028130509.A74DC439942E0@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) 2016-10-27 Florian Weimer * elf/dl-keysetup.h: New file. * elf/dl-keysetup.c: Likewise. * elf/Makefile (dl-routines): Add dl-keysetup. * csu/libc-start.c (LIBC_START_MAIN): Call __compute_keys to obtain key material. * elf/rtld.c (security_init): Likewise. * crypt/sha256.c: Use relative #include for sha256-block.c diff --git a/crypt/sha256.c b/crypt/sha256.c index b5497d9..a6ab2e1 100644 --- a/crypt/sha256.c +++ b/crypt/sha256.c @@ -211,4 +211,4 @@ __sha256_process_bytes (const void *buffer, size_t len, struct sha256_ctx *ctx) } } -#include +#include "sha256-block.c" diff --git a/csu/libc-start.c b/csu/libc-start.c index 99c040a..333a4cc 100644 --- a/csu/libc-start.c +++ b/csu/libc-start.c @@ -21,6 +21,7 @@ #include #include #include +#include extern void __libc_init_first (int argc, char **argv, char **envp); @@ -192,21 +193,21 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL), we need to setup errno. */ __pthread_initialize_minimal (); + struct key_setup keys; + __compute_keys (_dl_random, &keys); + /* Set up the stack checker's canary. */ - uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); # ifdef THREAD_SET_STACK_GUARD - THREAD_SET_STACK_GUARD (stack_chk_guard); + THREAD_SET_STACK_GUARD (keys.stack); # else - __stack_chk_guard = stack_chk_guard; + __stack_chk_guard = keys.stack; # endif /* Set up the pointer guard value. */ - uintptr_t pointer_chk_guard = _dl_setup_pointer_guard (_dl_random, - stack_chk_guard); # ifdef THREAD_SET_POINTER_GUARD - THREAD_SET_POINTER_GUARD (pointer_chk_guard); + THREAD_SET_POINTER_GUARD (keys.pointer); # else - __pointer_chk_guard_local = pointer_chk_guard; + __pointer_chk_guard_local = keys.pointer; # endif #endif diff --git a/elf/Makefile b/elf/Makefile index 82c7e05..c0a8e2e 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -31,7 +31,8 @@ routines = $(all-dl-routines) dl-support dl-iteratephdr \ dl-routines = $(addprefix dl-,load lookup object reloc deps hwcaps \ runtime error init fini debug misc \ version profile conflict tls origin scope \ - execstack caller open close trampoline) + execstack caller open close trampoline \ + keysetup) ifeq (yes,$(use-ldconfig)) dl-routines += dl-cache endif diff --git a/elf/dl-keysetup.c b/elf/dl-keysetup.c new file mode 100644 index 0000000..45bd4de --- /dev/null +++ b/elf/dl-keysetup.c @@ -0,0 +1,77 @@ +/* Compute secret keys used for protection heuristics. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see . */ + +#include +#include + +enum { at_random_size = 16 }; + +#if __WORDSIZE == 64 +enum { sha256_output_size = 32 }; +static void compute_sha256_of_random (const void *random, void *result); +#endif + +void +__compute_keys (const void *random, struct key_setup *result) +{ +#if __WORDSIZE == 32 + _Static_assert (sizeof (*result) == at_random_size, + "no key expansion required"); + memcpy (random, result, sizeof (result)); +#else + /* We use SHA-256 to expand the 16 bytes of randomness into 32 + bytes, so that it is hard to guess the remaining keys once a + subset of them is known. */ + _Static_assert (sizeof (*result) == sha256_output_size, + "SHA-256 provides required size"); + compute_sha256_of_random (random, result); +#endif + + /* Prevent leakage of the stack canary through a read buffer + overflow of a NUL-terminated string. */ + *(char *) &result->stack = '\0'; + + /* Clear the lowest three bits in the heap header guard value, so + that the flag bits remain unchanged. */ + result->heap_header <<= 3; +} + +#if __WORDSIZE == 64 + +#pragma GCC visibility push (hidden) + +/* Avoid symbol collisions with libcrypt. */ +#define __sha256_process_block __dl_sha256_process_block +#define __sha256_init_ctx __dl_sha256_init_ctx +#define __sha256_process_bytes __dl_sha256_process_bytes +#define __sha256_finish_ctx __dl_sha256_finish_ctx + +#include "../crypt/sha256.h" +#include "../crypt/sha256.c" + +#pragma GCC visibility pop + +static void +compute_sha256_of_random (const void *random, void *result) +{ + struct sha256_ctx ctx; + __sha256_init_ctx (&ctx); + __sha256_process_bytes (random, at_random_size, &ctx); + __sha256_finish_ctx (&ctx, result); +} +#endif diff --git a/elf/dl-keysetup.h b/elf/dl-keysetup.h new file mode 100644 index 0000000..3c7e9bb --- /dev/null +++ b/elf/dl-keysetup.h @@ -0,0 +1,45 @@ +/* Compute secret keys used for protection heuristics. + Copyright (C) 2016 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see . */ + +#ifndef KEY_SETUP_H +#define KEY_SETUP_H + +#include + +/* The set of protection keys used by glibc. */ +struct key_setup +{ + /* Canary for the stack-smashing protector. */ + uintptr_t stack; + + /* Pointer guard, protecting selected function pointers. */ + uintptr_t pointer; + + /* Heap guard, proctecting the malloc chunk header. */ + uintptr_t heap_header; + + /* Heap guard part two, protecting the previous chunk size field. */ + uintptr_t heap_footer; +}; + +/* Derive the keys in *RESULT from RANDOM, which comes from the + auxiliary vector and points to 16 bytes of randomness. */ +void __compute_keys (const void *random, struct key_setup *result) + attribute_hidden; + +#endif /* KEY_SETUP_H */ diff --git a/elf/rtld.c b/elf/rtld.c index 647661c..de965da 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -699,21 +700,21 @@ rtld_lock_default_unlock_recursive (void *lock) static void security_init (void) { + struct key_setup keys; + __compute_keys (_dl_random, &keys); + /* Set up the stack checker's canary. */ - uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (_dl_random); #ifdef THREAD_SET_STACK_GUARD - THREAD_SET_STACK_GUARD (stack_chk_guard); + THREAD_SET_STACK_GUARD (keys.stack); #else - __stack_chk_guard = stack_chk_guard; + __stack_chk_guard = keys.stack; #endif /* Set up the pointer guard as well, if necessary. */ - uintptr_t pointer_chk_guard - = _dl_setup_pointer_guard (_dl_random, stack_chk_guard); #ifdef THREAD_SET_POINTER_GUARD - THREAD_SET_POINTER_GUARD (pointer_chk_guard); + THREAD_SET_POINTER_GUARD (keys.pointer); #endif - __pointer_chk_guard_local = pointer_chk_guard; + __pointer_chk_guard_local = keys.pointer; /* We do not need the _dl_random value anymore. The less information we leave behind, the better, so clear the