mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 16:53:54 +08:00
s390/jump label: add sanity checks
Add sanity checks to verify that only expected code will be replaced. If the code patterns do not match print the code patterns and panic, since something went terribly wrong. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
db1177ee62
commit
5c6497c50f
@ -22,31 +22,59 @@ struct insn_args {
|
||||
enum jump_label_type type;
|
||||
};
|
||||
|
||||
static void __jump_label_transform(struct jump_entry *entry,
|
||||
enum jump_label_type type)
|
||||
static void jump_label_make_nop(struct jump_entry *entry, struct insn *insn)
|
||||
{
|
||||
struct insn insn;
|
||||
int rc;
|
||||
/* brcl 0,0 */
|
||||
insn->opcode = 0xc004;
|
||||
insn->offset = 0;
|
||||
}
|
||||
|
||||
static void jump_label_make_branch(struct jump_entry *entry, struct insn *insn)
|
||||
{
|
||||
/* brcl 15,offset */
|
||||
insn->opcode = 0xc0f4;
|
||||
insn->offset = (entry->target - entry->code) >> 1;
|
||||
}
|
||||
|
||||
static void jump_label_bug(struct jump_entry *entry, struct insn *insn)
|
||||
{
|
||||
unsigned char *ipc = (unsigned char *)entry->code;
|
||||
unsigned char *ipe = (unsigned char *)insn;
|
||||
|
||||
pr_emerg("Jump label code mismatch at %pS [%p]\n", ipc, ipc);
|
||||
pr_emerg("Found: %02x %02x %02x %02x %02x %02x\n",
|
||||
ipc[0], ipc[1], ipc[2], ipc[3], ipc[4], ipc[5]);
|
||||
pr_emerg("Expected: %02x %02x %02x %02x %02x %02x\n",
|
||||
ipe[0], ipe[1], ipe[2], ipe[3], ipe[4], ipe[5]);
|
||||
panic("Corrupted kernel text");
|
||||
}
|
||||
|
||||
static void __jump_label_transform(struct jump_entry *entry,
|
||||
enum jump_label_type type,
|
||||
int init)
|
||||
{
|
||||
struct insn old, new;
|
||||
|
||||
if (type == JUMP_LABEL_ENABLE) {
|
||||
/* brcl 15,offset */
|
||||
insn.opcode = 0xc0f4;
|
||||
insn.offset = (entry->target - entry->code) >> 1;
|
||||
jump_label_make_nop(entry, &old);
|
||||
jump_label_make_branch(entry, &new);
|
||||
} else {
|
||||
/* brcl 0,0 */
|
||||
insn.opcode = 0xc004;
|
||||
insn.offset = 0;
|
||||
if (init)
|
||||
jump_label_make_nop(entry, &old);
|
||||
else
|
||||
jump_label_make_branch(entry, &old);
|
||||
jump_label_make_nop(entry, &new);
|
||||
}
|
||||
|
||||
rc = probe_kernel_write((void *)entry->code, &insn, JUMP_LABEL_NOP_SIZE);
|
||||
WARN_ON_ONCE(rc < 0);
|
||||
if (memcmp((void *)entry->code, &old, sizeof(old)))
|
||||
jump_label_bug(entry, &old);
|
||||
probe_kernel_write((void *)entry->code, &new, sizeof(new));
|
||||
}
|
||||
|
||||
static int __sm_arch_jump_label_transform(void *data)
|
||||
{
|
||||
struct insn_args *args = data;
|
||||
|
||||
__jump_label_transform(args->entry, args->type);
|
||||
__jump_label_transform(args->entry, args->type, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -64,7 +92,7 @@ void arch_jump_label_transform(struct jump_entry *entry,
|
||||
void arch_jump_label_transform_static(struct jump_entry *entry,
|
||||
enum jump_label_type type)
|
||||
{
|
||||
__jump_label_transform(entry, type);
|
||||
__jump_label_transform(entry, type, 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user