1. 07 Oct, 2012 7 commits
    • Oleg Nesterov's avatar
      uprobes: Fix the racy uprobe->flags manipulation · 71434f2f
      Oleg Nesterov authored
      Multiple threads can manipulate uprobe->flags, this is obviously
      unsafe. For example mmap can set UPROBE_COPY_INSN while register
      tries to set UPROBE_RUN_HANDLER, the latter can also race with
      can_skip_sstep() which clears UPROBE_SKIP_SSTEP.
      
      Change this code to use bitops.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      71434f2f
    • Oleg Nesterov's avatar
      uprobes: Fix prepare_uprobe() race with itself · 4710f05f
      Oleg Nesterov authored
      install_breakpoint() is called under mm->mmap_sem, this protects
      set_swbp() but not prepare_uprobe(). Two or more different tasks
      can call install_breakpoint()->prepare_uprobe() at the same time,
      this leads to numerous problems if UPROBE_COPY_INSN is not set.
      
      Just for example, the second copy_insn() can corrupt the already
      analyzed/fixuped uprobe->arch.insn and race with handle_swbp().
      
      This patch simply adds uprobe->copy_mutex to serialize this code.
      We could probably reuse ->consumer_rwsem, but this would mean that
      consumer->handler() can not use mm->mmap_sem, not good.
      
      Note: this is another temporary ugly hack until we move this logic
      into uprobe_register().
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      4710f05f
    • Oleg Nesterov's avatar
      uprobes: Introduce prepare_uprobe() · cb9a19fe
      Oleg Nesterov authored
      Preparation. Extract the copy_insn/arch_uprobe_analyze_insn code
      from install_breakpoint() into the new helper, prepare_uprobe().
      
      And move uprobe->flags defines from uprobes.h to uprobes.c, nobody
      else can use them anyway.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      cb9a19fe
    • Oleg Nesterov's avatar
      uprobes: Fix handle_swbp() vs unregister() + register() race · 142b18dd
      Oleg Nesterov authored
      Strictly speaking this race was added by me in 56bb4cf6. However
      I think that this bug is just another indication that we should
      move copy_insn/uprobe_analyze_insn code from install_breakpoint()
      to uprobe_register(), there are a lot of other reasons for that.
      Until then, add a hack to close the race.
      
      A task can hit uprobe U1, but before it calls find_uprobe() this
      uprobe can be unregistered *AND* another uprobe U2 can be added to
      uprobes_tree at the same inode/offset. In this case handle_swbp()
      will use the not-fully-initialized U2, in particular its arch.insn
      for xol.
      
      Add the additional !UPROBE_COPY_INSN check into handle_swbp(),
      if this flag is not set we simply restart as if the new uprobe was
      not inserted yet. This is not very nice, we need barriers, but we
      will remove this hack when we change uprobe_register().
      
      Note: with or without this patch install_breakpoint() can race with
      itself, yet another reson to kill UPROBE_COPY_INSN altogether. And
      even the usage of uprobe->flags is not safe. See the next patches.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      142b18dd
    • Oleg Nesterov's avatar
      uprobes: Do not delete uprobe if uprobe_unregister() fails · 076a365b
      Oleg Nesterov authored
      delete_uprobe() must not be called if register_for_each_vma(false)
      fails to remove all breakpoints, __uprobe_unregister() is correct.
      The problem is that register_for_each_vma(false) always returns 0
      and thus this logic does not work.
      
      1. Change verify_opcode() to return 0 rather than -EINVAL when
         unregister detects the !is_swbp insn, we can treat this case
         as success and currently unregister paths ignore the error
         code anyway.
      
      2. Change remove_breakpoint() to propagate the error code from
         write_opcode().
      
      3. Change register_for_each_vma(is_register => false) to remove
         as much breakpoints as possible but return non-zero if
         remove_breakpoint() fails at least once.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      076a365b
    • Oleg Nesterov's avatar
      uprobes: Don't return success if alloc_uprobe() fails · a5f658b7
      Oleg Nesterov authored
      If alloc_uprobe() fails uprobe_register() should return ENOMEM, not 0.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      a5f658b7
    • Oleg Nesterov's avatar
      uprobes/x86: Only rep+nop can be emulated correctly · b64b9c93
      Oleg Nesterov authored
      __skip_sstep() correctly detects the "nontrivial" nop insns,
      but since it doesn't update regs->ip we can not really skip
      "0x0f 0x1f | 0x0f 0x19 | 0x87 0xc0", the probed application
      is killed by SIGILL'ed handle_swbp().
      
      Remove these additional checks. If we want to implement this
      correctly we need to know the full insn length to update ->ip.
      
      rep* + nop is fine even without updating ->ip.
      Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
      Acked-by: default avatarSrikar Dronamraju <srikar@linux.vnet.ibm.com>
      b64b9c93
  2. 29 Sep, 2012 12 commits
  3. 28 Sep, 2012 1 commit
  4. 27 Sep, 2012 3 commits
  5. 26 Sep, 2012 15 commits
  6. 25 Sep, 2012 2 commits