Skip to content

Commit 6ce4add

Browse files
authored
Merge pull request #9513 from richwelchaws/master_detect_memory_patch
memory_patcher: Add ability to detect patched memory
2 parents 291cc18 + 4383883 commit 6ce4add

File tree

4 files changed

+121
-12
lines changed

4 files changed

+121
-12
lines changed

opal/mca/memory/patcher/memory_patcher_component.c

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -607,31 +607,31 @@ static int patcher_open(void)
607607
rc = opal_patcher->patch_symbol("mmap", (uintptr_t) intercept_mmap,
608608
(uintptr_t *) &original_mmap);
609609
if (OPAL_SUCCESS != rc) {
610-
return rc;
610+
goto err_patching;
611611
}
612612
#endif
613613

614614
#if defined(SYS_munmap)
615615
rc = opal_patcher->patch_symbol("munmap", (uintptr_t) intercept_munmap,
616616
(uintptr_t *) &original_munmap);
617617
if (OPAL_SUCCESS != rc) {
618-
return rc;
618+
goto err_patching;
619619
}
620620
#endif
621621

622622
#if defined(SYS_mremap)
623623
rc = opal_patcher->patch_symbol("mremap", (uintptr_t) intercept_mremap,
624624
(uintptr_t *) &original_mremap);
625625
if (OPAL_SUCCESS != rc) {
626-
return rc;
626+
goto err_patching;
627627
}
628628
#endif
629629

630630
#if defined(SYS_madvise)
631631
rc = opal_patcher->patch_symbol("madvise", (uintptr_t) intercept_madvise,
632632
(uintptr_t *) &original_madvise);
633633
if (OPAL_SUCCESS != rc) {
634-
return rc;
634+
goto err_patching;
635635
}
636636
#endif
637637

@@ -640,7 +640,7 @@ static int patcher_open(void)
640640
rc = opal_patcher->patch_symbol("shmat", (uintptr_t) intercept_shmat,
641641
(uintptr_t *) &original_shmat);
642642
if (OPAL_SUCCESS != rc) {
643-
return rc;
643+
goto err_patching;
644644
}
645645
# endif
646646
#endif
@@ -650,7 +650,7 @@ static int patcher_open(void)
650650
rc = opal_patcher->patch_symbol("shmdt", (uintptr_t) intercept_shmdt,
651651
(uintptr_t *) &original_shmdt);
652652
if (OPAL_SUCCESS != rc) {
653-
return rc;
653+
goto err_patching;
654654
}
655655
# endif
656656
#endif
@@ -659,6 +659,18 @@ static int patcher_open(void)
659659
rc = opal_patcher->patch_symbol("brk", (uintptr_t) intercept_brk, (uintptr_t *) &original_brk);
660660
#endif
661661

662+
if (OPAL_SUCCESS != rc) {
663+
goto err_patching;
664+
}
665+
666+
return OPAL_SUCCESS;
667+
668+
err_patching:
669+
/* In the case we had a problem patching, set this flag to 0 so we do not
670+
directly return OPAL_SUCCESS if we call patcher_open() again. */
671+
was_executed_already = 0;
672+
opal_patcher_base_restore_all();
673+
662674
return rc;
663675
}
664676

opal/mca/patcher/base/base.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ OBJ_CLASS_DECLARATION(mca_patcher_base_patch_t);
6363
*/
6464
OPAL_DECLSPEC extern mca_base_framework_t opal_patcher_base_framework;
6565
OPAL_DECLSPEC int opal_patcher_base_select(void);
66+
OPAL_DECLSPEC int opal_patcher_base_restore_all(void);
6667
OPAL_DECLSPEC int mca_patcher_base_patch_hook(mca_patcher_base_module_t *module, uintptr_t hook);
6768
OPAL_DECLSPEC void mca_base_patcher_patch_apply_binary(mca_patcher_base_patch_t *patch);
6869

