lkml.org 
[lkml]   [2015]   [Jul]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH v3 05/14] uprobes: Change handle_trampoline() to find the next chain beforehand
    No functional changes, preparation.

    Add the new helper, find_next_ret_chain(), which finds the first !chained
    entry and returns its ->next. Yes, it is suboptimal. We probably want to
    turn ->chained into ->start_of_this_chain pointer and avoid another loop.
    But this needs the boring changes in dup_utask(), so lets do this later.

    Change the main loop in handle_trampoline() to unwind the stack until ri
    is equal to the pointer returned by this new helper.

    Signed-off-by: Oleg Nesterov <oleg@redhat.com>
    Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
    Acked-by: Anton Arapov <arapov@gmail.com>
    Tested-by: Pratyush Anand <panand@redhat.com>
    ---
    kernel/events/uprobes.c | 27 ++++++++++++++++-----------
    1 files changed, 16 insertions(+), 11 deletions(-)

    diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
    index 4c941fe..98e4d97 100644
    --- a/kernel/events/uprobes.c
    +++ b/kernel/events/uprobes.c
    @@ -1766,11 +1766,22 @@ handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs)
    up_read(&uprobe->register_rwsem);
    }

    +static struct return_instance *find_next_ret_chain(struct return_instance *ri)
    +{
    + bool chained;
    +
    + do {
    + chained = ri->chained;
    + ri = ri->next; /* can't be NULL if chained */
    + } while (chained);
    +
    + return ri;
    +}
    +
    static void handle_trampoline(struct pt_regs *regs)
    {
    struct uprobe_task *utask;
    - struct return_instance *ri;
    - bool chained;
    + struct return_instance *ri, *next;

    utask = current->utask;
    if (!utask)
    @@ -1780,24 +1791,18 @@ static void handle_trampoline(struct pt_regs *regs)
    if (!ri)
    goto sigill;

    + next = find_next_ret_chain(ri);
    /*
    * TODO: we should throw out return_instance's invalidated by
    * longjmp(), currently we assume that the probed function always
    * returns.
    */
    instruction_pointer_set(regs, ri->orig_ret_vaddr);
    -
    - for (;;) {
    + do {
    handle_uretprobe_chain(ri, regs);
    -
    - chained = ri->chained;
    ri = free_ret_instance(ri);
    utask->depth--;
    -
    - if (!chained)
    - break;
    - BUG_ON(!ri);
    - }
    + } while (ri != next);

    utask->return_instances = ri;
    return;
    --
    1.5.5.1


    \
     
     \ /
      Last update: 2015-07-21 16:01    [W:5.174 / U:0.616 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site