From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 502 invoked by alias); 21 Mar 2018 21:48:47 -0000 Mailing-List: contact gnu-gabi-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Post: List-Help: List-Subscribe: Sender: gnu-gabi-owner@sourceware.org Received: (qmail 117846 invoked by uid 89); 21 Mar 2018 21:48:33 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Checked: by ClamAV 0.99.4 on sourceware.org X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE,TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 spammy=respective, Carlos, kosher, elide X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE,TIME_LIMIT_EXCEEDED autolearn=unavailable version=3.3.2 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on sourceware.org X-Spam-Level: X-HELO: mail-qt0-f180.google.com Received: from mail-qt0-f180.google.com (HELO mail-qt0-f180.google.com) (209.85.216.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 21 Mar 2018 21:48:18 +0000 Received: by mail-qt0-f180.google.com with SMTP id s2so6913269qti.2 for ; Wed, 21 Mar 2018 14:48:06 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:subject:to:cc:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-language :content-transfer-encoding; bh=+6VlKragLh82OMT7GS888/ukRENHoJAsYRnBz5g2HtE=; b=dwrdtg1JOjX+c9q3qYaBCR6bEhRp3njhqRuZ9FC8hi740eYnO6SPBNEL6g3/D2QPMO QzpiE8jm90PNb1ouGDTtLgbj+961RYbIqen8i4ZcbJ/ozt56ab/7211W5yRausN8zwZ0 tfr3Zg/nvml4jJcwh7SVkPtP86l3JCaF2A0VVuNwV+4vsOrilKREIfF4wurFCbvVMr8J VG+giAPhPoPgp6GSc5NwuzdwTBQVCUBKXyYiANzZNbzlwb6jk5iPS0O0MnznE5BDCpXu CQk6F96k6c5dFQjTZfLM+lJ328Y8Zy/Q5g9ChooKyXNAUbatfSPNcLVuijYCRetauvem /mHw== X-Gm-Message-State: AElRT7G9SY4Nr8mgjY4hvUTNKJLfqEZ6KZ5aUXQBpXL+2lEQ4wwVJm5m K3cn2Lt8DggrjljHKHd6XAd6eaP55FI= X-Google-Smtp-Source: AG47ELu33wKCYk/agEGKnIc3U+GlKITTU5rNcYRCV7SBWH/b0oAOHJoRSNrTXR3oAdzkPctrZdrfFQ== X-Received: by 10.200.24.177 with SMTP id s46mr31608021qtj.239.1521668884252; Wed, 21 Mar 2018 14:48:04 -0700 (PDT) Received: from [10.150.73.95] (198.sub-174-207-13.myvzw.com. [174.207.13.198]) by smtp.gmail.com with ESMTPSA id y58sm444713qta.42.2018.03.21.14.48.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 21 Mar 2018 14:48:03 -0700 (PDT) Subject: Re: RFC: Audit external function called indirectly via GOT To: Cary Coutant , generic-abi@googlegroups.com Cc: gnu-gabi@sourceware.org References: <20180317133115.GA4681@gmail.com> From: Carlos O'Donell Message-ID: Date: Mon, 01 Jan 2018 00:00:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.6.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2018-q1/txt/msg00006.txt.bz2 On 03/21/2018 11:16 AM, Cary Coutant wrote: >> Auditing of external function calls and their return values relies on >> lazy binding with PLT. When external functions are called indirectly >> via GOT without using PLT, auditing stops working. > > Could you give a little background here? Why does it stop working? > What does auditing rely on? I didn't find anything about this in the > psABI document. To be specific we are talking about the Solaris LD_AUDIT support that is implemented in the GNU dynamic loader ld.so. This has been a very useful thing for developers to have, particularly those working on schemes that alter lookup paths or binding rules. Also those that use these hooks to do other useful auditing. There were a lot of Solaris LD_AUDIT users, and now there are a lot of users that use this same feature in the GNU tools. The problem comes when you build with -fno-plt, or if you elide a PLT slot for any other reason, there is no longer a place for the LD_AUDIT infrastructure to hook into. In the case of x86 the -fno-plt generated code is a direct call through the GOT. The GOT is RO after relocation (relro), and so most tooling expects that it cannot be changed. Therefore it's not entirely kosher to reuse the GOT for this purpose, though you could do that, in fact on x86 the GLOB_DAT reloc and GOT entry look an awful lot like a function descriptor and a call through that function descriptor (for arches that have non-code PLTs). By keeping the generation of the PLT slot, but not using it, you can go back and re-use that PLT entry for auditing. If you are RELRO then you are going to pay a performance cost for turning on auditing, you will be forced to go through the PLT call sequence every time, enter the loader, find your already computed resolution in the loader's cache, and continue. If you are non-RELRO you can finalize the binding in the PLT. Again, all of this is to support LD_AUDIT, which traditionally used PLT entries and I'd like to keep this developer tooling working even in the presence of optimized binaries. > Here is a proposal to support auditing of external function called >> indirectly via GOT: >> >> 1. Add optional dynamic tags: >> >> #define DT_GNU_PLT 0x6ffffef4 /* Address of PLT section */ >> #define DT_GNU_PLTSZ 0x6ffffdf1 /* Size of PLT section */ >> #define DT_GNU_PLTENT 0x6ffffdf2 /* Size of one PLT entry */ >> #define DT_GNU_PLT0SZ 0x6ffffdf3 /* Size of the first PLT entry */ >> #define DT_GNU_PLTGOTSZ 0x6ffffdf4 /* Size of PLTGOT section */ >> >> and update DT_FLAGS_1 with: >> >> #define DF_1_JMPRELIGN 0x10000000 /* DT_JMPREL can be ignored */ >> 2. Linker creates PLT entries for auditing external function calls via >> GOT and sets DT_GNU_PLT, DT_GNU_PLTSZ, DT_GNU_PLTENT, DT_GNU_PLT0SZ and >> DT_GNU_PLTGOTSZ. If PLT isn't required for lazy binding, set the >> DF_1_JMPRELIGN bit in DT_FLAGS_1. >> 3. When auditing is enabled at run-time, dynamic linker resolves GLOB_DAT >> relocation to its corresponding PLT entry by finding JUMP_SLOT relocation >> against the same function and use its PLT slot as the function address. >> On x86, the first PLT entry and the 3 GOT slots are reserved. GOT slot >> is (JUMP_SLOT relocation offset - DT_PLTGOT) / size of GOT entry. PLT >> offset is (GOT slot - 3) * DT_GNU_PLTENT + DT_GNU_PLT0SZ. PLT address >> is DT_GNU_PLT + PLT offset. DT_GNU_PLT, DT_GNU_PLTSZ, DT_PLTGOT and >> DT_GNU_PLTGOTSZ can be used to check if GOT and PLT offsets are within >> range. >> 4. If DF_1_JMPRELIGN is set, dynamic linker can ignore DT_JMPREL when >> lazy binding is disabled. >> >> Any comments? > > Maybe a little more background would help me understand this better, > but I don't see why the GOT slots aren't being (or couldn't be) > statically relocated to point to the PLT slots. If the linker does > that, all the dynamic loader has to do is ignore the JMPREL > relocations at startup, and let lazy binding happen. I don't see why > it would need to go through this complicated matching process. What does "statically relocated" mean? It appears you are implying the GOT slots for these function calls could be statically relocated to their respective PLT entries. This is possible, but you have another problem. You have a list of GLOB_DAT relocs to process, some of which would overwrite the statically relocated entries, how do you figure out which these are and avoid processing them when LD_AUDIT is enabled? > (One trivial comment on your choice of naming: I can't see "JMPRELIGN" > without reading it as a misspelled "jump re-align"! Maybe "IGN_JMPREL" > would be better for human readers.) Agreed. Cheers, Carlos.