1. 02 Jun, 2014 1 commit
    • Oleg Nesterov's avatar
      uprobes: Shift ->readpage check from __copy_insn() to uprobe_register() · 7fa31348
      Oleg Nesterov authored
      copy_insn() fails with -EIO if ->readpage == NULL, but this error
      is not propagated unless uprobe_register() path finds ->mm which
      already mmaps this file. In this case (say) "perf record" does not
      actually install the probe, but the user can't know about this.
      
      Move this check into uprobe_register() so that this problem can be
      detected earlier and reported to user.
      
      Note: this is still not perfect,
      
      	- copy_insn() and arch_uprobe_analyze_insn() should be called
      	  by uprobe_register() but this is not simple, we need vm_file
      	  for read_mapping_page() (although perhaps we can pass NULL),
      	  and we need ->mm for is_64bit_mm() (although this logic is
      	  broken anyway).
      
      	- uprobe_register() should be called by create_trace_uprobe(),
      	  not by probe_event_enable(), so that an error can be detected
      	  at "perf probe -x" time. This also needs more changes in the
      	  core uprobe code, uprobe register/unregister interface was
      	  poorly designed from the very beginning.
      Reported-by: default avatarDenys Vlasenko <dvlasenk@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      7fa31348
  2. 22 May, 2014 1 commit
  3. 14 May, 2014 10 commits
    • Oleg Nesterov's avatar
      uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap · b02ef20a
      Oleg Nesterov authored
      If the probed insn triggers a trap, ->si_addr = regs->ip is technically
      correct, but this is not what the signal handler wants; we need to pass
      the address of the probed insn, not the address of xol slot.
      
      Add the new arch-agnostic helper, uprobe_get_trap_addr(), and change
      fill_trap_info() and math_error() to use it. !CONFIG_UPROBES case in
      uprobes.h uses a macro to avoid include hell and ensure that it can be
      compiled even if an architecture doesn't define instruction_pointer().
      
      Test-case:
      
      	#include <signal.h>
      	#include <stdio.h>
      	#include <unistd.h>
      
      	extern void probe_div(void);
      
      	void sigh(int sig, siginfo_t *info, void *c)
      	{
      		int passed = (info->si_addr == probe_div);
      		printf(passed ? "PASS\n" : "FAIL\n");
      		_exit(!passed);
      	}
      
      	int main(void)
      	{
      		struct sigaction sa = {
      			.sa_sigaction	= sigh,
      			.sa_flags	= SA_SIGINFO,
      		};
      
      		sigaction(SIGFPE, &sa, NULL);
      
      		asm (
      			"xor %ecx,%ecx\n"
      			".globl probe_div; probe_div:\n"
      			"idiv %ecx\n"
      		);
      
      		return 0;
      	}
      
      it fails if probe_div() is probed.
      
      Note: show_unhandled_signals users should probably use this helper too,
      but we need to cleanup them first.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Reviewed-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      b02ef20a
    • Oleg Nesterov's avatar
      x86/traps: Kill DO_ERROR_INFO() · 0eb14833
      Oleg Nesterov authored
      Now that DO_ERROR_INFO() doesn't differ from DO_ERROR() we can remove
      it and use DO_ERROR() instead.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      0eb14833
    • Oleg Nesterov's avatar
      x86/traps: Shift fill_trap_info() from DO_ERROR_INFO() to do_error_trap() · 1c326c4d
      Oleg Nesterov authored
      Move the callsite of fill_trap_info() into do_error_trap() and remove
      the "siginfo_t *info" argument.
      
      This obviously breaks DO_ERROR() which passed info == NULL, we simply
      change fill_trap_info() to return "siginfo_t *" and add the "default"
      case which returns SEND_SIG_PRIV.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      1c326c4d
    • Oleg Nesterov's avatar
      x86/traps: Introduce fill_trap_info(), simplify DO_ERROR_INFO() · 958d3d72
      Oleg Nesterov authored
      Extract the fill-siginfo code from DO_ERROR_INFO() into the new helper,
      fill_trap_info().
      
      It can calculate si_code and si_addr looking at trapnr, so we can remove
      these arguments from DO_ERROR_INFO() and simplify the source code. The
      generated code is the same, __builtin_constant_p(trapnr) == T.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      958d3d72
    • Oleg Nesterov's avatar
      x86/traps: Introduce do_error_trap() · dff0796e
      Oleg Nesterov authored
      Move the common code from DO_ERROR() and DO_ERROR_INFO() into the new
      helper, do_error_trap(). This simplifies define's and shaves 527 bytes
      from traps.o.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      dff0796e
    • Oleg Nesterov's avatar
      x86/traps: Use SEND_SIG_PRIV instead of force_sig() · 38cad57b
      Oleg Nesterov authored
      force_sig() is just force_sig_info(SEND_SIG_PRIV). Imho it should die,
      we have too many ugly "send signal" helpers.
      
      And do_trap() looks just ugly because it uses force_sig_info() or
      force_sig() depending on info != NULL.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      38cad57b
    • Oleg Nesterov's avatar
      x86/traps: Make math_error() static · 5e1b05be
      Oleg Nesterov authored
      Trivial, make math_error() static.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      5e1b05be
    • 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
  4. 05 May, 2014 1 commit
  5. 01 May, 2014 3 commits
  6. 30 Apr, 2014 24 commits