From patchwork Wed Nov 25 11:36:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Topi Miettinen X-Patchwork-Id: 41187 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2F6C43958C2E; Wed, 25 Nov 2020 11:36:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2F6C43958C2E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1606304215; bh=udisgVoiDHtn5sxh5jNNuCUWnqnkUEHhVzR2hUyw8ds=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=VnkSVaEsPvnjQ4FjH4LpWpIfP2RHvuH22/8oQCJWSSB47yyGvvyQYOXE0WV3ZRYbC /cy8Vi7pkr9/r6bVKl8Zr7R9z/78fX4X9x16yd74POt9hY2k6kJHBXBZNlyKNg/5U/ uYb45Vr8K23P2gZw0cTKinNww/soxVZoasKQqLcM= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mail-lj1-x243.google.com (mail-lj1-x243.google.com [IPv6:2a00:1450:4864:20::243]) by sourceware.org (Postfix) with ESMTPS id 8F7433861972 for ; Wed, 25 Nov 2020 11:36:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 8F7433861972 Received: by mail-lj1-x243.google.com with SMTP id f24so1895840ljk.13 for ; Wed, 25 Nov 2020 03:36:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=udisgVoiDHtn5sxh5jNNuCUWnqnkUEHhVzR2hUyw8ds=; b=BlzTGS++oGnBf/DwVLQ3fgV+NIhHmFFU5LV03E3kTsmTQZlBdbPi6ni1FQrmTvhs6h FrRu/M+Nul78NSyRpKL085COgUHpQtDuxqZQMMj6euSQBm5qKnYuqWeNRwFzntuJqvyT 2wU7t3bujaidhGmC2mbAseN/aLYAF+LUFA0oRJZ3fXA7STlbNlzfzWHnJMh30UxSlrfc 2kdG/BXMpVOfESr0o35tpwvH3A4wQNvF558lVU+QkdPA2C0Ydv6o3f/Dye/ZwnqbsR64 IEKQl6MB9HtMaV72NPMpAWrlokZOSs7RiCEvTMjmzAVMKKeznBUdf/Rl5ies/wIP5ebF d8wg== X-Gm-Message-State: AOAM532CkJMdb8k5dEzKbGZuLE857xpNIspOIbA0C2HBncp5qHlhaN2I spnPLae+SvBVMENmtRUmtp8NsEb7xXP3XA== X-Google-Smtp-Source: ABdhPJzoCCi42OaI/XLnCvN9fz4UKHDsXlI4Zs7GvMwvkU11wIXPKn/ht0+4VVMJQfBjd9T6ZZ07Xg== X-Received: by 2002:a2e:80c5:: with SMTP id r5mr1144790ljg.297.1606304211065; Wed, 25 Nov 2020 03:36:51 -0800 (PST) Received: from localhost.localdomain (88-114-211-119.elisa-laajakaista.fi. [88.114.211.119]) by smtp.gmail.com with ESMTPSA id e15sm224271lfn.292.2020.11.25.03.36.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Nov 2020 03:36:50 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH 1/3] csu: randomize location of TCB Date: Wed, 25 Nov 2020 13:36:30 +0200 Message-Id: <20201125113632.6486-2-toiwoton@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20201125113632.6486-1-toiwoton@gmail.com> References: <20201125113632.6486-1-toiwoton@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-8.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Topi Miettinen via Libc-alpha From: Topi Miettinen Reply-To: Topi Miettinen Cc: Topi Miettinen Errors-To: libc-alpha-bounces@sourceware.org Sender: "Libc-alpha" Use mmap() for allocating TCB except if instructed by tunable glibc.malloc.use_sbrk. This makes the location of TCB random instead of always staying predictably next to data segment. When using mmap(), improve the logic so that allocation of TCB can be assumed to fail insted of segfaulting. --- v2: introduce a tunable to use sbrk() Signed-off-by: Topi Miettinen --- csu/libc-tls.c | 48 +++++++++++++++++++++---- elf/dl-tunables.list | 7 ++++ manual/tunables.texi | 5 +++ sysdeps/unix/sysv/linux/mmap64.c | 19 ++++++++++ sysdeps/unix/sysv/linux/mmap_internal.h | 5 +++ 5 files changed, 78 insertions(+), 6 deletions(-) diff --git a/csu/libc-tls.c b/csu/libc-tls.c index c3589f0a7d..38c1e3a532 100644 --- a/csu/libc-tls.c +++ b/csu/libc-tls.c @@ -25,11 +25,21 @@ #include #include #include +#include +#include + +#define HAVE_MMAP_INTERNAL 0 +#include #ifdef SHARED #error makefile bug, this file is for static only #endif +#if HAVE_TUNABLES +# define TUNABLE_NAMESPACE malloc +#endif +#include + dtv_t _dl_static_dtv[2 + TLS_SLOTINFO_SURPLUS]; @@ -135,25 +145,51 @@ __libc_setup_tls (void) /* We have to set up the TCB block which also (possibly) contains 'errno'. Therefore we avoid 'malloc' which might touch 'errno'. - Instead we use 'sbrk' which would only uses 'errno' if it fails. - In this case we are right away out of memory and the user gets - what she/he deserves. */ + Instead we use '__mmap_internal' (when available) which does not + use 'errno', except if instructed by tunable + glibc.malloc.use_sbrk to use 'sbrk()' instead. If 'sbrk()' fails, + it will access 'errno' with catastrophic results. */ + + int error = 0; +#if HAVE_TUNABLES && HAVE_MMAP_INTERNAL + int use_sbrk = 0; + use_sbrk = TUNABLE_GET (use_sbrk, int32_t, NULL); +#endif + #if TLS_TCB_AT_TP /* Align the TCB offset to the maximum alignment, as _dl_allocate_tls_storage (in elf/dl-tls.c) does using __libc_memalign and dl_tls_static_align. */ tcb_offset = roundup (memsz + GLRO(dl_tls_static_surplus), max_align); - tlsblock = __sbrk (tcb_offset + TLS_INIT_TCB_SIZE + max_align); + size_t tlsblock_size = tcb_offset + TLS_INIT_TCB_SIZE + max_align; +#if HAVE_MMAP_INTERNAL + if (!use_sbrk) + tlsblock = __mmap_internal (NULL, tlsblock_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error); + else +#endif + tlsblock = __sbrk (tlsblock_size); + #elif TLS_DTV_AT_TP tcb_offset = roundup (TLS_INIT_TCB_SIZE, align ?: 1); - tlsblock = __sbrk (tcb_offset + memsz + max_align - + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus)); + size_t tlsblock_size = tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GLRO(dl_tls_static_surplus); +#if HAS_MMAP_INTERNAL + if (!use_sbrk) + tlsblock = __mmap_internal (NULL, tlsblock_size, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0, &error); + else +#endif + tlsblock = __sbrk (tlsblock_size); + tlsblock += TLS_PRE_TCB_SIZE; #else /* In case a model with a different layout for the TCB and DTV is defined add another #elif here and in the following #ifs. */ # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined" #endif + if (error) + _startup_fatal ("Cannot allocate TCB"); /* Align the TLS block. */ tlsblock = (void *) (((uintptr_t) tlsblock + max_align - 1) diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list index e1d8225128..777ebee788 100644 --- a/elf/dl-tunables.list +++ b/elf/dl-tunables.list @@ -91,6 +91,13 @@ glibc { minval: 0 security_level: SXID_IGNORE } + use_sbrk { + type: INT_32 + minval: 0 + maxval: 1 + default: 0 + security_level: SXID_IGNORE + } } cpu { hwcap_mask { diff --git a/manual/tunables.texi b/manual/tunables.texi index d72d7a5ec0..46132900e3 100644 --- a/manual/tunables.texi +++ b/manual/tunables.texi @@ -227,6 +227,11 @@ pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size passed to @code{malloc} for the largest bin size to enable. @end deftp +@deftp Tunable glibc.malloc.use_sbrk +A value of 1 instructs @theglibc{} to use @code{sbrk()} for memory +allocation instead of @code{mmap()}. +@end deftp + @node Dynamic Linking Tunables @section Dynamic Linking Tunables @cindex dynamic linking tunables diff --git a/sysdeps/unix/sysv/linux/mmap64.c b/sysdeps/unix/sysv/linux/mmap64.c index 8074deb466..11f7c3f99b 100644 --- a/sysdeps/unix/sysv/linux/mmap64.c +++ b/sysdeps/unix/sysv/linux/mmap64.c @@ -67,3 +67,22 @@ weak_alias (__mmap64, mmap) weak_alias (__mmap64, __mmap) libc_hidden_def (__mmap) #endif + +void * +__mmap_internal (void *addr, size_t len, int prot, int flags, int fd, off64_t offset, int *error) +{ + unsigned long int ret; +#ifdef __NR_mmap2 + ret = INTERNAL_SYSCALL_CALL (mmap2, addr, len, prot, flags, fd, + (off_t) (offset / MMAP2_PAGE_UNIT)); +#else + ret = INTERNAL_SYSCALL_CALL (mmap, addr, len, prot, flags, fd, offset); +#endif + if (INTERNAL_SYSCALL_ERROR_P(ret)) + { + *error = ret; + return MAP_FAILED; + } + + return (void *) ret; +} diff --git a/sysdeps/unix/sysv/linux/mmap_internal.h b/sysdeps/unix/sysv/linux/mmap_internal.h index d53f0c642a..6e90f6f71e 100644 --- a/sysdeps/unix/sysv/linux/mmap_internal.h +++ b/sysdeps/unix/sysv/linux/mmap_internal.h @@ -46,4 +46,9 @@ static uint64_t page_unit; INLINE_SYSCALL_CALL (__nr, __addr, __len, __prot, __flags, __fd, __offset) #endif +#undef HAVE_MMAP_INTERNAL +#define HAVE_MMAP_INTERNAL 1 +/* Internal version of mmap() which doesn't attempt to access errno */ +void *__mmap_internal (void *addr, size_t len, int prot, int flags, int fd, off64_t offset, int *error); + #endif /* MMAP_INTERNAL_LINUX_H */