1. 14 May, 2014 3 commits
    • Denys Vlasenko's avatar
      uprobes/x86: Fix scratch register selection for rip-relative fixups · 1ea30fb6
      Denys Vlasenko authored
      Before this patch, instructions such as div, mul, shifts with count
      in CL, cmpxchg are mishandled.
      
      This patch adds vex prefix handling. In particular, it avoids colliding
      with register operand encoded in vex.vvvv field.
      
      Since we need to avoid two possible register operands, the selection of
      scratch register needs to be from at least three registers.
      
      After looking through a lot of CPU docs, it looks like the safest choice
      is SI,DI,BX. Selecting BX needs care to not collide with implicit use of
      BX by cmpxchg8b.
      
      Test-case:
      
      	#include <stdio.h>
      
      	static const char *const pass[] = { "FAIL", "pass" };
      
      	long two = 2;
      	void test1(void)
      	{
      		long ax = 0, dx = 0;
      		asm volatile("\n"
      	"			xor	%%edx,%%edx\n"
      	"			lea	2(%%edx),%%eax\n"
      	// We divide 2 by 2. Result (in eax) should be 1:
      	"	probe1:		.globl	probe1\n"
      	"			divl	two(%%rip)\n"
      	// If we have a bug (eax mangled on entry) the result will be 2,
      	// because eax gets restored by probe machinery.
      		: "=a" (ax), "=d" (dx) /*out*/
      		: "0" (ax), "1" (dx) /*in*/
      		: "memory" /*clobber*/
      		);
      		dprintf(2, "%s: %s\n", __func__,
      			pass[ax == 1]
      		);
      	}
      
      	long val2 = 0;
      	void test2(void)
      	{
      		long old_val = val2;
      		long ax = 0, dx = 0;
      		asm volatile("\n"
      	"			mov	val2,%%eax\n"     // eax := val2
      	"			lea	1(%%eax),%%edx\n" // edx := eax+1
      	// eax is equal to val2. cmpxchg should store edx to val2:
      	"	probe2:		.globl  probe2\n"
      	"			cmpxchg %%edx,val2(%%rip)\n"
      	// If we have a bug (eax mangled on entry), val2 will stay unchanged
      		: "=a" (ax), "=d" (dx) /*out*/
      		: "0" (ax), "1" (dx) /*in*/
      		: "memory" /*clobber*/
      		);
      		dprintf(2, "%s: %s\n", __func__,
      			pass[val2 == old_val + 1]
      		);
      	}
      
      	long val3[2] = {0,0};
      	void test3(void)
      	{
      		long old_val = val3[0];
      		long ax = 0, dx = 0;
      		asm volatile("\n"
      	"			mov	val3,%%eax\n"  // edx:eax := val3
      	"			mov	val3+4,%%edx\n"
      	"			mov	%%eax,%%ebx\n" // ecx:ebx := edx:eax + 1
      	"			mov	%%edx,%%ecx\n"
      	"			add	$1,%%ebx\n"
      	"			adc	$0,%%ecx\n"
      	// edx:eax is equal to val3. cmpxchg8b should store ecx:ebx to val3:
      	"	probe3:		.globl  probe3\n"
      	"			cmpxchg8b val3(%%rip)\n"
      	// If we have a bug (edx:eax mangled on entry), val3 will stay unchanged.
      	// If ecx:edx in mangled, val3 will get wrong value.
      		: "=a" (ax), "=d" (dx) /*out*/
      		: "0" (ax), "1" (dx) /*in*/
      		: "cx", "bx", "memory" /*clobber*/
      		);
      		dprintf(2, "%s: %s\n", __func__,
      			pass[val3[0] == old_val + 1 && val3[1] == 0]
      		);
      	}
      
      	int main(int argc, char **argv)
      	{
      		test1();
      		test2();
      		test3();
      		return 0;
      	}
      
      Before this change all tests fail if probe{1,2,3} are probed.
      Signed-off-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
      Reviewed-by: default avatarJim Keniston <jkenisto@us.ibm.com>
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      1ea30fb6
    • Denys Vlasenko's avatar
      uprobes/x86: Simplify rip-relative handling · 50204c6f
      Denys Vlasenko authored
      It is possible to replace rip-relative addressing mode with addressing
      mode of the same length: (reg+disp32). This eliminates the need to fix
      up immediate and correct for changing instruction length.
      
      And we can kill arch_uprobe->def.riprel_target.
      Signed-off-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
      Reviewed-by: default avatarJim Keniston <jkenisto@us.ibm.com>
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      50204c6f
    • Oleg Nesterov's avatar
      uprobes: Add mem_cgroup_charge_anon() into uprobe_write_opcode() · 29dedee0
      Oleg Nesterov authored
      Hugh says:
      
          The one I noticed was that it forgets all about memcg (because
          it was copied from KSM, and there the replacement page has already
          been charged to a memcg). See how mm/memory.c do_anonymous_page()
          does a mem_cgroup_charge_anon().
      
      Hopefully not a big problem, uprobes is a system-wide thing and only
      root can insert the probes. But I agree, should be fixed anyway.
      
      Add mem_cgroup_{un,}charge_anon() into uprobe_write_opcode(). To simplify
      the error handling (and avoid the new "uncharge" label) the patch also
      moves anon_vma_prepare() up before we alloc/charge the new page.
      
      While at it fix the comment about ->mmap_sem, it is held for write.
      Suggested-by: default avatarHugh Dickins <hughd@google.com>
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      29dedee0
  2. 05 May, 2014 1 commit
  3. 01 May, 2014 3 commits
  4. 30 Apr, 2014 28 commits
  5. 29 Apr, 2014 5 commits