Re: [PATCH v2] uprobes: fix scratch register selection for rip-relative fixups

From: Jim Keniston
Date: Fri May 02 2014 - 19:43:20 EST


On Fri, 2014-05-02 at 17:04 +0200, Denys Vlasenko wrote:
> Before this patch, instructions such as div, mul,
> shifts with count in CL, cmpxchg are mishandled.

I just noticed that this sounds rather worse than it is. It would be
more precise to say, "Before this patch, the rip-relative addressing
mode in instructions such as ... is mishandled."

...
>
> Signed-off-by: Denys Vlasenko <dvlasenk@xxxxxxxxxx>
> CC: Jim Keniston <jkenisto@xxxxxxxxxx>
> CC: Masami Hiramatsu <masami.hiramatsu.pt@xxxxxxxxxxx>
> CC: Srikar Dronamraju <srikar@xxxxxxxxxxxxxxxxxx>
> CC: Ingo Molnar <mingo@xxxxxxxxxx>
> CC: Oleg Nesterov <oleg@xxxxxxxxxx>
> ---
> arch/x86/kernel/uprobes.c | 179 +++++++++++++++++++++++++++++++++-------------
> 1 file changed, 128 insertions(+), 51 deletions(-)
>
> diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
> index dbbf6cd..5b387b7 100644
> --- a/arch/x86/kernel/uprobes.c
> +++ b/arch/x86/kernel/uprobes.c
> @@ -41,8 +41,12 @@
> /* Instruction will modify TF, don't change it */
> #define UPROBE_FIX_SETF 0x04
>
> -#define UPROBE_FIX_RIP_AX 0x08
> -#define UPROBE_FIX_RIP_CX 0x10
> +#define UPROBE_FIX_RIP_SI 0x08
> +#define UPROBE_FIX_RIP_DI 0x10
> +#define UPROBE_FIX_RIP_BX 0x20
> +#define UPROBE_FIX_RIP_MASK (UPROBE_FIX_RIP_SI \
> + | UPROBE_FIX_RIP_DI \
> + | UPROBE_FIX_RIP_BX)

Yes.

...
> + /* Fetch vex.vvvv */
> + reg2 = 0xff;
> + if (insn->vex_prefix.nbytes == 2) {
> + reg2 = insn->vex_prefix.bytes[1];
> + }
> + if (insn->vex_prefix.nbytes == 3) {
> + reg2 = insn->vex_prefix.bytes[2];
> + }
> + /* TODO: add XOP, EXEV vvvv reading */
> + /*
> + * vex.vvvv field is in bits 6-3, bits are inverted.
> + * But in 32-bit mode, high-order bit may be ignored.
> + * Therefore, let's consider only 3 low-order bits.
> + */
> + reg2 = ((reg2 >> 3) & 0x7) ^ 0x7;
>
> + /* Register numbering is ax,cx,dx,bx, sp,bp,si,di, r8..r15 */
> + /*
> + * Choose scratch reg. Order is important:
> + * must not select bx if we can use si (cmpxchg8b case!)

It'd be good to add here:
* For instructions without a VEX prefix, reg2 is 0 here.

Otherwise it kind of looks like you forgot to address that case, and the
reader shouldn't have to do the bit fiddling to figure it out.

> + */
> + if (reg != 6 && reg2 != 6) {
> + reg2 = 6;
> + auprobe->def.fixups |= UPROBE_FIX_RIP_SI;
> + } else if (reg != 7 && reg2 != 7) {
> + reg2 = 7;
> + auprobe->def.fixups |= UPROBE_FIX_RIP_DI;
> + /* TODO (paranoia): force maskmovq to not use di */
> + } else {
> + reg2 = 3; /* BX */
> + auprobe->def.fixups |= UPROBE_FIX_RIP_BX;
> + }

Yes. Looks good from here down.

Reviewed-by: Jim Keniston <jkenisto@xxxxxxxxxx>


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/