lkml.org 
[lkml]   [2019]   [Jan]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    SubjectRe: [PATCH v3 5/6] x86/alternative: Use a single access in text_poke() where possible
    From
    Date

    On 01/11/2019 05:57 PM, Josh Poimboeuf wrote:
    > On Fri, Jan 11, 2019 at 05:46:36PM +0100, Alexandre Chartre wrote:
    >>
    >>
    >> On 01/11/2019 04:28 PM, Josh Poimboeuf wrote:
    >>> On Fri, Jan 11, 2019 at 01:10:52PM +0100, Alexandre Chartre wrote:
    >>>> To avoid any issue with live patching the call instruction, what about
    >>>> toggling between two call instructions: one would be the currently active
    >>>> call, while the other would currently be inactive but to be used after a
    >>>> change is made. You can safely patch the inactive call and then toggle
    >>>> the call flow (using a jump label) between the active and inactive calls.
    >>>>
    >>>> So instead of having a single call instruction:
    >>>>
    >>>> call function
    >>>>
    >>>> You would have:
    >>>>
    >>>> STATIC_JUMP_IF_TRUE label, key
    >>>> call function1
    >>>> jmp done
    >>>> label:
    >>>> call function2
    >>>> done:
    >>>>
    >>>> If the key is set so that function1 is currently called then you can
    >>>> safely update the call instruction for function2. Once this is done,
    >>>> just flip the key to make the function2 call active. On a next update,
    >>>> you would, of course, have to switch and update the call for function1.
    >>>
    >>> What about the following race?
    >>>
    >>> CPU1 CPU2
    >>> static key is false, doesn't jump
    >>> task gets preempted before calling function1
    >>> change static key to true
    >>> start patching "call function1"
    >>> task resumes, sees inconsistent call instruction
    >>>
    >>
    >> If the function1 call is active then it won't be changed, you will change
    >> function2. However, I presume you can still have a race but if the function
    >> is changed twice before calling function1:
    >>
    >> CPU1 CPU2
    >> static key is false, doesn't jump
    >> task gets preempted before calling function1
    >> -- first function change --
    >> patch "call function2"
    >> change static key to true
    >> -- second function change --
    >> start patching "call function1"
    >> task resumes, sees inconsistent call instruction
    >>
    >> So right, that's a problem.
    >
    > Right, that's what I meant to say :-)
    >

    Thinking more about it (and I've probably missed something or I am just being
    totally stupid because this seems way too simple), can't we just replace the
    "call" with "push+jmp" and patch the jmp instruction?

    Instead of having:

    call target

    Have:

    push $done
    static_call:
    jmp target
    done:

    Then we can safely patch the "jmp" instruction to jump to a new target
    with text_poke_bp(), using the new target as the text_poke_bp() handler:

    new_jmp_code = opcode of "jmp new_target"

    text_poke_bp(static_call, new_jmp_code, new_jmp_code_size, new_target);

    Problems come with patching a call instruction, but there's no issue with patching
    a jmp, no? (that's what jump labels do).

    No change to the int3 handler, no thunk, this seems really too simple... :-)


    alex.

    \
     
     \ /
      Last update: 2019-01-15 12:13    [W:5.316 / U:0.072 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site