1. 01 5月, 2014 11 次提交
  2. 18 4月, 2014 14 次提交
    • O
      uprobes/x86: Emulate relative conditional "near" jmp's · 6cc5e7ff
      Oleg Nesterov 提交于
      Change branch_setup_xol_ops() to simply use opc1 = OPCODE2(insn) - 0x10
      if OPCODE1() == 0x0f; this matches the "short" jmp which checks the same
      condition.
      
      Thanks to lib/insn.c, it does the rest correctly. branch->ilen/offs are
      correct no matter if this jmp is "near" or "short".
      Reported-by: NJonathan Lebon <jlebon@redhat.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      6cc5e7ff
    • O
      uprobes/x86: Emulate relative conditional "short" jmp's · 8f95505b
      Oleg Nesterov 提交于
      Teach branch_emulate_op() to emulate the conditional "short" jmp's which
      check regs->flags.
      
      Note: this doesn't support jcxz/jcexz, loope/loopz, and loopne/loopnz.
      They all are rel8 and thus they can't trigger the problem, but perhaps
      we will add the support in future just for completeness.
      Reported-by: NJonathan Lebon <jlebon@redhat.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      8f95505b
    • O
      uprobes/x86: Emulate relative call's · 8e89c0be
      Oleg Nesterov 提交于
      See the previous "Emulate unconditional relative jmp's" which explains
      why we can not execute "jmp" out-of-line, the same applies to "call".
      
      Emulating of rip-relative call is trivial, we only need to additionally
      push the ret-address. If this fails, we execute this instruction out of
      line and this should trigger the trap, the probed application should die
      or the same insn will be restarted if a signal handler expands the stack.
      We do not even need ->post_xol() for this case.
      
      But there is a corner (and almost theoretical) case: another thread can
      expand the stack right before we execute this insn out of line. In this
      case it hit the same problem we are trying to solve. So we simply turn
      the probed insn into "call 1f; 1:" and add ->post_xol() which restores
      ->sp and restarts.
      
      Many thanks to Jonathan who finally found the standalone reproducer,
      otherwise I would never resolve the "random SIGSEGV's under systemtap"
      bug-report. Now that the problem is clear we can write the simplified
      test-case:
      
      	void probe_func(void), callee(void);
      
      	int failed = 1;
      
      	asm (
      		".text\n"
      		".align 4096\n"
      		".globl probe_func\n"
      		"probe_func:\n"
      		"call callee\n"
      		"ret"
      	);
      
      	/*
      	 * This assumes that:
      	 *
      	 *	- &probe_func = 0x401000 + a_bit, aligned = 0x402000
      	 *
      	 *	- xol_vma->vm_start = TASK_SIZE_MAX - PAGE_SIZE = 0x7fffffffe000
      	 *	  as xol_add_vma() asks; the 1st slot = 0x7fffffffe080
      	 *
      	 * so we can target the non-canonical address from xol_vma using
      	 * the simple math below, 100 * 4096 is just the random offset
      	 */
      	asm (".org . + 0x800000000000 - 0x7fffffffe080 - 5 - 1  + 100 * 4096\n");
      
      	void callee(void)
      	{
      		failed = 0;
      	}
      
      	int main(void)
      	{
      		probe_func();
      		return failed;
      	}
      
      It SIGSEGV's if you probe "probe_func" (although this is not very reliable,
      randomize_va_space/etc can change the placement of xol area).
      
      Note: as Denys Vlasenko pointed out, amd and intel treat "callw" (0x66 0xe8)
      differently. This patch relies on lib/insn.c and thus implements the intel's
      behaviour: 0x66 is simply ignored. Fortunately nothing sane should ever use
      this insn, so we postpone the fix until we decide what should we do; emulate
      or not, support or not, etc.
      Reported-by: NJonathan Lebon <jlebon@redhat.com>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      8e89c0be
    • O
      uprobes/x86: Emulate nop's using ops->emulate() · d2410063
      Oleg Nesterov 提交于
      Finally we can kill the ugly (and very limited) code in __skip_sstep().
      Just change branch_setup_xol_ops() to treat "nop" as jmp to the next insn.
      
      Thanks to lib/insn.c, it is clever enough. OPCODE1() == 0x90 includes
      "(rep;)+ nop;" at least, and (afaics) much more.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      d2410063
    • O
      uprobes/x86: Emulate unconditional relative jmp's · 7ba6db2d
      Oleg Nesterov 提交于
      Currently we always execute all insns out-of-line, including relative
      jmp's and call's. This assumes that even if regs->ip points to nowhere
      after the single-step, default_post_xol_op(UPROBE_FIX_IP) logic will
      update it correctly.
      
      However, this doesn't work if this regs->ip == xol_vaddr + insn_offset
      is not canonical. In this case CPU generates #GP and general_protection()
      kills the task which tries to execute this insn out-of-line.
      
      Now that we have uprobe_xol_ops we can teach uprobes to emulate these
      insns and solve the problem. This patch adds branch_xol_ops which has
      a single branch_emulate_op() hook, so far it can only handle rel8/32
      relative jmp's.
      
      TODO: move ->fixup into the union along with rip_rela_target_address.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reported-by: NJonathan Lebon <jlebon@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      7ba6db2d
    • O
      uprobes/x86: Introduce sizeof_long(), cleanup adjust_ret_addr() and... · 8faaed1b
      Oleg Nesterov 提交于
      uprobes/x86: Introduce sizeof_long(), cleanup adjust_ret_addr() and arch_uretprobe_hijack_return_addr()
      
      1. Add the trivial sizeof_long() helper and change other callers of
         is_ia32_task() to use it.
      
         TODO: is_ia32_task() is not what we actually want, TS_COMPAT does
         not necessarily mean 32bit. Fortunately syscall-like insns can't be
         probed so it actually works, but it would be better to rename and
         use is_ia32_frame().
      
      2. As Jim pointed out "ncopied" in arch_uretprobe_hijack_return_addr()
         and adjust_ret_addr() should be named "nleft". And in fact only the
         last copy_to_user() in arch_uretprobe_hijack_return_addr() actually
         needs to inspect the non-zero error code.
      
      TODO: adjust_ret_addr() should die. We can always calculate the value
      we need to write into *regs->sp, just UPROBE_FIX_CALL should record
      insn->length.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      8faaed1b
    • O
      uprobes/x86: Teach arch_uprobe_post_xol() to restart if possible · 75f9ef0b
      Oleg Nesterov 提交于
      SIGILL after the failed arch_uprobe_post_xol() should only be used as
      a last resort, we should try to restart the probed insn if possible.
      
      Currently only adjust_ret_addr() can fail, and this can only happen if
      another thread unmapped our stack after we executed "call" out-of-line.
      Most probably the application if buggy, but even in this case it can
      have a handler for SIGSEGV/etc. And in theory it can be even correct
      and do something non-trivial with its memory.
      
      Of course we can't restart unconditionally, so arch_uprobe_post_xol()
      does this only if ->post_xol() returns -ERESTART even if currently this
      is the only possible error.
      
      default_post_xol_op(UPROBE_FIX_CALL) can always restart, but as Jim
      pointed out it should not forget to pop off the return address pushed
      by this insn executed out-of-line.
      
      Note: this is not "perfect", we do not want the extra handler_chain()
      after restart, but I think this is the best solution we can realistically
      do without too much uglifications.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      75f9ef0b
    • O
      uprobes/x86: Send SIGILL if arch_uprobe_post_xol() fails · 014940ba
      Oleg Nesterov 提交于
      Currently the error from arch_uprobe_post_xol() is silently ignored.
      This doesn't look good and this can lead to the hard-to-debug problems.
      
      1. Change handle_singlestep() to loudly complain and send SIGILL.
      
         Note: this only affects x86, ppc/arm can't fail.
      
      2. Change arch_uprobe_post_xol() to call arch_uprobe_abort_xol() and
         avoid TF games if it is going to return an error.
      
         This can help to to analyze the problem, if nothing else we should
         not report ->ip = xol_slot in the core-file.
      
         Note: this means that handle_riprel_post_xol() can be called twice,
         but this is fine because it is idempotent.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      014940ba
    • O
      uprobes/x86: Conditionalize the usage of handle_riprel_insn() · e55848a4
      Oleg Nesterov 提交于
      arch_uprobe_analyze_insn() calls handle_riprel_insn() at the start,
      but only "0xff" and "default" cases need the UPROBE_FIX_RIP_ logic.
      Move the callsite into "default" case and change the "0xff" case to
      fall-through.
      
      We are going to add the various hooks to handle the rip-relative
      jmp/call instructions (and more), we need this change to enforce the
      fact that the new code can not conflict with is_riprel_insn() logic
      which, after this change, can only be used by default_xol_ops.
      
      Note: arch_uprobe_abort_xol() still calls handle_riprel_post_xol()
      directly. This is fine unless another _xol_ops we may add later will
      need to reuse "UPROBE_FIX_RIP_AX|UPROBE_FIX_RIP_CX" bits in ->fixup.
      In this case we can add uprobe_xol_ops->abort() hook, which (perhaps)
      we will need anyway in the long term.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      e55848a4
    • O
      uprobes/x86: Introduce uprobe_xol_ops and arch_uprobe->ops · 8ad8e9d3
      Oleg Nesterov 提交于
      Introduce arch_uprobe->ops pointing to the "struct uprobe_xol_ops",
      move the current UPROBE_FIX_{RIP*,IP,CALL} code into the default
      set of methods and change arch_uprobe_pre/post_xol() accordingly.
      
      This way we can add the new uprobe_xol_ops's to handle the insns
      which need the special processing (rip-relative jmp/call at least).
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      8ad8e9d3
    • O
      uprobes/x86: move the UPROBE_FIX_{RIP,IP,CALL} code at the end of pre/post hooks · 34e7317d
      Oleg Nesterov 提交于
      No functional changes. Preparation to simplify the review of the next
      change. Just reorder the code in arch_uprobe_pre/post_xol() functions
      so that UPROBE_FIX_{RIP_*,IP,CALL} logic goes to the end.
      
      Also change arch_uprobe_pre_xol() to use utask instead of autask, to
      make the code more symmetrical with arch_uprobe_post_xol().
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      34e7317d
    • O
      uprobes/x86: Gather "riprel" functions together · d20737c0
      Oleg Nesterov 提交于
      Cosmetic. Move pre_xol_rip_insn() and handle_riprel_post_xol() up to
      the closely related handle_riprel_insn(). This way it is simpler to
      read and understand this code, and this lessens the number of ifdef's.
      
      While at it, update the comment in handle_riprel_post_xol() as Jim
      suggested.
      
      TODO: rename them somehow to make the naming consistent.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      d20737c0
    • O
      uprobes/x86: Kill the "ia32_compat" check in handle_riprel_insn(), remove "mm" arg · 59078d4b
      Oleg Nesterov 提交于
      Kill the "mm->context.ia32_compat" check in handle_riprel_insn(), if
      it is true insn_rip_relative() must return false. validate_insn_bits()
      passed "ia32_compat" as !x86_64 to insn_init(), and insn_rip_relative()
      checks insn->x86_64.
      
      Also, remove the no longer needed "struct mm_struct *mm" argument and
      the unnecessary "return" at the end.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      59078d4b
    • O
      uprobes/x86: Fold prepare_fixups() into arch_uprobe_analyze_insn() · ddb69f27
      Oleg Nesterov 提交于
      No functional changes, preparation.
      
      Shift the code from prepare_fixups() to arch_uprobe_analyze_insn()
      with the following modifications:
      
      	- Do not call insn_get_opcode() again, it was already called
      	  by validate_insn_bits().
      
      	- Move "case 0xea" up. This way "case 0xff" can fall through
      	  to default case.
      
      	- change "case 0xff" to use the nested "switch (MODRM_REG)",
      	  this way the code looks a bit simpler.
      
      	- Make the comments look consistent.
      
      While at it, kill the initialization of rip_rela_target_address and
      ->fixups, we can rely on kzalloc(). We will add the new members into
      arch_uprobe, it would be better to assume that everything is zero by
      default.
      
      TODO: cleanup/fix the mess in validate_insn_bits() paths:
      
      	- validate_insn_64bits() and validate_insn_32bits() should be
      	  unified.
      
      	- "ifdef" is not used consistently; if good_insns_64 depends
      	  on CONFIG_X86_64, then probably good_insns_32 should depend
      	  on CONFIG_X86_32/EMULATION
      
      	- the usage of mm->context.ia32_compat looks wrong if the task
      	  is TIF_X32.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Reviewed-by: NMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Reviewed-by: NJim Keniston <jkenisto@us.ibm.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      ddb69f27
  3. 13 4月, 2013 1 次提交
  4. 09 2月, 2013 2 次提交
  5. 04 11月, 2012 1 次提交
  6. 08 10月, 2012 1 次提交
  7. 15 9月, 2012 4 次提交
    • O
      uprobes/x86: Fix arch_uprobe_disable_step() && UTASK_SSTEP_TRAPPED interaction · d6a00b35
      Oleg Nesterov 提交于
      arch_uprobe_disable_step() should also take UTASK_SSTEP_TRAPPED into
      account. In this case the probed insn was not executed, we need to
      clear X86_EFLAGS_TF if it was set by us and that is all.
      
      Again, this code will look more clean when we move it into
      arch_uprobe_post_xol() and arch_uprobe_abort_xol().
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      d6a00b35
    • O
      uprobes/x86: Xol should send SIGTRAP if X86_EFLAGS_TF was set · 3a4664aa
      Oleg Nesterov 提交于
      arch_uprobe_disable_step() correctly preserves X86_EFLAGS_TF and
      returns to user-mode. But this means the application gets SIGTRAP
      only after the next insn.
      
      This means that UPROBE_CLEAR_TF logic is not really right. _enable
      should only record the state of X86_EFLAGS_TF, and _disable should
      check it separately from UPROBE_FIX_SETF.
      
      Remove arch_uprobe_task->restore_flags, add ->saved_tf instead, and
      change enable/disable accordingly. This assumes that the probed insn
      was not trapped, see the next patch.
      
      arch_uprobe_skip_sstep() logic has the same problem, change it to
      check X86_EFLAGS_TF and send SIGTRAP as well. We will cleanup this
      all after we fold enable/disable_step into pre/post_hol hooks.
      
      Note: send_sig(SIGTRAP) is not actually right, we need send_sigtrap().
      But this needs more changes, handle_swbp() does the same and this is
      equally wrong.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      3a4664aa
    • O
      uprobes/x86: Do not (ab)use TIF_SINGLESTEP/user_*_single_step() for single-stepping · 9bd1190a
      Oleg Nesterov 提交于
      user_enable/disable_single_step() was designed for ptrace, it assumes
      a single user and does unnecessary and wrong things for uprobes. For
      example:
      
      	- arch_uprobe_enable_step() can't trust TIF_SINGLESTEP, an
      	  application itself can set X86_EFLAGS_TF which must be
      	  preserved after arch_uprobe_disable_step().
      
      	- we do not want to set TIF_SINGLESTEP/TIF_FORCED_TF in
      	  arch_uprobe_enable_step(), this only makes sense for ptrace.
      
      	- otoh we leak TIF_SINGLESTEP if arch_uprobe_disable_step()
      	  doesn't do user_disable_single_step(), the application will
      	  be killed after the next syscall.
      
      	- arch_uprobe_enable_step() does access_process_vm() we do
      	  not need/want.
      
      Change arch_uprobe_enable/disable_step() to set/clear X86_EFLAGS_TF
      directly, this is much simpler and more correct. However, we need to
      clear TIF_BLOCKSTEP/DEBUGCTLMSR_BTF before executing the probed insn,
      add set_task_blockstep(false).
      
      Note: with or without this patch, there is another (hopefully minor)
      problem. A probed "pushf" insn can see the wrong X86_EFLAGS_TF set by
      uprobes. Perhaps we should change _disable to update the stack, or
      teach arch_uprobe_skip_sstep() to emulate this insn.
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      9bd1190a
    • S
      uprobes/x86: Implement x86 specific arch_uprobe_*_step · bdc1e472
      Sebastian Andrzej Siewior 提交于
      The arch specific implementation behaves like user_enable_single_step()
      except that it does not disable single stepping if it was already
      enabled by ptrace. This allows the debugger to single step over an
      uprobe. The state of block stepping is not restored. It makes only sense
      together with TF and if that was enabled then the debugger is notified.
      
      Note: this is still not correct. For example, TIF_SINGLESTEP check
      is not right, the application itself can set X86_EFLAGS_TF. And otoh
      we leak TIF_SINGLESTEP (set by enable) if the probed insn is "popf".
      See the next patches, we need the changes in arch/x86/kernel/step.c
      first.
      Signed-off-by: NSebastian Andrzej Siewior <bigeasy@linutronix.de>
      Signed-off-by: NOleg Nesterov <oleg@redhat.com>
      Acked-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      bdc1e472
  8. 08 6月, 2012 1 次提交
  9. 14 3月, 2012 1 次提交
    • S
      uprobes/core: Handle breakpoint and singlestep exceptions · 0326f5a9
      Srikar Dronamraju 提交于
      Uprobes uses exception notifiers to get to know if a thread hit
      a breakpoint or a singlestep exception.
      
      When a thread hits a uprobe or is singlestepping post a uprobe
      hit, the uprobe exception notifier sets its TIF_UPROBE bit,
      which will then be checked on its return to userspace path
      (do_notify_resume() ->uprobe_notify_resume()), where the
      consumers handlers are run (in task context) based on the
      defined filters.
      
      Uprobe hits are thread specific and hence we need to maintain
      information about if a task hit a uprobe, what uprobe was hit,
      the slot where the original instruction was copied for xol so
      that it can be singlestepped with appropriate fixups.
      
      In some cases, special care is needed for instructions that are
      executed out of line (xol). These are architecture specific
      artefacts, such as handling RIP relative instructions on x86_64.
      
      Since the instruction at which the uprobe was inserted is
      executed out of line, architecture specific fixups are added so
      that the thread continues normal execution in the presence of a
      uprobe.
      
      Postpone the signals until we execute the probed insn.
      post_xol() path does a recalc_sigpending() before return to
      user-mode, this ensures the signal can't be lost.
      
      Uprobes relies on DIE_DEBUG notification to notify if a
      singlestep is complete.
      
      Adds x86 specific uprobe exception notifiers and appropriate
      hooks needed to determine a uprobe hit and subsequent post
      processing.
      
      Add requisite x86 fixups for xol for uprobes. Specific cases
      needing fixups include relative jumps (x86_64), calls, etc.
      
      Where possible, we check and skip singlestepping the
      breakpointed instructions. For now we skip single byte as well
      as few multibyte nop instructions. However this can be extended
      to other instructions too.
      
      Credits to Oleg Nesterov for suggestions/patches related to
      signal, breakpoint, singlestep handling code.
      Signed-off-by: NSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      Cc: Linus Torvalds <torvalds@linux-foundation.org>
      Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
      Cc: Jim Keniston <jkenisto@linux.vnet.ibm.com>
      Cc: Linux-mm <linux-mm@kvack.org>
      Cc: Oleg Nesterov <oleg@redhat.com>
      Cc: Andi Kleen <andi@firstfloor.org>
      Cc: Christoph Hellwig <hch@infradead.org>
      Cc: Steven Rostedt <rostedt@goodmis.org>
      Cc: Arnaldo Carvalho de Melo <acme@infradead.org>
      Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
      Cc: Peter Zijlstra <peterz@infradead.org>
      Link: http://lkml.kernel.org/r/20120313180011.29771.89027.sendpatchset@srdronam.in.ibm.com
      [ Performed various cleanliness edits ]
      Signed-off-by: NIngo Molnar <mingo@elte.hu>
      0326f5a9
  10. 13 3月, 2012 2 次提交
  11. 22 2月, 2012 2 次提交