jump_label.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. /*
  2. * jump label x86 support
  3. *
  4. * Copyright (C) 2009 Jason Baron <jbaron@redhat.com>
  5. *
  6. */
  7. #include <linux/jump_label.h>
  8. #include <linux/memory.h>
  9. #include <linux/uaccess.h>
  10. #include <linux/module.h>
  11. #include <linux/list.h>
  12. #include <linux/jhash.h>
  13. #include <linux/cpu.h>
  14. #include <asm/kprobes.h>
  15. #include <asm/alternative.h>
  16. #ifdef HAVE_JUMP_LABEL
  17. union jump_code_union {
  18. char code[JUMP_LABEL_NOP_SIZE];
  19. struct {
  20. char jump;
  21. int offset;
  22. } __attribute__((packed));
  23. };
  24. static void bug_at(unsigned char *ip, int line)
  25. {
  26. /*
  27. * The location is not an op that we were expecting.
  28. * Something went wrong. Crash the box, as something could be
  29. * corrupting the kernel.
  30. */
  31. pr_warning("Unexpected op at %pS [%p] (%02x %02x %02x %02x %02x) %s:%d\n",
  32. ip, ip, ip[0], ip[1], ip[2], ip[3], ip[4], __FILE__, line);
  33. BUG();
  34. }
  35. static void __jump_label_transform(struct jump_entry *entry,
  36. enum jump_label_type type,
  37. void *(*poker)(void *, const void *, size_t),
  38. int init)
  39. {
  40. union jump_code_union code;
  41. const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
  42. if (type == JUMP_LABEL_ENABLE) {
  43. /*
  44. * We are enabling this jump label. If it is not a nop
  45. * then something must have gone wrong.
  46. */
  47. if (unlikely(memcmp((void *)entry->code, ideal_nop, 5) != 0))
  48. bug_at((void *)entry->code, __LINE__);
  49. code.jump = 0xe9;
  50. code.offset = entry->target -
  51. (entry->code + JUMP_LABEL_NOP_SIZE);
  52. } else {
  53. /*
  54. * We are disabling this jump label. If it is not what
  55. * we think it is, then something must have gone wrong.
  56. * If this is the first initialization call, then we
  57. * are converting the default nop to the ideal nop.
  58. */
  59. if (init) {
  60. const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
  61. if (unlikely(memcmp((void *)entry->code, default_nop, 5) != 0))
  62. bug_at((void *)entry->code, __LINE__);
  63. } else {
  64. code.jump = 0xe9;
  65. code.offset = entry->target -
  66. (entry->code + JUMP_LABEL_NOP_SIZE);
  67. if (unlikely(memcmp((void *)entry->code, &code, 5) != 0))
  68. bug_at((void *)entry->code, __LINE__);
  69. }
  70. memcpy(&code, ideal_nops[NOP_ATOMIC5], JUMP_LABEL_NOP_SIZE);
  71. }
  72. /*
  73. * Make text_poke_bp() a default fallback poker.
  74. *
  75. * At the time the change is being done, just ignore whether we
  76. * are doing nop -> jump or jump -> nop transition, and assume
  77. * always nop being the 'currently valid' instruction
  78. *
  79. */
  80. if (poker)
  81. (*poker)((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE);
  82. else
  83. text_poke_bp((void *)entry->code, &code, JUMP_LABEL_NOP_SIZE,
  84. (void *)entry->code + JUMP_LABEL_NOP_SIZE);
  85. }
  86. void arch_jump_label_transform(struct jump_entry *entry,
  87. enum jump_label_type type)
  88. {
  89. get_online_cpus();
  90. mutex_lock(&text_mutex);
  91. __jump_label_transform(entry, type, NULL, 0);
  92. mutex_unlock(&text_mutex);
  93. put_online_cpus();
  94. }
  95. static enum {
  96. JL_STATE_START,
  97. JL_STATE_NO_UPDATE,
  98. JL_STATE_UPDATE,
  99. } jlstate __initdata_or_module = JL_STATE_START;
  100. __init_or_module void arch_jump_label_transform_static(struct jump_entry *entry,
  101. enum jump_label_type type)
  102. {
  103. /*
  104. * This function is called at boot up and when modules are
  105. * first loaded. Check if the default nop, the one that is
  106. * inserted at compile time, is the ideal nop. If it is, then
  107. * we do not need to update the nop, and we can leave it as is.
  108. * If it is not, then we need to update the nop to the ideal nop.
  109. */
  110. if (jlstate == JL_STATE_START) {
  111. const unsigned char default_nop[] = { STATIC_KEY_INIT_NOP };
  112. const unsigned char *ideal_nop = ideal_nops[NOP_ATOMIC5];
  113. if (memcmp(ideal_nop, default_nop, 5) != 0)
  114. jlstate = JL_STATE_UPDATE;
  115. else
  116. jlstate = JL_STATE_NO_UPDATE;
  117. }
  118. if (jlstate == JL_STATE_UPDATE)
  119. __jump_label_transform(entry, type, text_poke_early, 1);
  120. }
  121. #endif