Received: by 2002:ac0:98c7:0:0:0:0:0 with SMTP id g7-v6csp559830imd; Fri, 26 Oct 2018 12:59:50 -0700 (PDT) X-Google-Smtp-Source: AJdET5dRpd9/Jy9Qu64rnaSvEzAYcrN0/GGuVYtTGpGeVk2sdNm4v0zkARx7ZpIKfDuFjszX+Ppj X-Received: by 2002:a63:7154:: with SMTP id b20mr4767630pgn.342.1540583990395; Fri, 26 Oct 2018 12:59:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1540583990; cv=none; d=google.com; s=arc-20160816; b=iY9+FvtpVZ6sWBXQWBmv89UvvkQOcr3vu4U+FI6JWQZtE76r8McESltSElhR6UEVrK w2dzRij30nmUSp+at9gguSpUyv0bom013H7Q/vfIuLF/2RrP7nRGMSU30jkUk8cupTbY reKzm4DsHTSXadV1aV9nYKqo864zuHhYAcgN4mDIxpZoPACjkDZMwVJiTjeQGwi1xPQP 2t7BBc7OFwrvJKp5d4PgljVq3kVmwGlXs5HUP2iL9Zxz+1WQPD+XCXIicz1H33U8BLqa zJu9MsiRaIFaBEqAo6oevT1yFY9jystOFKVsdNvjZRzh06AYTQUdz7CkzlytpIkIV8uy 2Uqg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:from:cc:to:subject; bh=sEQojyGcef5Li/a93HrDga3oF4o3My53ZXqXgktORsM=; b=jy2dnN2QFxZxuzlaOmOeQG8Wbp0N6wAK4BJ54TWzqvIregdDha0FcaEqAHZcL0GYs0 uY6BpBPUGr/mXlBnWLhtJ6tnxd3KgDCpSOvZg5fuIJQzuhhqF8T4hChRHFIFSAhi+s5z 2b+2Jr7iAd/zCWust3l2Dyw3I+rzJ/3QiovHDejF2Enhq/xQG3LfT8ePWi00rDwdMb3f Hnt36nanNcxVFMavpuNqbNbzWdbr30rf4HvHqGQa3HE08mAU9gmt7GviilL6t7MGcaSj inQnRc5aWAhu9vJHUdUzpCuEwjI+RgP2tuVCCaBc00nZZJoRkDf2Jw/R1eX3L0u3M26T zB5A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id l13-v6si12030605pgb.534.2018.10.26.12.59.34; Fri, 26 Oct 2018 12:59:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727945AbeJ0Efk (ORCPT + 99 others); Sat, 27 Oct 2018 00:35:40 -0400 Received: from mga06.intel.com ([134.134.136.31]:18772 "EHLO mga06.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725965AbeJ0Efk (ORCPT ); Sat, 27 Oct 2018 00:35:40 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga104.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 Oct 2018 12:57:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.54,429,1534834800"; d="scan'208";a="102992382" Received: from viggo.jf.intel.com (HELO localhost.localdomain) ([10.54.77.144]) by orsmga001.jf.intel.com with ESMTP; 26 Oct 2018 12:57:19 -0700 Subject: [PATCH 1/2] x86/pkeys: copy pkey state at fork() To: linux-kernel@vger.kernel.org Cc: Dave Hansen , tglx@linutronix.de, mingo@redhat.com, bp@alien8.de, hpa@zytor.com, x86@kernel.org, peterz@infradead.org, mpe@ellerman.id.au, will.deacon@arm.com, luto@kernel.org, jroedel@suse.de From: Dave Hansen Date: Fri, 26 Oct 2018 12:51:46 -0700 Message-Id: <20181026195146.9C7C1136@viggo.jf.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Dave Hansen Our creation of new mm's is a bit convoluted. At fork(), the code does: 1. memcpy() the parent mm to initialize child 2. mm_init() to initalize some select stuff stuff 3. dup_mmap() to create true copies that memcpy() did not do right. For pkeys, we need to preserve two bits of state across a fork: 'execute_only_pkey' and 'pkey_allocation_map'. Those are preserved by the memcpy(), which I thought did the right thing. But, mm_init() calls init_new_context(), which I thought was *only* for execve()-time and overwrites 'execute_only_pkey' and 'pkey_allocation_map' with "new" values. The result is that, after a fork(), the child's pkey state ends up looking like it does after an execve(), which is totally wrong. pkeys that are already allocated can be allocated again, for instance. To fix this, add code called by dup_mmap() to copy the pkey state from parent to child explicitly. Also add a comment above init_new_context() to make it more clear to the next poor sod what this code is used for. Fixes: e8c24d3a23a ("x86/pkeys: Allocation/free syscalls") Signed-off-by: Dave Hansen Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: "H. Peter Anvin" Cc: x86@kernel.org Cc: Dave Hansen Cc: Peter Zijlstra Cc: Michael Ellerman Cc: Will Deacon Cc: Andy Lutomirski Cc: Joerg Roedel --- b/arch/x86/include/asm/mmu_context.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff -puN arch/x86/include/asm/mmu_context.h~x86-pkeys-no-init-at-fork arch/x86/include/asm/mmu_context.h --- a/arch/x86/include/asm/mmu_context.h~x86-pkeys-no-init-at-fork 2018-10-26 09:24:09.444102622 -0700 +++ b/arch/x86/include/asm/mmu_context.h 2018-10-26 09:24:09.451102622 -0700 @@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk); +/* + * Init a new mm. Used on mm copies, like at fork() + * and on mm's that are brand-new, like at execve(). + */ static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) { @@ -228,8 +232,22 @@ do { \ } while (0) #endif +static inline void arch_dup_pkeys(struct mm_struct *oldmm, + struct mm_struct *mm) +{ +#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS + if (!cpu_feature_enabled(X86_FEATURE_OSPKE)) + return; + + /* Duplicate the oldmm pkey state in mm: */ + mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map; + mm->context.execute_only_pkey = oldmm->context.execute_only_pkey; +#endif +} + static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm) { + arch_dup_pkeys(oldmm, mm); paravirt_arch_dup_mmap(oldmm, mm); return ldt_dup_context(oldmm, mm); } _