From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x62b.google.com (mail-pl1-x62b.google.com [IPv6:2607:f8b0:4864:20::62b]) by sourceware.org (Postfix) with ESMTPS id 657DE3857409; Wed, 11 May 2022 17:51:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 657DE3857409 Received: by mail-pl1-x62b.google.com with SMTP id d22so2587267plr.9; Wed, 11 May 2022 10:51:15 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=YZIkDoLJ/k2mXOuvbodES4QBeALYwVlQ4uKH4hkVKEs=; b=uaUhqFG6+IIXmD9dJQXBMr9hJJ45MJYeW52DObBexwcVsxSKq6irJ6DVqCciAuxrhX om53R0CwfCLJY93DnRhqX2IYmjxxJ50g/MlZAG6pNU6XZWmVvpcbzWAKHe4wiKt0LWQr /ntlH6ek/9ZZgKxudfDdYraz82X5NEBjFL9JcEdcCSfYtKM0ziU0Fl15aU40LtUD6kRG L9FFa4wB0dm/2XnoDtoQnwlNIPvbujpio09t7uFaWRcp9vrJY0ciE3ZFoQzcPoNVRuhn 86pqMU/UNQGCkT+hqQl1EtLuD9F7lUQSFd+lp7F8d2HE9/bjfsmLq3jJxD42zexy8el3 EbaA== X-Gm-Message-State: AOAM532DQpkAwXhRid2BYILS97MkV5kO5WJtlLVYdjb5r07y8tBB/NuS 806B+Rm5oo2bKhUw8f1M7QZ3hAUEwQmHZU7prW16cqs4TQY= X-Google-Smtp-Source: ABdhPJxCCekz7NtrBZxXQpx2fe+IOXUEKkg+6I7tzspM0NhMikoowPyTl1xsdarXve0CZpiFe9IJcgrcYMLTKMS9+wA= X-Received: by 2002:a17:90b:1b44:b0:1dc:315f:4510 with SMTP id nv4-20020a17090b1b4400b001dc315f4510mr6577295pjb.28.1652291474298; Wed, 11 May 2022 10:51:14 -0700 (PDT) MIME-Version: 1.0 References: <871qx0dmz5.fsf@oldenburg.str.redhat.com> In-Reply-To: <871qx0dmz5.fsf@oldenburg.str.redhat.com> From: "H.J. Lu" Date: Wed, 11 May 2022 10:50:37 -0700 Message-ID: Subject: Re: PT_GNU_RELRO is somewhat broken To: Florian Weimer Cc: binutils@sourceware.org, libc-alpha@sourceware.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-3019.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 May 2022 17:51:17 -0000 On Wed, May 11, 2022 at 9:59 AM Florian Weimer via Libc-alpha wrote: > > PT_GNU_RELRO is supposed to identify a region in the process image which > has to be flipped to PROT_READ (only) permission after relocation > (=E2=80=9CRead-Only after RELocation=E2=80=9D). > > glibc has this code in the dynamic loader in elf/dl-reloc.c: > > | void > | _dl_protect_relro (struct link_map *l) > | { > | ElfW(Addr) start =3D ALIGN_DOWN((l->l_addr > | + l->l_relro_addr), > | GLRO(dl_pagesize)); > | ElfW(Addr) end =3D ALIGN_DOWN((l->l_addr > | + l->l_relro_addr > | + l->l_relro_size), > | GLRO(dl_pagesize)); > | if (start !=3D end > | && __mprotect ((void *) start, end - start, PROT_READ) < 0) > | { > | static const char errstring[] =3D N_("\ > | cannot apply additional memory protection after relocation"); > | _dl_signal_error (errno, l->l_name, NULL, errstring); > | } > | } > > I assume the intent is to conservatively apply the largest possible > RELRO region given GLRO(dl_pagesize), the run-time page size reported by > the kernel. If the binary is built to a smaller page size (to save disk > space), glibc can still load it, but apply only some RELRO protection. > But _dl_relocate_object has a bug: to be conservative, it would have to > use ALGIN_UP for the start (lower) address of the range. > > But it turns out we can't make this change without incurring a loss of > hardening: BFD ld does not align the start address to a page boundary. > For example, /bin/true in Fedora 35 x86-64 has this: > > | $ readelf -l /bin/true > | > | Elf file type is DYN (Position-Independent Executable file) > | Entry point 0x1960 > | There are 13 program headers, starting at offset 64 > | > | Program Headers: > | Type Offset VirtAddr PhysAddr > | FileSiz MemSiz Flags Align > | PHDR 0x0000000000000040 0x0000000000000040 0x00000000000000= 40 > | 0x00000000000002d8 0x00000000000002d8 R 0x8 > | INTERP 0x0000000000000318 0x0000000000000318 0x00000000000003= 18 > | 0x000000000000001c 0x000000000000001c R 0x1 > | [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] > | LOAD 0x0000000000000000 0x0000000000000000 0x00000000000000= 00 > | 0x0000000000000ff8 0x0000000000000ff8 R 0x1000 > | LOAD 0x0000000000001000 0x0000000000001000 0x00000000000010= 00 > | 0x00000000000029a1 0x00000000000029a1 R E 0x1000 > | LOAD 0x0000000000004000 0x0000000000004000 0x00000000000040= 00 > | 0x0000000000000d38 0x0000000000000d38 R 0x1000 > | LOAD 0x0000000000005c78 0x0000000000006c78 0x0000000000006c= 78 > | 0x0000000000000390 0x00000000000003a0 RW 0x1000 > | DYNAMIC 0x0000000000005c90 0x0000000000006c90 0x0000000000006c= 90 > | 0x00000000000001f0 0x00000000000001f0 RW 0x8 > | NOTE 0x0000000000000338 0x0000000000000338 0x00000000000003= 38 > | 0x0000000000000050 0x0000000000000050 R 0x8 > | NOTE 0x0000000000000388 0x0000000000000388 0x00000000000003= 88 > | 0x0000000000000044 0x0000000000000044 R 0x4 > | GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x00000000000003= 38 > | 0x0000000000000050 0x0000000000000050 R 0x8 > | GNU_EH_FRAME 0x00000000000049c4 0x00000000000049c4 0x00000000000049= c4 > | 0x000000000000007c 0x000000000000007c R 0x4 > | GNU_STACK 0x0000000000000000 0x0000000000000000 0x00000000000000= 00 > | 0x0000000000000000 0x0000000000000000 RW 0x10 > | GNU_RELRO 0x0000000000005c78 0x0000000000006c78 0x0000000000006c= 78 > | 0x0000000000000388 0x0000000000000388 R 0x1 > | [=E2=80=A6] > > The virtual address for PT_GNU_RELRO is 0x388, which is definitely not > aligned to a 4K page. (0x388 + 0x6c78 =3D=3D 0x7000, so at least the end > address is aligned.) In practice, this seems to work because the RELRO > area seems to be at the start of the RW LOAD segment, so we can safely > flip the slack space at the start of the page to RO. It still looks > like a major wart to me, though. After relocation, we change the end of the RO segment (aligned down from the beginning of the RELRO area) to the end of the RELRO segment to RO. Since the end of the RELRO segment must be aligned to the page size, ALIGN_DOWN on the end of the RELRO segment doesn't lose any protection. > Any suggestions what should we do to fix this properly, mainly for > targets that have varying page size in practice? The end of the RELRO segment should be aligned to the maximum page size. > > Thanks, > Florian > --=20 H.J.