@@ -108,50 +108,6 @@ static const u32 twobyte_is_boostable[256 / 32] = {
108108 /* ----------------------------------------------- */
109109 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
110110};
111- static const u32 onebyte_has_modrm [256 / 32 ] = {
112- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
113- /* ----------------------------------------------- */
114- W (0x00 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ) | /* 00 */
115- W (0x10 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ) , /* 10 */
116- W (0x20 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ) | /* 20 */
117- W (0x30 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 ) , /* 30 */
118- W (0x40 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* 40 */
119- W (0x50 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* 50 */
120- W (0x60 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 , 0 , 0 , 0 , 0 ) | /* 60 */
121- W (0x70 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* 70 */
122- W (0x80 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) | /* 80 */
123- W (0x90 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* 90 */
124- W (0xa0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* a0 */
125- W (0xb0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* b0 */
126- W (0xc0 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* c0 */
127- W (0xd0 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) , /* d0 */
128- W (0xe0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* e0 */
129- W (0xf0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 ) /* f0 */
130- /* ----------------------------------------------- */
131- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
132- };
133- static const u32 twobyte_has_modrm [256 / 32 ] = {
134- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
135- /* ----------------------------------------------- */
136- W (0x00 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 1 ) | /* 0f */
137- W (0x10 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* 1f */
138- W (0x20 , 1 , 1 , 1 , 1 , 1 , 0 , 1 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) | /* 2f */
139- W (0x30 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) , /* 3f */
140- W (0x40 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) | /* 4f */
141- W (0x50 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) , /* 5f */
142- W (0x60 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) | /* 6f */
143- W (0x70 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 ) , /* 7f */
144- W (0x80 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* 8f */
145- W (0x90 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) , /* 9f */
146- W (0xa0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 ) | /* af */
147- W (0xb0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 ) , /* bf */
148- W (0xc0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ) | /* cf */
149- W (0xd0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) , /* df */
150- W (0xe0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 ) | /* ef */
151- W (0xf0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 ) /* ff */
152- /* ----------------------------------------------- */
153- /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
154- };
155111#undef W
156112
157113struct kretprobe_blackpoint kretprobe_blacklist [] = {
@@ -348,68 +304,30 @@ static int __kprobes is_IF_modifier(kprobe_opcode_t *insn)
348304static void __kprobes fix_riprel (struct kprobe * p )
349305{
350306#ifdef CONFIG_X86_64
351- u8 * insn = p -> ainsn .insn ;
352- s64 disp ;
353- int need_modrm ;
354-
355- /* Skip legacy instruction prefixes. */
356- while (1 ) {
357- switch (* insn ) {
358- case 0x66 :
359- case 0x67 :
360- case 0x2e :
361- case 0x3e :
362- case 0x26 :
363- case 0x64 :
364- case 0x65 :
365- case 0x36 :
366- case 0xf0 :
367- case 0xf3 :
368- case 0xf2 :
369- ++ insn ;
370- continue ;
371- }
372- break ;
373- }
307+ struct insn insn ;
308+ kernel_insn_init (& insn , p -> ainsn .insn );
374309
375- /* Skip REX instruction prefix. */
376- if (is_REX_prefix (insn ))
377- ++ insn ;
378-
379- if (* insn == 0x0f ) {
380- /* Two-byte opcode. */
381- ++ insn ;
382- need_modrm = test_bit (* insn ,
383- (unsigned long * )twobyte_has_modrm );
384- } else
385- /* One-byte opcode. */
386- need_modrm = test_bit (* insn ,
387- (unsigned long * )onebyte_has_modrm );
388-
389- if (need_modrm ) {
390- u8 modrm = * ++ insn ;
391- if ((modrm & 0xc7 ) == 0x05 ) {
392- /* %rip+disp32 addressing mode */
393- /* Displacement follows ModRM byte. */
394- ++ insn ;
395- /*
396- * The copied instruction uses the %rip-relative
397- * addressing mode. Adjust the displacement for the
398- * difference between the original location of this
399- * instruction and the location of the copy that will
400- * actually be run. The tricky bit here is making sure
401- * that the sign extension happens correctly in this
402- * calculation, since we need a signed 32-bit result to
403- * be sign-extended to 64 bits when it's added to the
404- * %rip value and yield the same 64-bit result that the
405- * sign-extension of the original signed 32-bit
406- * displacement would have given.
407- */
408- disp = (u8 * ) p -> addr + * ((s32 * ) insn ) -
409- (u8 * ) p -> ainsn .insn ;
410- BUG_ON ((s64 ) (s32 ) disp != disp ); /* Sanity check. */
411- * (s32 * )insn = (s32 ) disp ;
412- }
310+ if (insn_rip_relative (& insn )) {
311+ s64 newdisp ;
312+ u8 * disp ;
313+ insn_get_displacement (& insn );
314+ /*
315+ * The copied instruction uses the %rip-relative addressing
316+ * mode. Adjust the displacement for the difference between
317+ * the original location of this instruction and the location
318+ * of the copy that will actually be run. The tricky bit here
319+ * is making sure that the sign extension happens correctly in
320+ * this calculation, since we need a signed 32-bit result to
321+ * be sign-extended to 64 bits when it's added to the %rip
322+ * value and yield the same 64-bit result that the sign-
323+ * extension of the original signed 32-bit displacement would
324+ * have given.
325+ */
326+ newdisp = (u8 * ) p -> addr + (s64 ) insn .displacement .value -
327+ (u8 * ) p -> ainsn .insn ;
328+ BUG_ON ((s64 ) (s32 ) newdisp != newdisp ); /* Sanity check. */
329+ disp = (u8 * ) p -> ainsn .insn + insn_offset_displacement (& insn );
330+ * (s32 * ) disp = (s32 ) newdisp ;
413331 }
414332#endif
415333}
0 commit comments