lkml.org 
[lkml]   [2018]   [Sep]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.18 100/136] perf/hw_breakpoint: Split attribute parse and commit
    Date
    From: Frederic Weisbecker <frederic@kernel.org>

    [ Upstream commit 9a4903dde2c8633c5fcf887b98c4e047a6154a54 ]

    arch_validate_hwbkpt_settings() 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 data.

    This is harmless when we deal with a new breakpoint but it becomes a
    problem when we modify an existing breakpoint.

    Split attribute parse and commit to fix that. The architecture is
    passed a "struct arch_hw_breakpoint" to fill on top of the new attr
    and the core takes care about copying the backend data once it's fully
    validated. The architectures then need to implement the new API.

    Original-patch-by: Andy Lutomirski <luto@kernel.org>
    Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Frederic Weisbecker <frederic@kernel.org>
    Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
    Cc: Andy Lutomirski <luto@kernel.org>
    Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
    Cc: Catalin Marinas <catalin.marinas@arm.com>
    Cc: Chris Zankel <chris@zankel.net>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Joel Fernandes <joel.opensrc@gmail.com>
    Cc: Mark Rutland <mark.rutland@arm.com>
    Cc: Max Filippov <jcmvbkbc@gmail.com>
    Cc: Michael Ellerman <mpe@ellerman.id.au>
    Cc: Namhyung Kim <namhyung@kernel.org>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Rich Felker <dalias@libc.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Will Deacon <will.deacon@arm.com>
    Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
    Link: http://lkml.kernel.org/r/1529981939-8231-2-git-send-email-frederic@kernel.org
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
    ---
    kernel/events/hw_breakpoint.c | 57 +++++++++++++++++++++++++----------
    1 file changed, 41 insertions(+), 16 deletions(-)

    diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
    index 6e28d2866be5..314e2a9040c7 100644
    --- a/kernel/events/hw_breakpoint.c
    +++ b/kernel/events/hw_breakpoint.c
    @@ -400,16 +400,35 @@ int dbg_release_bp_slot(struct perf_event *bp)
    return 0;
    }

    -static int validate_hw_breakpoint(struct perf_event *bp)
    +#ifndef hw_breakpoint_arch_parse
    +int hw_breakpoint_arch_parse(struct perf_event *bp,
    + const struct perf_event_attr *attr,
    + struct arch_hw_breakpoint *hw)
    {
    - int ret;
    + int err;

    - ret = arch_validate_hwbkpt_settings(bp);
    - if (ret)
    - return ret;
    + err = arch_validate_hwbkpt_settings(bp);
    + if (err)
    + return err;
    +
    + *hw = bp->hw.info;
    +
    + return 0;
    +}
    +#endif
    +
    +static int hw_breakpoint_parse(struct perf_event *bp,
    + const struct perf_event_attr *attr,
    + struct arch_hw_breakpoint *hw)
    +{
    + int err;
    +
    + err = hw_breakpoint_arch_parse(bp, attr, hw);
    + if (err)
    + return err;

    if (arch_check_bp_in_kernelspace(bp)) {
    - if (bp->attr.exclude_kernel)
    + if (attr->exclude_kernel)
    return -EINVAL;
    /*
    * Don't let unprivileged users set a breakpoint in the trap
    @@ -424,19 +443,22 @@ static int validate_hw_breakpoint(struct perf_event *bp)

    int register_perf_hw_breakpoint(struct perf_event *bp)
    {
    - int ret;
    -
    - ret = reserve_bp_slot(bp);
    - if (ret)
    - return ret;
    + struct arch_hw_breakpoint hw;
    + int err;

    - ret = validate_hw_breakpoint(bp);
    + err = reserve_bp_slot(bp);
    + if (err)
    + return err;

    - /* if arch_validate_hwbkpt_settings() fails then release bp slot */
    - if (ret)
    + err = hw_breakpoint_parse(bp, &bp->attr, &hw);
    + if (err) {
    release_bp_slot(bp);
    + return err;
    + }

    - return ret;
    + bp->hw.info = hw;
    +
    + return 0;
    }

    /**
    @@ -464,6 +486,7 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a
    u64 old_len = bp->attr.bp_len;
    int old_type = bp->attr.bp_type;
    bool modify = attr->bp_type != old_type;
    + struct arch_hw_breakpoint hw;
    int err = 0;

    bp->attr.bp_addr = attr->bp_addr;
    @@ -473,7 +496,7 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a
    if (check && memcmp(&bp->attr, attr, sizeof(*attr)))
    return -EINVAL;

    - err = validate_hw_breakpoint(bp);
    + err = hw_breakpoint_parse(bp, attr, &hw);
    if (!err && modify)
    err = modify_bp_slot(bp, old_type);

    @@ -484,7 +507,9 @@ modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *a
    return err;
    }

    + bp->hw.info = hw;
    bp->attr.disabled = attr->disabled;
    +
    return 0;
    }

    --
    2.17.1
    \
     
     \ /
      Last update: 2018-09-17 05:30    [W:3.406 / U:0.008 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site