From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.1 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC7CFC433E0 for ; Thu, 30 Jul 2020 20:54:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A03352084D for ; Thu, 30 Jul 2020 20:54:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1596142460; bh=kjsUMa7W/2716/E66O9BRcoDTvK1hMoraL3jFZhSbhQ=; h=References:In-Reply-To:From:Date:Subject:To:Cc:List-ID:From; b=PaSbdguIUV98+3S6gKgfeTm0vE97/ujcBEcxwJSJhGQGn4M7mElsRXvCeeictwNYD sUtXMZIZoYT8G1NhZ1PI6GvsNtqx7q22BTj8zODqQFMq2gogv/vmT5SDzG2fAHE51H PTq71QLMo60MRSt+JNCCljaRN/UcBFOZzQvRhdKM= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730279AbgG3UyU (ORCPT ); Thu, 30 Jul 2020 16:54:20 -0400 Received: from mail.kernel.org ([198.145.29.99]:42594 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728778AbgG3UyT (ORCPT ); Thu, 30 Jul 2020 16:54:19 -0400 Received: from mail-wr1-f53.google.com (mail-wr1-f53.google.com [209.85.221.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 38E042084D for ; Thu, 30 Jul 2020 20:54:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1596142458; bh=kjsUMa7W/2716/E66O9BRcoDTvK1hMoraL3jFZhSbhQ=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=o9dMLI7V7xLay/4FEvc5ZBCLpWIPaCqr6MXAhd3v41abR8skQqLAzbrq08+887reU wRySApjBQKeQ5VZq/RrsOM5e6cbno9eOfSVO8kC1+jgM4mvZwzHMUrYvd4E6R5+giP WaOsgZjN1HyUHoKP9cFT3MNatWBEDqakktTzyWTE= Received: by mail-wr1-f53.google.com with SMTP id f18so26130987wrs.0 for ; Thu, 30 Jul 2020 13:54:18 -0700 (PDT) X-Gm-Message-State: AOAM532tv60UEZQfSZlC2b2Quwf9hwdEGYpUGt7haobTV0Dkt1V9GaTE gHQQLl5wOUF6J3im4jxq+qEn+7Z5Q7N2aqBezpp7vA== X-Google-Smtp-Source: ABdhPJzKLFb8fOLe7ajuISL9Za2Aj4/QcGOi3NXA9PDpcRSYfLFS4b/xrq0MWMJYlHADmhXcVVN9ubUqp0AHIqmO1Bk= X-Received: by 2002:adf:fa85:: with SMTP id h5mr509001wrr.18.1596142456738; Thu, 30 Jul 2020 13:54:16 -0700 (PDT) MIME-Version: 1.0 References: <20200728131050.24443-1-madvenka@linux.microsoft.com> <6540b4b7-3f70-adbf-c922-43886599713a@linux.microsoft.com> In-Reply-To: <6540b4b7-3f70-adbf-c922-43886599713a@linux.microsoft.com> From: Andy Lutomirski Date: Thu, 30 Jul 2020 13:54:03 -0700 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v1 0/4] [RFC] Implement Trampoline File Descriptor To: "Madhavan T. Venkataraman" Cc: Andy Lutomirski , Kernel Hardening , Linux API , linux-arm-kernel , Linux FS Devel , linux-integrity , LKML , LSM List , Oleg Nesterov , X86 ML Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Sender: linux-integrity-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-integrity@vger.kernel.org On Thu, Jul 30, 2020 at 7:24 AM Madhavan T. Venkataraman wrote: > > Sorry for the delay. I just wanted to think about this a little. > In this email, I will respond to your first suggestion. I will > respond to the rest in separate emails if that is alright with > you. > > On 7/28/20 12:31 PM, Andy Lutomirski wrote: > > On Jul 28, 2020, at 6:11 AM, madvenka@linux.microsoft.com wrote: > > =EF=BB=BFFrom: "Madhavan T. Venkataraman" > > The kernel creates the trampoline mapping without any permissions. When > the trampoline is executed by user code, a page fault happens and the > kernel gets control. The kernel recognizes that this is a trampoline > invocation. It sets up the user registers based on the specified > register context, and/or pushes values on the user stack based on the > specified stack context, and sets the user PC to the requested target > PC. When the kernel returns, execution continues at the target PC. > So, the kernel does the work of the trampoline on behalf of the > application. > > This is quite clever, but now I=E2=80=99m wondering just how much kernel = help > is really needed. In your series, the trampoline is an non-executable > page. I can think of at least two alternative approaches, and I'd > like to know the pros and cons. > > 1. Entirely userspace: a return trampoline would be something like: > > 1: > pushq %rax > pushq %rbc > pushq %rcx > ... > pushq %r15 > movq %rsp, %rdi # pointer to saved regs > leaq 1b(%rip), %rsi # pointer to the trampoline itself > callq trampoline_handler # see below > > You would fill a page with a bunch of these, possibly compacted to get > more per page, and then you would remap as many copies as needed. The > 'callq trampoline_handler' part would need to be a bit clever to make > it continue to work despite this remapping. This will be *much* > faster than trampfd. How much of your use case would it cover? For > the inverse, it's not too hard to write a bit of asm to set all > registers and jump somewhere. > > Let me state what I have understood about this suggestion. Correct me if > I get anything wrong. If you don't mind, I will also take the liberty > of generalizing and paraphrasing your suggestion. > > The goal is to create two page mappings that are adjacent to each other: > > - a code page that contains template code for a trampoline. Since the > template code would tend to be small in size, pack as many of them > as possible within a page to conserve memory. In other words, create > an array of the template code fragments. Each element in the array > would be used for one trampoline instance. > > - a data page that contains an array of data elements. Corresponding > to each code element in the code page, there would be a data element > in the data page that would contain data that is specific to a > trampoline instance. > > - Code will access data using PC-relative addressing. > > The management of the code pages and allocation for each trampoline > instance would all be done in user space. > > Is this the general idea? Yes. > > Creating a code page > -------------------- > > We can do this in one of the following ways: > > - Allocate a writable page at run time, write the template code into > the page and have execute permissions on the page. > > - Allocate a writable page at run time, write the template code into > the page and remap the page with just execute permissions. > > - Allocate a writable page at run time, write the template code into > the page, write the page into a temporary file and map the file with > execute permissions. > > - Include the template code in a code page at build time itself and > just remap the code page each time you need a code page. This latter part shouldn't need any special permissions as far as I know. > > Pros and Cons > ------------- > > As long as the OS provides the functionality to do this and the security > subsystem in the OS allows the actions, this is totally feasible. If not, > we need something like trampfd. > > As Floren mentioned, libffi does implement something like this for MACH. > > In fact, in my libffi changes, I use trampfd only after all the other met= hods > have failed because of security settings. > > But the above approach only solves the problem for this simple type of > trampoline. It does not provide a framework for addressing more complex t= ypes > or even other forms of dynamic code. > > Also, each application would need to implement this solution for itself > as opposed to relying on one implementation provided by the kernel. I would argue this is a benefit. If the whole implementation is in userspace, there is no ABI compatibility issue. The user program contains the trampoline code and the code that uses it. > > Trampfd-based solution > ---------------------- > > I outlined an enhancement to trampfd in a response to David Laight. In th= is > enhancement, the kernel is the one that would set up the code page. > > The kernel would call an arch-specific support function to generate the > code required to load registers, push values on the stack and jump to a P= C > for a trampoline instance based on its current context. The trampoline > instance data could be baked into the code. > > My initial idea was to only have one trampoline instance per page. But I > think I can implement multiple instances per page. I just have to manage > the trampfd file private data and VMA private data accordingly to map an > element in a code page to its trampoline object. > > The two approaches are similar except for the detail about who sets up > and manages the trampoline pages. In both approaches, the performance pro= blem > is addressed. But trampfd can be used even when security settings are > restrictive. > > Is my solution acceptable? Perhaps. In general, before adding a new ABI to the kernel, it's nice to understand how it's better than doing the same thing in userspace. Saying that it's easier for user code to work with if it's in the kernel isn't necessarily an adequate justification. Why would remapping two pages of actual application text ever fail?