1. 22 5月, 2014 1 次提交
  2. 14 5月, 2014 10 次提交
    • O
      uprobes/x86: Fix the wrong ->si_addr when xol triggers a trap · b02ef20a
      Oleg Nesterov 提交于
      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: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      b02ef20a
    • O
      x86/traps: Kill DO_ERROR_INFO() · 0eb14833
      Oleg Nesterov 提交于
      Now that DO_ERROR_INFO() doesn't differ from DO_ERROR() we can remove
      it and use DO_ERROR() instead.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      0eb14833
    • O
      x86/traps: Shift fill_trap_info() from DO_ERROR_INFO() to do_error_trap() · 1c326c4d
      Oleg Nesterov 提交于
      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: NOleg Nesterov <oleg@redhat.com>
      1c326c4d
    • O
      x86/traps: Introduce fill_trap_info(), simplify DO_ERROR_INFO() · 958d3d72
      Oleg Nesterov 提交于
      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: NOleg Nesterov <oleg@redhat.com>
      958d3d72
    • O
      x86/traps: Introduce do_error_trap() · dff0796e
      Oleg Nesterov 提交于
      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: NOleg Nesterov <oleg@redhat.com>
      dff0796e
    • O
      x86/traps: Use SEND_SIG_PRIV instead of force_sig() · 38cad57b
      Oleg Nesterov 提交于
      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: NOleg Nesterov <oleg@redhat.com>
      38cad57b
    • O
      x86/traps: Make math_error() static · 5e1b05be
      Oleg Nesterov 提交于
      Trivial, make math_error() static.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      5e1b05be
    • D
      uprobes/x86: Fix scratch register selection for rip-relative fixups · 1ea30fb6
      Denys Vlasenko 提交于
      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: NDenys Vlasenko <dvlasenk@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      1ea30fb6
    • D
      uprobes/x86: Simplify rip-relative handling · 50204c6f
      Denys Vlasenko 提交于
      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: NDenys Vlasenko <dvlasenk@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      50204c6f
    • O
      uprobes: Add mem_cgroup_charge_anon() into uprobe_write_opcode() · 29dedee0
      Oleg Nesterov 提交于
      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: NHugh Dickins <hughd@google.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      29dedee0
  3. 05 5月, 2014 1 次提交
  4. 01 5月, 2014 24 次提交
  5. 30 4月, 2014 4 次提交