Received: by 10.192.165.148 with SMTP id m20csp2339243imm; Sun, 6 May 2018 12:24:11 -0700 (PDT) X-Google-Smtp-Source: AB8JxZq0rDntYChU0tti4jCc7isv8cgFe+bXxVSVGjsVHubnWu0t/LgmyNw+cBFLCj2keIWBLI/f X-Received: by 2002:a63:5f82:: with SMTP id t124-v6mr28363447pgb.150.1525634651696; Sun, 06 May 2018 12:24:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1525634651; cv=none; d=google.com; s=arc-20160816; b=sLQnUd0B8EsO8Fh7NoPzpmu/ZZiMYf27wmVpApSkBLzHiNWTGjpX9II3W0mOuwt1O2 gVpDTp3WlOkCd2BO8xZy/DO6oal9PpA4M6yOmGiPS0CQOpIjVmyMK54T9Kmmf5EB4/je JhvJ6aFnitV7r15DSVStW6jzX020yCXSrVieoJPMTJYZF++KoloFD2nLPXyMM4CAWj/F W84ssAX8gEM4zfA4rv8FWl0s8DAQyF4Q3QfjeA9S7qZRDToaJu2NL0vbnfG0qsGA3y12 tDgOJDcR7Ebwwuq0nCP19XPZ4zrh/a9vBVYoOat5ufUvBG0o4OXEY/xNUryuz9ORKhgR Bu+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dkim-signature:arc-authentication-results; bh=guJayCDeXAl9qLgR5H/J68DTSB8hKhxnqGiptEouD6Q=; b=Cz1SHHX+C+GhT35fDSfuF++PDLwQ+gpeJZwL2zMd+x7tajCUN+YVqUPPwFGsytHPX0 xMjy8vBSB3cs9jOwL9rVjfhxm762t+IZvbcTYHMU3aQG0PE4MXptyKC9bqUBE+ON56ff AW/k2OlGbt6XtWfMI5ycmrERjpi2XfWaVN1FXMGb9amHtWuAEvRURzpnWB4Snfu0b5/a 0gsxGj9X01Xtl0vQBIeWtgKV+uXoM5Ng3BGQPce3I+Vqw43O/I/+BNEFvdHXC/qZMPql zmhiAKq2HBL/j3aONk1WwfBsY8z1+tYEj3MqJj67zuHsM+8qejeDNHhqwsb3N2G2y1cO hl3g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=DaA9mlk2; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d23-v6si17105626pgn.582.2018.05.06.12.23.57; Sun, 06 May 2018 12:24:11 -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; dkim=pass header.i=@kernel.org header.s=default header.b=DaA9mlk2; 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=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751906AbeEFTUT (ORCPT + 99 others); Sun, 6 May 2018 15:20:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:38354 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751807AbeEFTUO (ORCPT ); Sun, 6 May 2018 15:20:14 -0400 Received: from lerouge.home (LFbn-NCY-1-193-82.w83-194.abo.wanadoo.fr [83.194.41.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 75DA4217B4; Sun, 6 May 2018 19:20:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1525634413; bh=8RKfz61hEh4fyPauG8UhUCmIlLPzW2dcSsSQxj2+Ah0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=DaA9mlk2sVZVhx92L/1HotVLlGSD+MTYOw2fB/iS0LMAnDfd8lC5u37Z6nWTf69+t d21aTCoWVb1gX/eg7MNhrWBC8vN4iYxOB4QBNuT5PPpb7xJccgGzUgChREaHlXjYqy wIgEKZrd6Gd4VFydBzL3UJjtJspisExPZRYdAOLA= From: Frederic Weisbecker To: LKML Cc: Frederic Weisbecker , Jiri Olsa , Namhyung Kim , Peter Zijlstra , Linus Torvalds , Yoshinori Sato , Benjamin Herrenschmidt , Catalin Marinas , Chris Zankel , Paul Mackerras , Thomas Gleixner , Will Deacon , Michael Ellerman , Rich Felker , Ingo Molnar , Mark Rutland , Alexander Shishkin , Andy Lutomirski , Arnaldo Carvalho de Melo , Max Filippov Subject: [PATCH 1/9] x86/breakpoint: Split validation into "check" and "commit" Date: Sun, 6 May 2018 21:19:47 +0200 Message-Id: <1525634395-23380-2-git-send-email-frederic@kernel.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1525634395-23380-1-git-send-email-frederic@kernel.org> References: <1525634395-23380-1-git-send-email-frederic@kernel.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The breakpoint code mixes up attribute check and commit into a single code entity. Therefore the validation may return an error due to incorrect atributes while still leaving halfway modified architecture breakpoint struct. Prepare fox fixing this misdesign and separate both logics. Original-patch-by: Andy Lutomirski Signed-off-by: Frederic Weisbecker Cc: Linus Torvalds Cc: Andy Lutomirski Cc: Yoshinori Sato Cc: Rich Felker Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Will Deacon Cc: Mark Rutland Cc: Max Filippov Cc: Chris Zankel Cc: Catalin Marinas Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Cc: Michael Ellerman Cc: Peter Zijlstra Cc: Arnaldo Carvalho de Melo Cc: Alexander Shishkin Cc: Jiri Olsa Cc: Namhyung Kim --- arch/x86/kernel/hw_breakpoint.c | 137 +++++++++++++++++++++------------------- 1 file changed, 72 insertions(+), 65 deletions(-) diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c index 8771766..6960800 100644 --- a/arch/x86/kernel/hw_breakpoint.c +++ b/arch/x86/kernel/hw_breakpoint.c @@ -233,20 +233,15 @@ int arch_bp_generic_fields(int x86_len, int x86_type, return 0; } - -static int arch_build_bp_info(struct perf_event *bp) +static int hw_breakpoint_arch_check(struct perf_event *bp, + const struct perf_event_attr *attr) { - struct arch_hw_breakpoint *info = counter_arch_bp(bp); + unsigned int align; - info->address = bp->attr.bp_addr; - - /* Type */ - switch (bp->attr.bp_type) { + /* Check type */ + switch (attr->bp_type) { case HW_BREAKPOINT_W: - info->type = X86_BREAKPOINT_WRITE; - break; case HW_BREAKPOINT_W | HW_BREAKPOINT_R: - info->type = X86_BREAKPOINT_RW; break; case HW_BREAKPOINT_X: /* @@ -254,33 +249,84 @@ static int arch_build_bp_info(struct perf_event *bp) * acceptable for kprobes. On non-kprobes kernels, we don't * allow kernel breakpoints at all. */ - if (bp->attr.bp_addr >= TASK_SIZE_MAX) { + if (attr->bp_addr >= TASK_SIZE_MAX) { #ifdef CONFIG_KPROBES - if (within_kprobe_blacklist(bp->attr.bp_addr)) + if (within_kprobe_blacklist(attr->bp_addr)) return -EINVAL; #else return -EINVAL; #endif } + if (attr->bp_len == sizeof(long)) + return 0; + default: + return -EINVAL; + } + + /* Check len */ + switch (attr->bp_len) { + case HW_BREAKPOINT_LEN_1: + case HW_BREAKPOINT_LEN_2: + case HW_BREAKPOINT_LEN_4: + break; +#ifdef CONFIG_X86_64 + case HW_BREAKPOINT_LEN_8: + break; + default: + /* AMD range breakpoint */ + if (!is_power_of_2(attr->bp_len)) + return -EINVAL; + + if (!boot_cpu_has(X86_FEATURE_BPEXT)) + return -EOPNOTSUPP; +#endif + } + + align = attr->bp_len - 1; + + /* + * Check that the low-order bits of the address are appropriate + * for the alignment implied by len. + */ + if (attr->bp_addr & align) + return -EINVAL; + + return 0; +} + +static void hw_breakpoint_arch_commit(struct perf_event *bp) +{ + struct arch_hw_breakpoint *info = counter_arch_bp(bp); + struct perf_event_attr *attr = &bp->attr; + + info->address = attr->bp_addr; + + /* Set type */ + switch (attr->bp_type) { + case HW_BREAKPOINT_W: + info->type = X86_BREAKPOINT_WRITE; + break; + case HW_BREAKPOINT_W | HW_BREAKPOINT_R: + info->type = X86_BREAKPOINT_RW; + break; + case HW_BREAKPOINT_X: info->type = X86_BREAKPOINT_EXECUTE; /* * x86 inst breakpoints need to have a specific undefined len. * But we still need to check userspace is not trying to setup * an unsupported length, to get a range breakpoint for example. */ - if (bp->attr.bp_len == sizeof(long)) { - info->len = X86_BREAKPOINT_LEN_X; - return 0; - } + info->len = X86_BREAKPOINT_LEN_X; + return; default: - return -EINVAL; + WARN_ON_ONCE(1); } - /* Len */ + /* Set len */ info->mask = 0; - switch (bp->attr.bp_len) { + switch (attr->bp_len) { case HW_BREAKPOINT_LEN_1: info->len = X86_BREAKPOINT_LEN_1; break; @@ -296,15 +342,6 @@ static int arch_build_bp_info(struct perf_event *bp) break; #endif default: - /* AMD range breakpoint */ - if (!is_power_of_2(bp->attr.bp_len)) - return -EINVAL; - if (bp->attr.bp_addr & (bp->attr.bp_len - 1)) - return -EINVAL; - - if (!boot_cpu_has(X86_FEATURE_BPEXT)) - return -EOPNOTSUPP; - /* * It's impossible to use a range breakpoint to fake out * user vs kernel detection because bp_len - 1 can't @@ -312,54 +349,24 @@ static int arch_build_bp_info(struct perf_event *bp) * breakpoints, then we'll have to check for kprobe-blacklisted * addresses anywhere in the range. */ - info->mask = bp->attr.bp_len - 1; + info->mask = attr->bp_len - 1; info->len = X86_BREAKPOINT_LEN_1; } - - return 0; } + /* * Validate the arch-specific HW Breakpoint register settings */ int arch_validate_hwbkpt_settings(struct perf_event *bp) { - struct arch_hw_breakpoint *info = counter_arch_bp(bp); - unsigned int align; - int ret; + int err; + err = hw_breakpoint_arch_check(bp, &bp->attr); + if (err) + return err; - ret = arch_build_bp_info(bp); - if (ret) - return ret; - - switch (info->len) { - case X86_BREAKPOINT_LEN_1: - align = 0; - if (info->mask) - align = info->mask; - break; - case X86_BREAKPOINT_LEN_2: - align = 1; - break; - case X86_BREAKPOINT_LEN_4: - align = 3; - break; -#ifdef CONFIG_X86_64 - case X86_BREAKPOINT_LEN_8: - align = 7; - break; -#endif - default: - WARN_ON_ONCE(1); - } - - /* - * Check that the low-order bits of the address are appropriate - * for the alignment implied by len. - */ - if (info->address & align) - return -EINVAL; + hw_breakpoint_arch_commit(bp); return 0; } -- 2.7.4