opal/mca/patcher/base/patcher_base_frame.c

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,17 +54,35 @@ int opal_patcher_base_select(void)
5454
return OPAL_SUCCESS;
5555
}
5656

57-
static int opal_patcher_base_close(void)
57+
int opal_patcher_base_restore_all(void)
5858
{
59+
mca_patcher_base_patch_t *patch, *patch_next;
60+
5961
if (opal_patcher == &empty_module) {
6062
return OPAL_SUCCESS;
6163
}
6264

63-
mca_patcher_base_patch_t *patch;
64-
OPAL_LIST_FOREACH_REV (patch, &opal_patcher->patch_list, mca_patcher_base_patch_t) {
65-
patch->patch_restore(patch);
65+
opal_mutex_lock(&opal_patcher->patch_list_mutex);
66+
67+
OPAL_LIST_FOREACH_SAFE_REV(patch, patch_next, &opal_patcher->patch_list, mca_patcher_base_patch_t) {
68+
patch->patch_restore (patch);
69+
opal_list_remove_item(&opal_patcher->patch_list, &patch->super);
70+
OBJ_RELEASE(patch);
71+
}
72+
73+
opal_mutex_unlock(&opal_patcher->patch_list_mutex);
74+
75+
return OPAL_SUCCESS;
76+
}
77+
78+
static int opal_patcher_base_close(void)
79+
{
80+
if (opal_patcher == &empty_module) {
81+
return OPAL_SUCCESS;
6682
}
6783

84+
opal_patcher_base_restore_all();
85+
6886
OPAL_LIST_DESTRUCT(&opal_patcher->patch_list);
6987
OBJ_DESTRUCT(&opal_patcher->patch_list_mutex);
7088

opal/mca/patcher/overwrite/patcher_overwrite_module.c

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
5757
return OPAL_SUCCESS;
5858
}
5959

60-
/* end of #if defined(__i386__) || defined(__x86_64__) || defined(__ia64__) */
60+
/* end of #if defined(__i386__) || defined(__x86_64__) */
6161
// ------------------------------------------------- PPC equivalent:
6262
#elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
6363

@@ -214,6 +214,78 @@ static int mca_patcher_overwrite_apply_patch(mca_patcher_base_patch_t *patch)
214214

215215
#endif
216216

217+
/*
218+
* The logic in this function for each platform is based on code from
219+
* mca_patcher_overwrite_apply_patch(). There are 2 general approaches:
220+
* 1: Directly check constant instructions (ignoring addresses as parameters)
221+
* 2: Generate a bit mask by passing min and max values to underlying helper
222+
* functions and negate the XOR'ed results. These results can be used to
223+
* mask off transient values (like addresess) and non-instruction values
224+
* (like register contents). Once the masks are applied, the results are
225+
* compared against the min values directly to check for equality. If equal,
226+
* we consider the memory to be previously patched.
227+
*/
228+
static bool mca_patcher_is_function_patched(unsigned char *target)
229+
{
230+
231+
#if (OPAL_ASSEMBLY_ARCH == OPAL_IA32)
232+
return (*(unsigned char *)target == 0xe9);
233+
#elif (OPAL_ASSEMBLY_ARCH == OPAL_X86_64)
234+
return (
235+
(*(unsigned short*)(target + 0) == 0xbb49) &&
236+
(*(unsigned char* )(target +10) == 0x41 ) &&
237+
(*(unsigned char* )(target +11) == 0xff ) &&
238+
(*(unsigned char* )(target +12) == 0xe3 )
239+
);
240+
#elif (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32 ) || (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC64)
241+
const unsigned int gr_max = 0xF; //11 is used in our patching code, but is the max 4 or 5 bits?
242+
const unsigned int addr_max = 0xFFFF;
243+
unsigned int addis_base = addis( 0, 0, 0);
244+
unsigned int addis_mask = ~(addis_base ^ addis( gr_max, 0, addr_max));
245+
unsigned int ori_base = ori( 0, 0, 0);
246+
unsigned int ori_mask = ~( ori_base ^ ori( gr_max, gr_max, addr_max));
247+
unsigned int mtspr_base = mtspr( 9, 0); // 9 = CTR
248+
unsigned int mtspr_mask = ~(mtspr_base ^ mtspr( 9, gr_max));
249+
unsigned int bcctr_base = bcctr(20, 0, 0); // 20 = always
250+
unsigned int bcctr_mask = ~(bcctr_base ^ bcctr(20, 0, 0));
251+
#if (OPAL_ASSEMBLY_ARCH == OPAL_POWERPC32)
252+
253+
return (
254+
((*(unsigned int *) (target + 0 )) & addis_mask) == addis_base &&
255+
((*(unsigned int *) (target + 4 )) & ori_mask) == ori_base &&
256+
((*(unsigned int *) (target + 8 )) & mtspr_mask) == mtspr_base &&
257+
((*(unsigned int *) (target + 12)) & bcctr_mask) == bcctr_base
258+
);
259+
#else
260+
unsigned int rldicr_base = rldicr( 0, 0, 32, 31);
261+
unsigned int rldicr_mask = ~(rldicr_base ^ rldicr( gr_max, gr_max, 32, 31));
262+
unsigned int oris_base = oris( 0, 0, 0);
263+
unsigned int oris_mask = ~(oris_base ^ oris( gr_max, gr_max, addr_max));
264+
265+
return (
266+
((*(unsigned int *) (target + 0 )) & addis_mask) == addis_base &&
267+
((*(unsigned int *) (target + 4 )) & ori_mask) == ori_base &&
268+
((*(unsigned int *) (target + 8 )) & rldicr_mask) == rldicr_base &&
269+
((*(unsigned int *) (target + 12)) & oris_mask) == oris_base &&
270+
((*(unsigned int *) (target + 16)) & ori_mask) == ori_base &&
271+
((*(unsigned int *) (target + 20)) & mtspr_mask) == mtspr_base &&
272+
((*(unsigned int *) (target + 24)) & bcctr_mask) == bcctr_base
273+
);
274+
#endif
275+
#elif defined(__aarch64__)
276+
uint32_t mov_mask=~((0xFFFF << 5) | 0x1F);
277+
uint32_t br_mask=~(0x1F << 5);
278+
279+
return (
280+
((*(uint32_t *) (target + 0)) & mov_mask) == mov(0, 3, 0) &&
281+
((*(uint32_t *) (target + 4)) & mov_mask) == movk(0, 2, 0) &&
282+
((*(uint32_t *) (target + 8)) & mov_mask) == movk(0, 1, 0) &&
283+
((*(uint32_t *) (target + 12)) & mov_mask) == movk(0, 0, 0) &&
284+
((*(uint32_t *) (target + 16)) & br_mask) == br(0)
285+
);
286+
#endif
287+
}
288+
217289
static int mca_patcher_overwrite_patch_address(uintptr_t sys_addr, uintptr_t hook_addr)
218290
{
219291
mca_patcher_base_patch_t *patch;
@@ -268,7 +340,13 @@ static int mca_patcher_overwrite_patch_symbol(const char *func_symbol_name, uint
268340
*func_old_addr = 0;
269341
}
270342

271-
return mca_patcher_overwrite_patch_address(old_addr, func_new_addr);
343+
if (mca_patcher_is_function_patched((unsigned char*)old_addr)) {
344+
opal_output_verbose(10, 0, "function %s is already patched; stopping further patching\n",
345+
func_symbol_name);
346+
return OPAL_ERR_RESOURCE_BUSY;
347+
} else {
348+
return mca_patcher_overwrite_patch_address(old_addr, func_new_addr);
349+
}
272350
}
273351

274352
mca_patcher_base_module_t mca_patcher_overwrite_module = {

0 commit comments

Comments
 (0)