From e7cc89a038d08bdcbc7986cb5d8424ec975757b8 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 4 May 2026 15:27:11 -0400 Subject: [PATCH] kernel/x86: Use multibyte NOP constants in altcodepatch. Follows up on a suggestion from the commits mailing list. --- .../kernel/arch/x86/arch_altcodepatch.h | 26 +++++++++---------- .../kernel/arch/x86/arch_altcodepatch.cpp | 18 +++++++++++-- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/headers/private/kernel/arch/x86/arch_altcodepatch.h b/headers/private/kernel/arch/x86/arch_altcodepatch.h index 3fe6334dda..dff0fa189d 100644 --- a/headers/private/kernel/arch/x86/arch_altcodepatch.h +++ b/headers/private/kernel/arch/x86/arch_altcodepatch.h @@ -9,15 +9,15 @@ #include -#define ASM_NOP1 .byte 0x90 -#define ASM_NOP2 .byte 0x66, 0x90 -#define ASM_NOP3 .byte 0x0f, 0x1f, 0x00 -#define ASM_NOP4 .byte 0x0f, 0x1f, 0x40, 0x00 -#define ASM_NOP5 .byte 0x0f, 0x1f, 0x44, 0x00, 0x00 -#define ASM_NOP6 .byte 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 -#define ASM_NOP7 .byte 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 -#define ASM_NOP8 .byte 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 -#define ASM_NOP9 .byte 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 +#define X86_NOP1 0x90 +#define X86_NOP2 0x66, 0x90 +#define X86_NOP3 0x0f, 0x1f, 0x00 +#define X86_NOP4 0x0f, 0x1f, 0x40, 0x00 +#define X86_NOP5 0x0f, 0x1f, 0x44, 0x00, 0x00 +#define X86_NOP6 0x66, 0x0f, 0x1f, 0x44, 0x00, 0x00 +#define X86_NOP7 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 +#define X86_NOP8 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 +#define X86_NOP9 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 #define ALTCODEPATCH_TAG_STAC 1 @@ -38,11 +38,11 @@ .popsection #define ASM_STAC CODEPATCH_START \ - ASM_NOP3 ; \ + .byte X86_NOP3 ; \ CODEPATCH_END(ALTCODEPATCH_TAG_STAC) #define ASM_CLAC CODEPATCH_START \ - ASM_NOP3 ; \ + .byte X86_NOP3 ; \ CODEPATCH_END(ALTCODEPATCH_TAG_CLAC) #else @@ -59,11 +59,11 @@ ".popsection" #define ASM_STAC CODEPATCH_START \ - STRINGIFY(ASM_NOP3) "\n" \ + STRINGIFY(.byte X86_NOP3) "\n" \ CODEPATCH_END(ALTCODEPATCH_TAG_STAC) #define ASM_CLAC CODEPATCH_START \ - STRINGIFY(ASM_NOP3) "\n"\ + STRINGIFY(.byte X86_NOP3) "\n"\ CODEPATCH_END(ALTCODEPATCH_TAG_CLAC) diff --git a/src/system/kernel/arch/x86/arch_altcodepatch.cpp b/src/system/kernel/arch/x86/arch_altcodepatch.cpp index 789c56c361..173d2e186a 100644 --- a/src/system/kernel/arch/x86/arch_altcodepatch.cpp +++ b/src/system/kernel/arch/x86/arch_altcodepatch.cpp @@ -38,16 +38,30 @@ arch_altcodepatch_replace(uint16 tag, void* newcodepatch, size_t length) const uint32 kernelProtection = B_KERNEL_READ_AREA | B_KERNEL_EXECUTE_AREA; set_area_protection(info->text_region.id, kernelProtection | B_KERNEL_WRITE_AREA); + const uint8 kNOPs[9][9] = { + {X86_NOP1}, {X86_NOP2}, {X86_NOP3}, {X86_NOP4}, {X86_NOP5}, {X86_NOP6}, + {X86_NOP7}, {X86_NOP8}, {X86_NOP9} + }; + for (altcodepatch* patch = &altcodepatch_begin; patch < &altcodepatch_end; patch++) { if (patch->tag != tag) continue; - void* address = (void*)(KERNEL_LOAD_BASE + patch->kernel_offset); + uint8* address = (uint8*)(KERNEL_LOAD_BASE + patch->kernel_offset); if (patch->length < length) panic("can't copy patch: new code is too long\n"); memcpy(address, newcodepatch, length); - memset((uint8*)address + length, 0x90 /* nop */, patch->length - length); + address += length; + + size_t remainder = patch->length - length; + while (remainder > 0) { + size_t toWrite = min_c(remainder, 9); + memcpy(address, kNOPs[toWrite - 1], toWrite); + address += toWrite; + remainder -= toWrite; + } + count++; }