From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754003AbeAJT3R (ORCPT + 1 other); Wed, 10 Jan 2018 14:29:17 -0500 Received: from wtarreau.pck.nerim.net ([62.212.114.60]:39458 "EHLO 1wt.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751913AbeAJT3P (ORCPT ); Wed, 10 Jan 2018 14:29:15 -0500 From: Willy Tarreau To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: Willy Tarreau , Andy Lutomirski , Borislav Petkov , Brian Gerst , Dave Hansen , Ingo Molnar , Linus Torvalds , Peter Zijlstra , Thomas Gleixner , Josh Poimboeuf , "H. Peter Anvin" , Kees Cook Subject: [RFC PATCH v3 4/8] x86/arch_prctl: add ARCH_DISABLE_PTI_{NOW,NEXT} to enable/disable PTI Date: Wed, 10 Jan 2018 20:28:16 +0100 Message-Id: <1515612500-14505-5-git-send-email-w@1wt.eu> X-Mailer: git-send-email 2.8.0.rc2.1.gbe9624a In-Reply-To: <1515612500-14505-1-git-send-email-w@1wt.eu> References: <1515612500-14505-1-git-send-email-w@1wt.eu> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: These two prctls adjust the current task flags allowing to disable page table isolation respectively for the current process or for the one resulting from the next execve(). Both settings depend on CONFIG_PER_PROCESS_PTI. It is not possible to set the flags if the pti_adjust sysctl is lower than 1, nor if the task isn't capable of CAP_SYS_RAWIO, though it is still possible to disable them. Setting the flags is not allowed anymore once the task has created new threads, but it's still possible to disable them. Signed-off-by: Willy Tarreau Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Dave Hansen Cc: Ingo Molnar Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: Josh Poimboeuf Cc: "H. Peter Anvin" Cc: Kees Cook v3: - depend on CONFIG_PER_PROCESS_PTI - switch back to task flags - use one task flag for the immediate task (config-based setting) and one task flag for the task resulting from the next execve (wrapper-based setting) - check the pti_adjust sysctl v2: - use {set,clear}_thread_flag() as recommended by Peter - use task->mm->context.pti_disable instead of task flag - check for mm_users == 1 - check for CAP_SYS_RAWIO only when setting, not clearing - make the code depend on CONFIG_PAGE_TABLE_ISOLATION --- arch/x86/include/uapi/asm/prctl.h | 3 +++ arch/x86/kernel/process_64.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h index 5a6aac9..1564f98 100644 --- a/arch/x86/include/uapi/asm/prctl.h +++ b/arch/x86/include/uapi/asm/prctl.h @@ -10,6 +10,9 @@ #define ARCH_GET_CPUID 0x1011 #define ARCH_SET_CPUID 0x1012 +#define ARCH_DISABLE_PTI_NOW 0x1021 +#define ARCH_DISABLE_PTI_NEXT 0x1022 + #define ARCH_MAP_VDSO_X32 0x2001 #define ARCH_MAP_VDSO_32 0x2002 #define ARCH_MAP_VDSO_64 0x2003 diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index c754662..b4de8aa 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -654,7 +654,37 @@ long do_arch_prctl_64(struct task_struct *task, int option, unsigned long arg2) ret = put_user(base, (unsigned long __user *)arg2); break; } +#ifdef CONFIG_PER_PROCESS_PTI + case ARCH_DISABLE_PTI_NOW: + if (!task->mm || atomic_read(&task->mm->mm_users) > 1) + return -EPERM; + + if (arg2 && (!capable(CAP_SYS_RAWIO) || pti_adjust < 1)) + return -EPERM; + + if (doit) { + if (arg2) + set_thread_flag(TIF_DISABLE_PTI_NOW); + else + clear_thread_flag(TIF_DISABLE_PTI_NOW); + } + break; + case ARCH_DISABLE_PTI_NEXT: + if (!task->mm || atomic_read(&task->mm->mm_users) > 1) + return -EPERM; + + if (arg2 && (!capable(CAP_SYS_RAWIO) || pti_adjust < 1)) + return -EPERM; + + if (doit) { + if (arg2) + set_thread_flag(TIF_DISABLE_PTI_NEXT); + else + clear_thread_flag(TIF_DISABLE_PTI_NEXT); + } + break; +#endif #ifdef CONFIG_CHECKPOINT_RESTORE # ifdef CONFIG_X86_X32_ABI case ARCH_MAP_VDSO_X32: -- 1.7.12.1