From patchwork Fri Aug 21 23:38:47 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Kennelly X-Patchwork-Id: 11730765 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 94C63722 for ; Fri, 21 Aug 2020 23:39:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 7DD522072D for ; Fri, 21 Aug 2020 23:39:00 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="tLmds5aw" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726826AbgHUXi7 (ORCPT ); Fri, 21 Aug 2020 19:38:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726767AbgHUXiz (ORCPT ); Fri, 21 Aug 2020 19:38:55 -0400 Received: from mail-qt1-x849.google.com (mail-qt1-x849.google.com [IPv6:2607:f8b0:4864:20::849]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0DAE9C061755 for ; Fri, 21 Aug 2020 16:38:55 -0700 (PDT) Received: by mail-qt1-x849.google.com with SMTP id b1so2413320qto.17 for ; Fri, 21 Aug 2020 16:38:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=wTTHOHLUpSJsOh9SXDMCY9S+w0wdFVpDu5cnszimX/A=; b=tLmds5awKD+FJoYN96kwnKij9GFM/pG0TOWm3XWwY7RIPcUjATUDrfyrJrQHJCIuzC 1XkCFnYfVOwG4ca9Ki81zRk1PhWizTWjfLzpUDIPranMwe2BF7S7EkBFFJOPFd4Fsowu mI5rukKBOLTTHJ4/nYEbTb880O4uHKMJEgSXs3YGPYNRJX05+3Nt942vNchy7zJ9wRCQ AHQPoZRCMKnAF7feD2eHbZyckVSJJNYAXEC1gJLDzthOagDsvKQweXy0SYabreDRZB8u RQfpslAk12zxgl0x4N4FK0656RUYGMeudH2TuA63k+nFdKUF0RsEKAtOhy/2bPsy54B1 N87A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=wTTHOHLUpSJsOh9SXDMCY9S+w0wdFVpDu5cnszimX/A=; b=MpsILJVEzLWsk8M8qAuVpqw9oiVje4EvlVGzwukYmu2g7XnpZedikWcuWt4Q9+6aZD sa+ZSVkNx3fV1N+aFeD7iQGqzvNAXMPIGPnMfJuvpow6MVjy/1VsScLXURHEWSHb5v0O DbkFa6PUPbxUEbC5TedmmPHIsIm0S9k50GlRJAq6FUvKqF2YVcJ1Ysd2dgPzxrN8+nvm O4vDlvU2z856X/+Fe3s6I1ay5JhjyAvcgcZUAZmkVAqKk0zas6beiOGpl3KYpCFEMnO/ YCPAXDOCiFuTy7aq+vjBRBXeJqNIUP9vi51obS+1+KfnANok3nBWnK+9yRhkkLuKSOX+ kvqA== X-Gm-Message-State: AOAM5318C+c91F3+OaeSw52OyQ6Q5Agb05FJQHjtf9/iayric7NK227E /OUSrTuIjdTYrUbZ0QF13r/mtUJgZ7rmIaw= X-Google-Smtp-Source: ABdhPJy4/FIHmfbB1ei2uKSt3zT5fgTFGlHdwFHL+MIq3vrWnFAajV1NZ4y5+CZc6pq3XXE0PYqMN2s1gQsfAUc= X-Received: from ckennelly28.nyc.corp.google.com ([2620:0:1003:1003:3e52:82ff:fe5a:a91a]) (user=ckennelly job=sendgmr) by 2002:a05:6214:184b:: with SMTP id d11mr4672334qvy.21.1598053133560; Fri, 21 Aug 2020 16:38:53 -0700 (PDT) Date: Fri, 21 Aug 2020 19:38:47 -0400 In-Reply-To: <20200821233848.3904680-1-ckennelly@google.com> Message-Id: <20200821233848.3904680-2-ckennelly@google.com> Mime-Version: 1.0 References: <20200821233848.3904680-1-ckennelly@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH v4 1/2] fs/binfmt_elf: Use PT_LOAD p_align values for suitable start address. From: Chris Kennelly To: Alexander Viro , Alexey Dobriyan , Song Liu Cc: David Rientjes , Ian Rogers , Hugh Dickens , Andrew Morton , Suren Baghdasaryan , Sandeep Patil , Fangrui Song , Nick Desaulniers , clang-built-linux@googlegroups.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Kennelly Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org The current ELF loading mechancism provides page-aligned mappings. This can lead to the program being loaded in a way unsuitable for file-backed, transparent huge pages when handling PIE executables. For binaries built with increased alignment, this limits the number of bits usable for ASLR, but provides some randomization over using fixed load addresses/non-PIE binaries. Tested: verified program with -Wl,-z,max-page-size=0x200000 loading Signed-off-by: Chris Kennelly --- fs/binfmt_elf.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 13d053982dd73..96370e3e36872 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -421,6 +422,26 @@ static int elf_read(struct file *file, void *buf, size_t len, loff_t pos) return 0; } +static unsigned long maximum_alignment(struct elf_phdr *cmds, int nr) +{ + unsigned long alignment = 0; + int i; + + for (i = 0; i < nr; i++) { + if (cmds[i].p_type == PT_LOAD) { + unsigned long p_align = cmds[i].p_align; + + /* skip non-power of two alignments as invalid */ + if (!is_power_of_2(p_align)) + continue; + alignment = max(alignment, p_align); + } + } + + /* ensure we align to at least one page */ + return ELF_PAGEALIGN(alignment); +} + /** * load_elf_phdrs() - load ELF program headers * @elf_ex: ELF header of the binary whose program headers should be loaded @@ -1008,6 +1029,7 @@ static int load_elf_binary(struct linux_binprm *bprm) int elf_prot, elf_flags; unsigned long k, vaddr; unsigned long total_size = 0; + unsigned long alignment; if (elf_ppnt->p_type != PT_LOAD) continue; @@ -1086,6 +1108,9 @@ static int load_elf_binary(struct linux_binprm *bprm) load_bias = ELF_ET_DYN_BASE; if (current->flags & PF_RANDOMIZE) load_bias += arch_mmap_rnd(); + alignment = maximum_alignment(elf_phdata, elf_ex->e_phnum); + if (alignment) + load_bias &= ~(alignment - 1); elf_flags |= MAP_FIXED; } else load_bias = 0; From patchwork Fri Aug 21 23:38:48 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Kennelly X-Patchwork-Id: 11730767 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 088A9722 for ; Fri, 21 Aug 2020 23:39:18 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DBAE42087D for ; Fri, 21 Aug 2020 23:39:17 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (2048-bit key) header.d=google.com header.i=@google.com header.b="julErzN+" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726875AbgHUXjO (ORCPT ); Fri, 21 Aug 2020 19:39:14 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:44800 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726772AbgHUXi4 (ORCPT ); Fri, 21 Aug 2020 19:38:56 -0400 Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7217CC061573 for ; Fri, 21 Aug 2020 16:38:56 -0700 (PDT) Received: by mail-qk1-x74a.google.com with SMTP id a186so2455128qke.1 for ; Fri, 21 Aug 2020 16:38:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=sender:date:in-reply-to:message-id:mime-version:references:subject :from:to:cc; bh=TSLmEPwlFccaRVuUrhKv3FaWDdmO/JVWcm6IHHbjArg=; b=julErzN+mNPctjW2tIYSo2PVDr4mRN4OJ3eGmTv5d1wb7Fd6DgqQWFQB7bdtal6SdY iNYxrxVIY+EbA9V1RcNlGRxzADVibuS9oI+04OoasYO5Pf9vUMe7437Mcu56WzjFDcUa 4ObuI9OL5wXGcAgNoYV5FEINB0ml+WfOj6jmH8BXWLXzQ3Y4qJqpUZN32AqsdxaJUwY3 eP95eJk7+yipnN1kilTzgkButU4Gtk8DM6+tjomNOLFc9R9cMZdmqtFciG4JS87A2uHh zGg9izTeWf76F5fHLjM4k4RXpCifGN81O9Fvh+/WndzTyEoPHH7YDuwZhrtTzQI3fJ6K LykA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=TSLmEPwlFccaRVuUrhKv3FaWDdmO/JVWcm6IHHbjArg=; b=g/wSQSFs1HqCZIvkG6WcT5k7s+p0gqX0CZOW5x88mIPFCKjHgCzYeybZbwnEGldq6h mABmS9trviie5CTShctI583HAczcMnvvC6ucN4DPIzKPV90Da6AHXqpCBT3yQ74qkKXX 7ebUa9Qd/HdFlHDPVDdPg+MaUBAWL70B9t2525LcaGadJ2kVsrmg0cdtvgKsEdc8vHtL DisoglFR9JjV2FfvIBkT7ML2MdqT676kMgCj3GzXYElaDODg2knUwGwkttKk21jWcWBt hUqKqbKgy8hVXOSoMEppSd6xpRCyIQie6J8A/y6bUMjHk1NXlv1pWE/j/Xos01baI9Uf GhQg== X-Gm-Message-State: AOAM532czp44quJTDtHGfs40Y8l9jAoDHYPSin1Mv2vR8i2bqYpJ3SxM +j8LIFJH9oBOw25C7Qf4wEm7iFsmLdEznUw= X-Google-Smtp-Source: ABdhPJwqfP5FHmg5WUuShDAHQ+afX+0COMOTSMvOLitOZZeWUhCwlY7NYdc5FsUHW8TW0XkGIpD5Fk3T2ZMwv0s= X-Received: from ckennelly28.nyc.corp.google.com ([2620:0:1003:1003:3e52:82ff:fe5a:a91a]) (user=ckennelly job=sendgmr) by 2002:a05:6214:d6c:: with SMTP id 12mr4515046qvs.208.1598053135628; Fri, 21 Aug 2020 16:38:55 -0700 (PDT) Date: Fri, 21 Aug 2020 19:38:48 -0400 In-Reply-To: <20200821233848.3904680-1-ckennelly@google.com> Message-Id: <20200821233848.3904680-3-ckennelly@google.com> Mime-Version: 1.0 References: <20200821233848.3904680-1-ckennelly@google.com> X-Mailer: git-send-email 2.28.0.297.g1956fa8f8d-goog Subject: [PATCH v4 2/2] Add self-test for verifying load alignment. From: Chris Kennelly To: Alexander Viro , Alexey Dobriyan , Song Liu Cc: David Rientjes , Ian Rogers , Hugh Dickens , Andrew Morton , Suren Baghdasaryan , Sandeep Patil , Fangrui Song , Nick Desaulniers , clang-built-linux@googlegroups.com, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Chris Kennelly Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org This produces a PIE binary with a variety of p_align requirements, suitable for verifying that the load address meets that alignment requirement. Signed-off-by: Chris Kennelly --- tools/testing/selftests/exec/.gitignore | 1 + tools/testing/selftests/exec/Makefile | 9 ++- tools/testing/selftests/exec/load_address.c | 68 +++++++++++++++++++++ 3 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tools/testing/selftests/exec/load_address.c diff --git a/tools/testing/selftests/exec/.gitignore b/tools/testing/selftests/exec/.gitignore index 344a99c6da1b7..9e2f00343f15f 100644 --- a/tools/testing/selftests/exec/.gitignore +++ b/tools/testing/selftests/exec/.gitignore @@ -7,6 +7,7 @@ execveat.moved execveat.path.ephemeral execveat.ephemeral execveat.denatured +/load_address_* /recursion-depth xxxxxxxx* pipe diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile index 0a13b110c1e66..cf69b2fcce59e 100644 --- a/tools/testing/selftests/exec/Makefile +++ b/tools/testing/selftests/exec/Makefile @@ -4,7 +4,7 @@ CFLAGS += -Wno-nonnull CFLAGS += -D_GNU_SOURCE TEST_PROGS := binfmt_script non-regular -TEST_GEN_PROGS := execveat +TEST_GEN_PROGS := execveat load_address_4096 load_address_2097152 load_address_16777216 TEST_GEN_FILES := execveat.symlink execveat.denatured script subdir pipe # Makefile is a run-time dependency, since it's accessed by the execveat test TEST_FILES := Makefile @@ -27,4 +27,9 @@ $(OUTPUT)/execveat.symlink: $(OUTPUT)/execveat $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat cp $< $@ chmod -x $@ - +$(OUTPUT)/load_address_4096: load_address.c + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie $< -o $@ +$(OUTPUT)/load_address_2097152: load_address.c + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie $< -o $@ +$(OUTPUT)/load_address_16777216: load_address.c + $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@ diff --git a/tools/testing/selftests/exec/load_address.c b/tools/testing/selftests/exec/load_address.c new file mode 100644 index 0000000000000..d487c2f6a6150 --- /dev/null +++ b/tools/testing/selftests/exec/load_address.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include +#include +#include + +struct Statistics { + unsigned long long load_address; + unsigned long long alignment; +}; + +int ExtractStatistics(struct dl_phdr_info *info, size_t size, void *data) +{ + struct Statistics *stats = (struct Statistics *) data; + int i; + + if (info->dlpi_name != NULL && info->dlpi_name[0] != '\0') { + // Ignore headers from other than the executable. + return 2; + } + + stats->load_address = (unsigned long long) info->dlpi_addr; + stats->alignment = 0; + + for (i = 0; i < info->dlpi_phnum; i++) { + if (info->dlpi_phdr[i].p_type != PT_LOAD) + continue; + + if (info->dlpi_phdr[i].p_align > stats->alignment) + stats->alignment = info->dlpi_phdr[i].p_align; + } + + return 1; // Terminate dl_iterate_phdr. +} + +int main(int argc, char **argv) +{ + struct Statistics extracted; + unsigned long long misalign; + int ret; + + ret = dl_iterate_phdr(ExtractStatistics, &extracted); + if (ret != 1) { + fprintf(stderr, "FAILED\n"); + return 1; + } + + if (extracted.alignment == 0) { + fprintf(stderr, "No alignment found\n"); + return 1; + } else if (extracted.alignment & (extracted.alignment - 1)) { + fprintf(stderr, "Alignment is not a power of 2\n"); + return 1; + } + + misalign = extracted.load_address & (extracted.alignment - 1); + if (misalign) { + printf("alignment = %llu, load_address = %llu\n", + extracted.alignment, extracted.load_address); + fprintf(stderr, "FAILED\n"); + return 1; + } + + fprintf(stderr, "PASS\n"); + return 0; +}