<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      通過前面有章調試方法概述的簡單介紹,kprobe其實就是將某個要檢測的指令備份,再替換成int3(x86)或者未定義指令(arm)來觸發異常,再調用對應體系的異常處理函數來執行我們自定義的hook,執行完我們自定義的hook,再將備份的指令放回原來的位置繼續往下執行,下面我們就來看下linux內核版本為5.17.5的arm64的kprobe代碼架構,首先看下probe這個結構體

      struct kprobe {
          struct hlist_node hlist;
      
          /* list of kprobes for multi-handler support */
          struct list_head list;
      
          /*count the number of times this probe was temporarily disarmed */
          unsigned long nmissed;
      
          /* location of the probe point */
          kprobe_opcode_t *addr;
      
          /* Allow user to indicate symbol name of the probe point */
          const char *symbol_name;
      
          /* Offset into the symbol */
          unsigned int offset;
      
          /* Called before addr is executed. */
          kprobe_pre_handler_t pre_handler;
      
          /* Called after addr is executed, unless... */
          kprobe_post_handler_t post_handler;
      
          /* Saved opcode (which has been replaced with breakpoint) */
          kprobe_opcode_t opcode;
      
          /* copy of the original instruction */
          struct arch_specific_insn ainsn;
      
          /*
           * Indicates various status flags.
           * Protected by kprobe_mutex after this kprobe is registered.
           */
          u32 flags;
      };

      替換成未定義指令后,就會觸發的未定義指令異常處理函數

      void do_undefinstr(struct pt_regs *regs)
      {
          /* check for AArch32 breakpoint instructions */
          if (!aarch32_break_handler(regs))
              return;
      
          if (call_undef_hook(regs) == 0)
              return;
      
          BUG_ON(!user_mode(regs));
          force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
      }

      里面的會調用call_undef_hook,這個函數的參數就是記錄在堆棧中的寄存器組,下面一個函數我們也可以看到用到了程序計數器pc

      static int call_undef_hook(struct pt_regs *regs)
      {
          struct undef_hook *hook;
          unsigned long flags;
          u32 instr;
          int (*fn)(struct pt_regs *regs, u32 instr) = NULL;
          unsigned long pc = instruction_pointer(regs);
      
          if (!user_mode(regs)) {
              __le32 instr_le;
              if (get_kernel_nofault(instr_le, (__le32 *)pc))
                  goto exit;
              instr = le32_to_cpu(instr_le);
          } else if (compat_thumb_mode(regs)) {
              /* 16-bit Thumb instruction */
              __le16 instr_le;
              if (get_user(instr_le, (__le16 __user *)pc))
                  goto exit;
              instr = le16_to_cpu(instr_le);
              if (aarch32_insn_is_wide(instr)) {
                  u32 instr2;
      
                  if (get_user(instr_le, (__le16 __user *)(pc + 2)))
                      goto exit;
                  instr2 = le16_to_cpu(instr_le);
                  instr = (instr << 16) | instr2;
              }
          } else {
              /* 32-bit ARM instruction */
              __le32 instr_le;
              if (get_user(instr_le, (__le32 __user *)pc))
                  goto exit;
              instr = le32_to_cpu(instr_le);
          }
      
          raw_spin_lock_irqsave(&undef_lock, flags);
          list_for_each_entry(hook, &undef_hook, node)
              if ((instr & hook->instr_mask) == hook->instr_val &&
                  (regs->pstate & hook->pstate_mask) == hook->pstate_val)
                  fn = hook->fn;
      
          raw_spin_unlock_irqrestore(&undef_lock, flags);
      exit:
          return fn ? fn(regs, instr) : 1;
      }

      從最后幾行我們看到他會便利整個undef_hook,通過對比instr_mask等找到對應的undef_hook的fn:其實也就是 kprobe_trap_handler

       

      在系統初始化kprobe子系統時

      static int __init init_kprobes(void)
      {
          int i, err = 0;
      
          /* FIXME allocate the probe table, currently defined statically */
          /* initialize all list heads */
          for (i = 0; i < KPROBE_TABLE_SIZE; i++)
              INIT_HLIST_HEAD(&kprobe_table[i]);
      
          err = populate_kprobe_blacklist(__start_kprobe_blacklist,
                          __stop_kprobe_blacklist);
          if (err)
              pr_err("Failed to populate blacklist (error %d), kprobes not restricted, be careful using them!\n", err);
      
          if (kretprobe_blacklist_size) {
              /* lookup the function address from its name */
              for (i = 0; kretprobe_blacklist[i].name != NULL; i++) {
                  kretprobe_blacklist[i].addr =
                      kprobe_lookup_name(kretprobe_blacklist[i].name, 0);
                  if (!kretprobe_blacklist[i].addr)
                      pr_err("Failed to lookup symbol '%s' for kretprobe blacklist. Maybe the target function is removed or renamed.\n",
                             kretprobe_blacklist[i].name);
              }
          }
      
          /* By default, kprobes are armed */
          kprobes_all_disarmed = false;
      
      #if defined(CONFIG_OPTPROBES) && defined(__ARCH_WANT_KPROBES_INSN_SLOT)
          /* Init 'kprobe_optinsn_slots' for allocation */
          kprobe_optinsn_slots.insn_size = MAX_OPTINSN_SIZE;
      #endif
      
          err = arch_init_kprobes();
          if (!err)
              err = register_die_notifier(&kprobe_exceptions_nb);
          if (!err)
              err = register_module_notifier(&kprobe_module_nb);
      
          kprobes_initialized = (err == 0);
          kprobe_sysctls_init();
          return err;
      }
      early_initcall(init_kprobes);

      會調用arch_init_kprobes來注冊體系架構的kprobe的hook

      static struct undef_hook kprobes_arm_break_hook = {
          .instr_mask    = 0x0fffffff,
          .instr_val    = KPROBE_ARM_BREAKPOINT_INSTRUCTION,
          .cpsr_mask    = MODE_MASK,
          .cpsr_val    = SVC_MODE,
          .fn        = kprobe_trap_handler,
      };
      
      #endif /* !CONFIG_THUMB2_KERNEL */
      
      int __init arch_init_kprobes(void)
      {
          arm_probes_decode_init();
      #ifdef CONFIG_THUMB2_KERNEL
          register_undef_hook(&kprobes_thumb16_break_hook);
          register_undef_hook(&kprobes_thumb32_break_hook);
      #else
          register_undef_hook(&kprobes_arm_break_hook);
      #endif
          return 0;
      }
      kprobe_trap_handler會調用kprobe_handler
      void __kprobes kprobe_handler(struct pt_regs *regs)
      {
          struct kprobe *p, *cur;
          struct kprobe_ctlblk *kcb;
      
          kcb = get_kprobe_ctlblk();
          cur = kprobe_running();
      
      #ifdef CONFIG_THUMB2_KERNEL
          /*
           * First look for a probe which was registered using an address with
           * bit 0 set, this is the usual situation for pointers to Thumb code.
           * If not found, fallback to looking for one with bit 0 clear.
           */
          p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1));
          if (!p)
              p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
      
      #else /* ! CONFIG_THUMB2_KERNEL */
          p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc);
      #endif
      
          if (p) {
              if (!p->ainsn.insn_check_cc(regs->ARM_cpsr)) {
                  /*
                   * Probe hit but conditional execution check failed,
                   * so just skip the instruction and continue as if
                   * nothing had happened.
                   * In this case, we can skip recursing check too.
                   */
                  singlestep_skip(p, regs);
              } else if (cur) {
                  /* Kprobe is pending, so we're recursing. */
                  switch (kcb->kprobe_status) {
                  case KPROBE_HIT_ACTIVE:
                  case KPROBE_HIT_SSDONE:
                  case KPROBE_HIT_SS:
                      /* A pre- or post-handler probe got us here. */
                      kprobes_inc_nmissed_count(p);
                      save_previous_kprobe(kcb);
                      set_current_kprobe(p);
                      kcb->kprobe_status = KPROBE_REENTER;
                      singlestep(p, regs, kcb);
                      restore_previous_kprobe(kcb);
                      break;
                  case KPROBE_REENTER:
                      /* A nested probe was hit in FIQ, it is a BUG */
                      pr_warn("Failed to recover from reentered kprobes.\n");
                      dump_kprobe(p);
                      fallthrough;
                  default:
                      /* impossible cases */
                      BUG();
                  }
              } else {
                  /* Probe hit and conditional execution check ok. */
                  set_current_kprobe(p);
                  kcb->kprobe_status = KPROBE_HIT_ACTIVE;
      
                  /*
                   * If we have no pre-handler or it returned 0, we
                   * continue with normal processing. If we have a
                   * pre-handler and it returned non-zero, it will
                   * modify the execution path and no need to single
                   * stepping. Let's just reset current kprobe and exit.
                   */
                  if (!p->pre_handler || !p->pre_handler(p, regs)) {
                      kcb->kprobe_status = KPROBE_HIT_SS;
                      singlestep(p, regs, kcb);
                      if (p->post_handler) {
                          kcb->kprobe_status = KPROBE_HIT_SSDONE;
                          p->post_handler(p, regs, 0);
                      }
                  }
                  reset_current_kprobe();
              }
          } else {
              /*
               * The probe was removed and a race is in progress.
               * There is nothing we can do about it.  Let's restart
               * the instruction.  By the time we can restart, the
               * real instruction will be there.
               */
          }
      }
      
      

       

      上面這個函數我們可以看到,會調用kprobe的pre_handler和post_handler,這兩個函數被我們實現好,裝填進kprobe,并用register_kprobe注冊到kprobe子系統;當注冊好之后,系統執行到這個位置就會陷入異常,異常處理函數就會來處理我們的kprobe

      int register_kprobe(struct kprobe *p)
      {
          int ret;
          struct kprobe *old_p;
          struct module *probed_mod;
          kprobe_opcode_t *addr;
      
          /* Adjust probe address from symbol */
          addr = kprobe_addr(p);
          if (IS_ERR(addr))
              return PTR_ERR(addr);
          p->addr = addr;
      
          ret = warn_kprobe_rereg(p);
          if (ret)
              return ret;
      
          /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
          p->flags &= KPROBE_FLAG_DISABLED;
          p->nmissed = 0;
          INIT_LIST_HEAD(&p->list);
      
          ret = check_kprobe_address_safe(p, &probed_mod);
          if (ret)
              return ret;
      
          mutex_lock(&kprobe_mutex);
      
          old_p = get_kprobe(p->addr);
          if (old_p) {
              /* Since this may unoptimize 'old_p', locking 'text_mutex'. */
              ret = register_aggr_kprobe(old_p, p);
              goto out;
          }
      
          cpus_read_lock();
          /* Prevent text modification */
          mutex_lock(&text_mutex);
          ret = prepare_kprobe(p);
          mutex_unlock(&text_mutex);
          cpus_read_unlock();
          if (ret)
              goto out;
      
          INIT_HLIST_NODE(&p->hlist);
          hlist_add_head_rcu(&p->hlist,
                     &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
      
          if (!kprobes_all_disarmed && !kprobe_disabled(p)) {
              ret = arm_kprobe(p);
              if (ret) {
                  hlist_del_rcu(&p->hlist);
                  synchronize_rcu();
                  goto out;
              }
          }
      
          /* Try to optimize kprobe */
          try_to_optimize_kprobe(p);
      out:
          mutex_unlock(&kprobe_mutex);
      
          if (probed_mod)
              module_put(probed_mod);
      
          return ret;
      }

       

       
      posted on 2022-05-01 23:44  lzd626  閱讀(326)  評論(0)    收藏  舉報



      主站蜘蛛池模板: 人妻va精品va欧美va| 亚洲午夜成人精品电影在线观看| 国厂精品114福利电影免费| 国产精品自在线拍国产手青青机版| 日韩一区二区三区无码a片| 成人精品老熟妇一区二区| 欧美一区二区三区性视频| 亚洲欧美日韩精品久久亚洲区 | 骚虎三级在线免费播放| 99久久国产精品无码| 无套内谢少妇一二三四| 亚洲成在人天堂一区二区| 亚洲一区二区中文av| 万山特区| 精品嫩模福利一区二区蜜臀| 久热综合在线亚洲精品| 浙江省| 欧美人禽zozo动人物杂交| 欧美巨大极度另类| 亚洲综合无码明星蕉在线视频| 亚洲中文字幕无码中字| 一日本道伊人久久综合影| 成年无码av片在线蜜芽| 国产成人无码精品亚洲| 国产精品爱久久久久久久电影| 亚洲色一色噜一噜噜噜| 日韩黄色av一区二区三区| 亚洲精品不卡无码福利在线观看| 免费现黄频在线观看国产| 成人啪啪高潮不断观看| 国产色悠悠在线免费观看| 蜜臀av一区二区三区日韩| 国产综合久久亚洲综合| 洪泽县| 无码国产一区二区三区四区| 九九热在线免费视频精品| 悠悠人体艺术视频在线播放| 伊人精品成人久久综合97| 亚洲VA成无码人在线观看天堂| 中文字幕久久国产精品| 九九热在线精品视频99|