Received: by 2002:a05:6a10:16a7:0:0:0:0 with SMTP id gp39csp1147806pxb; Fri, 6 Nov 2020 02:08:23 -0800 (PST) X-Google-Smtp-Source: ABdhPJzew74PbKYVtbMfYw8kGBwb3s0YB+NdDvXHDqLA0Toa1jmPSkzl+HT+KBz5WS5i6vwq8YT0 X-Received: by 2002:aa7:d2d2:: with SMTP id k18mr1161344edr.290.1604657303324; Fri, 06 Nov 2020 02:08:23 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1604657303; cv=none; d=google.com; s=arc-20160816; b=rKUSEXE8/7G1t/TrsMpdRS7TJgvHISBubDJ/qL12vV1gLaDIDIQlYG+COfJtpQKfI3 oZhOSHoNR3MZCDgD4skJLHYuUfmdoSdyId8F48e/878KCNkvCcoqRqhMZQRuZGARP4/g HQT7A1Bphks5gjvpJvhl4mBvtGkfXK0JQFUWNyBKFJ7p9qwBim7VSU65vagP02LfQSSC wTXcnMB1Pq7a1jvgNvqTvEv/sznZ/He8lkpj62STjQ/M0XczsJNGZBDtm+fARbOkwCwF fk5TYUDjNFMnh/dnGZDahMxmTH4GF72eKU3rqXn47+54qAXYXvt+vfWX/CTHzwEgmBWX ponw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:user-agent:in-reply-to:content-disposition :mime-version:references:message-id:subject:cc:to:from:date; bh=OHWDezQsEnQhgHT8fLQokI602trIOPz8StZZtZVum0k=; b=Yehw99+zCEsPFgBfm/LNJVThvQfoIZmg3XsZuS+PB5L7dTYwTsz4fvmqblvnnfk8uI o7Qfl2qvw9vKWiXZAanFb8pkjRlxtiJOzVtmJx7VK+zb0yjU1hearjo1TU57UlDy/s3I yRx14BgT5yb0sjhOVeerH1IrZ1v0LG+FJzoylmvnTLT0qEyAdK9TUEyO7sbXFDnsyCrv xWXIdiPkT4azKfIDTFUFoxcb9syfWQEs+2aiMlAIVdVlFVg20h4FxYDmWCZD4XImp/Iq 5sMj1eaMvwLK7BKXaCTMQBTJh9i72hBrr/8GuDJy757/aRKRS6d82Eth10o17aAg+2/M GnwA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id bq23si496403ejb.529.2020.11.06.02.08.00; Fri, 06 Nov 2020 02:08:23 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726422AbgKFKEO (ORCPT + 99 others); Fri, 6 Nov 2020 05:04:14 -0500 Received: from outbound-smtp02.blacknight.com ([81.17.249.8]:40321 "EHLO outbound-smtp02.blacknight.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726074AbgKFKEN (ORCPT ); Fri, 6 Nov 2020 05:04:13 -0500 Received: from mail.blacknight.com (pemlinmail04.blacknight.ie [81.17.254.17]) by outbound-smtp02.blacknight.com (Postfix) with ESMTPS id 805A4BAD56 for ; Fri, 6 Nov 2020 10:04:11 +0000 (GMT) Received: (qmail 14879 invoked from network); 6 Nov 2020 10:04:11 -0000 Received: from unknown (HELO techsingularity.net) (mgorman@techsingularity.net@[84.203.22.4]) by 81.17.254.9 with ESMTPSA (AES256-SHA encrypted, authenticated); 6 Nov 2020 10:04:11 -0000 Date: Fri, 6 Nov 2020 10:04:09 +0000 From: Mel Gorman To: Jarkko Sakkinen Cc: x86@kernel.org, linux-sgx@vger.kernel.org, linux-kernel@vger.kernel.org, Sean Christopherson , linux-mm@kvack.org, Andrew Morton , Matthew Wilcox , Jethro Beekman , Darren Kenny , andriy.shevchenko@linux.intel.com, asapek@google.com, bp@alien8.de, cedric.xing@intel.com, chenalexchen@google.com, conradparker@google.com, cyhanish@google.com, dave.hansen@intel.com, haitao.huang@intel.com, kai.huang@intel.com, kai.svahn@intel.com, kmoy@google.com, ludloff@google.com, luto@kernel.org, nhorman@redhat.com, npmccallum@redhat.com, puiterwijk@redhat.com, rientjes@google.com, tglx@linutronix.de, yaozhangx@google.com, mikko.ylinen@intel.com, Michal Hocko , Vlastimil Babka Subject: Re: [PATCH v40 10/24] mm: Add 'mprotect' hook to struct vm_operations_struct Message-ID: <20201106100409.GD3371@techsingularity.net> References: <20201104145430.300542-1-jarkko.sakkinen@linux.intel.com> <20201104145430.300542-11-jarkko.sakkinen@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Disposition: inline In-Reply-To: <20201104145430.300542-11-jarkko.sakkinen@linux.intel.com> User-Agent: Mutt/1.10.1 (2018-07-13) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Wed, Nov 04, 2020 at 04:54:16PM +0200, Jarkko Sakkinen wrote: > From: Sean Christopherson > > Background > ========== > > 1. SGX enclave pages are populated with data by copying from normal memory > via ioctl() (SGX_IOC_ENCLAVE_ADD_PAGES), which will be added later in > this series. > 2. It is desirable to be able to restrict those normal memory data sources. > For instance, to ensure that the source data is executable before > copying data to an executable enclave page. > 3. Enclave page permissions are dynamic (just like normal permissions) and > can be adjusted at runtime with mprotect(). > > This creates a problem because the original data source may have long since > vanished at the time when enclave page permissions are established (mmap() > or mprotect()). > > The solution (elsewhere in this series) is to force enclaves creators to > declare their paging permission *intent* up front to the ioctl(). This > intent can me immediately compared to the source data???s mapping and > rejected if necessary. > > The ???intent??? is also stashed off for later comparison with enclave > PTEs. This ensures that any future mmap()/mprotect() operations > performed by the enclave creator or done on behalf of the enclave > can be compared with the earlier declared permissions. > > Problem > ======= > > There is an existing mmap() hook which allows SGX to perform this > permission comparison at mmap() time. However, there is no corresponding > ->mprotect() hook. > > Solution > ======== > > Add a vm_ops->mprotect() hook so that mprotect() operations which are > inconsistent with any page's stashed intent can be rejected by the driver. > I have not read the series so this is superficial only. That said... > Cc: linux-mm@kvack.org > Cc: Andrew Morton > Cc: Matthew Wilcox > Acked-by: Jethro Beekman > Reviewed-by: Darren Kenny > Signed-off-by: Sean Christopherson > Co-developed-by: Jarkko Sakkinen > Signed-off-by: Jarkko Sakkinen > --- > include/linux/mm.h | 3 +++ > mm/mprotect.c | 5 ++++- > 2 files changed, 7 insertions(+), 1 deletion(-) > > diff --git a/include/linux/mm.h b/include/linux/mm.h > index ef360fe70aaf..eb38eabc5039 100644 > --- a/include/linux/mm.h > +++ b/include/linux/mm.h > @@ -559,6 +559,9 @@ struct vm_operations_struct { > void (*close)(struct vm_area_struct * area); > int (*split)(struct vm_area_struct * area, unsigned long addr); > int (*mremap)(struct vm_area_struct * area); > + int (*mprotect)(struct vm_area_struct *vma, > + struct vm_area_struct **pprev, unsigned long start, > + unsigned long end, unsigned long newflags); The first user of this uses the following information ret = sgx_encl_may_map(vma->vm_private_data, start, end, newflags); It only needs start, end and newflags. The pprev is passed in so the hook can call mprotect_fixup() which is redundant as the caller knows it should do that. I don't think an arbitrary driver should be responsible for poking too much into the mm internals to do the fixup because we do not know what other users of this hook might require in the future. Hence, I would suggest that the hook receive the minimum possible information to do the permissions check for the first in-tree user. If it returns without failure then mm/mprotect.c would always do the fixup. > vm_fault_t (*fault)(struct vm_fault *vmf); > vm_fault_t (*huge_fault)(struct vm_fault *vmf, > enum page_entry_size pe_size); > diff --git a/mm/mprotect.c b/mm/mprotect.c > index 56c02beb6041..1fd4fa71ce16 100644 > --- a/mm/mprotect.c > +++ b/mm/mprotect.c > @@ -616,7 +616,10 @@ static int do_mprotect_pkey(unsigned long start, size_t len, > tmp = vma->vm_end; > if (tmp > end) > tmp = end; > - error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); > + if (vma->vm_ops && vma->vm_ops->mprotect) > + error = vma->vm_ops->mprotect(vma, &prev, nstart, tmp, newflags); > + else > + error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); That would then become if (vma->vm_ops && vma->vm_ops->mprotect) error = vma->vm_ops->mprotect(vma, &prev, nstart, tmp, newflags); if (!error) error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); and mprotect_fixup would be removed from the driver. While vm_operations_struct has borderline zero documentation, a hook for one in-kernel user should have a comment explaining what the semantics of the hook is -- what is it responsible for (permission check), what can it change (nothing), etc. Maybe something like /* * Called by mprotect in the event driver-specific permission * checks need to be made before the mprotect is finalised. * No modifications should be done to the VMA, returns 0 * if the mprotect is permitted. */ int (*mprotect)(struct vm_area_struct *vma, unsigned long start, unsigned long end, unsigned long newflags); If a future driver *does* need to poke deeper into the VM for mprotect then at least they'll have to explain why that's a good idea. -- Mel Gorman SUSE Labs