lkml.org 
[lkml]   [2018]   [Mar]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5/8] hw_breakpoint: Add perf_event_attr fields check in __modify_user_hw_breakpoint
    Date
    And rename it to modify_user_hw_breakpoint_check.

    We are about to use modify_user_hw_breakpoint_check for user space
    breakpoints modification, we must be very strict to check only the
    fields we can change have changed. As Peter explained:

    Suppose someone does:
    attr = malloc(sizeof(*attr)); // uninitialized memory
    attr->type = BP;
    attr->bp_addr = new_addr;
    attr->bp_type = bp_type;
    attr->bp_len = bp_len;
    ioctl(fd, PERF_IOC_MOD_ATTR, &attr);

    And feeds absolute shite for the rest of the fields.
    Then we later want to extend IOC_MOD_ATTR to allow changing
    attr::sample_type but we can't, because that would break the
    above application.

    I'm making this check optional because we already export
    modify_user_hw_breakpoint and with this check we could
    break existing users.

    Suggested-by: Peter Zijlstra <peterz@infradead.org>
    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    ---
    kernel/events/hw_breakpoint.c | 9 +++++++--
    1 file changed, 7 insertions(+), 2 deletions(-)

    diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
    index a556aba223da..0c82663395f7 100644
    --- a/kernel/events/hw_breakpoint.c
    +++ b/kernel/events/hw_breakpoint.c
    @@ -456,7 +456,9 @@ register_user_hw_breakpoint(struct perf_event_attr *attr,
    }
    EXPORT_SYMBOL_GPL(register_user_hw_breakpoint);

    -static int __modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *attr)
    +static int
    +modify_user_hw_breakpoint_check(struct perf_event *bp, struct perf_event_attr *attr,
    + bool check)
    {
    u64 old_addr = bp->attr.bp_addr;
    u64 old_len = bp->attr.bp_len;
    @@ -468,6 +470,9 @@ static int __modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_
    bp->attr.bp_type = attr->bp_type;
    bp->attr.bp_len = attr->bp_len;

    + if (check && memcmp(&bp->attr, attr, sizeof(*attr)))
    + return -EINVAL;
    +
    err = validate_hw_breakpoint(bp);
    if (!err && modify)
    err = modify_bp_slot(bp, old_type);
    @@ -505,7 +510,7 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
    else
    perf_event_disable(bp);

    - err = __modify_user_hw_breakpoint(bp, attr);
    + err = modify_user_hw_breakpoint_check(bp, attr, false);

    if (err) {
    if (!bp->attr.disabled)
    --
    2.13.6
    \
     
     \ /
      Last update: 2018-03-12 14:47    [W:5.444 / U:0.268 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site