X-Git-Url: https://glassweightruler.freedombox.rocks/gitweb/Ventoy.git/blobdiff_plain/3f65f0ef03e4aebcd14f233ca808a4f894657802..44fb9f456480f7d3feb0b35a32d08ae32a713883:/DMPATCH/dmpatch.c diff --git a/DMPATCH/dmpatch.c b/DMPATCH/dmpatch.c index e4ed6f9..f91648f 100644 --- a/DMPATCH/dmpatch.c +++ b/DMPATCH/dmpatch.c @@ -56,6 +56,8 @@ typedef struct ko_param unsigned long kv_minor; unsigned long blkdev_get_addr; unsigned long blkdev_put_addr; + unsigned long bdev_open_addr; + unsigned long kv_subminor; unsigned long padding[1]; }ko_param; @@ -157,6 +159,26 @@ static unsigned int g_claim_ptr = 0; static unsigned char *g_get_patch[MAX_PATCH] = { NULL }; static unsigned char *g_put_patch[MAX_PATCH] = { NULL }; +static int notrace dmpatch_kv_above(unsigned long Major, unsigned long Minor, unsigned long SubMinor) +{ + if (g_ko_param.kv_major != Major) + { + return (g_ko_param.kv_major > Major) ? 1 : 0; + } + + if (g_ko_param.kv_minor != Minor) + { + return (g_ko_param.kv_minor > Minor) ? 1 : 0; + } + + if (g_ko_param.kv_subminor != SubMinor) + { + return (g_ko_param.kv_subminor > SubMinor) ? 1 : 0; + } + + return 1; +} + static void notrace dmpatch_restore_code(int bytes, unsigned char *opCode, unsigned int code) { unsigned long align; @@ -246,7 +268,7 @@ static int notrace dmpatch_replace_code return 0; } -static unsigned long dmpatch_find_call_offset(unsigned long addr, unsigned long size, unsigned long func) +static unsigned long notrace dmpatch_find_call_offset(unsigned long addr, unsigned long size, unsigned long func) { unsigned long i = 0; unsigned long dest; @@ -275,18 +297,15 @@ static unsigned long dmpatch_find_call_offset(unsigned long addr, unsigned long return 0; } -static unsigned int dmpatch_patch_claim_ptr(void) +static unsigned int notrace dmpatch_patch_claim_ptr(void) { unsigned long i = 0; unsigned long t = 0; - unsigned long offset1; - unsigned long offset2; - unsigned long align; + unsigned long offset1 = 0; + unsigned long offset2 = 0; + unsigned long align = 0; unsigned char *opCode = NULL; - vdebug("Get addr: 0x%lx %lu 0x%lx\n", g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.blkdev_get_addr); - vdebug("Put addr: 0x%lx %lu 0x%lx\n", g_ko_param.sym_put_addr, g_ko_param.sym_put_size, g_ko_param.blkdev_put_addr); - opCode = (unsigned char *)g_ko_param.sym_get_addr; for (i = 0; i < 4; i++) { @@ -297,13 +316,30 @@ static unsigned int dmpatch_patch_claim_ptr(void) opCode[i + 12], opCode[i + 13], opCode[i + 14], opCode[i + 15]); } - offset1 = dmpatch_find_call_offset(g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.blkdev_get_addr); - offset2 = dmpatch_find_call_offset(g_ko_param.sym_put_addr, g_ko_param.sym_put_size, g_ko_param.blkdev_put_addr); - if (offset1 == 0 || offset2 == 0) + if (dmpatch_kv_above(6, 7, 0)) /* >= 6.7 kernel */ { - vdebug("call blkdev_get or blkdev_put Not found, %lu %lu\n", offset1, offset2); - return 1; + vdebug("Get addr: 0x%lx %lu 0x%lx\n", g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.bdev_open_addr); + offset1 = dmpatch_find_call_offset(g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.bdev_open_addr); + if (offset1 == 0) + { + vdebug("call bdev_open_addr Not found\n"); + return 1; + } } + else + { + vdebug("Get addr: 0x%lx %lu 0x%lx\n", g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.blkdev_get_addr); + vdebug("Put addr: 0x%lx %lu 0x%lx\n", g_ko_param.sym_put_addr, g_ko_param.sym_put_size, g_ko_param.blkdev_put_addr); + + offset1 = dmpatch_find_call_offset(g_ko_param.sym_get_addr, g_ko_param.sym_get_size, g_ko_param.blkdev_get_addr); + offset2 = dmpatch_find_call_offset(g_ko_param.sym_put_addr, g_ko_param.sym_put_size, g_ko_param.blkdev_put_addr); + if (offset1 == 0 || offset2 == 0) + { + vdebug("call blkdev_get or blkdev_put Not found, %lu %lu\n", offset1, offset2); + return 1; + } + } + vdebug("call addr1:0x%lx call addr2:0x%lx\n", g_ko_param.sym_get_addr + offset1, g_ko_param.sym_put_addr + offset2); @@ -327,36 +363,41 @@ static unsigned int dmpatch_patch_claim_ptr(void) return 1; } - opCode = (unsigned char *)g_ko_param.sym_put_addr; - for (i = offset2 - 1, t = 0; (i > 0) && (t < 24); i--, t++) - { - /* rsi */ - if (opCode[i] == 0x48 && opCode[i + 1] == 0xc7 && opCode[i + 2] == 0xc6) - { - if (*(unsigned int *)(opCode + i + 3) == g_claim_ptr) - { - vdebug("claim_ptr found at put addr 0x%lx\n", g_ko_param.sym_put_addr + i + 3); - g_put_patch[0] = opCode + i + 3; - break; - } - } - } - - if (g_put_patch[0] == 0) - { - vdebug("Claim_ptr not found in put\n"); - return 1; - } - + align = (unsigned long)g_get_patch[0] / g_ko_param.pgsize * g_ko_param.pgsize; set_mem_rw(align, 1); *(unsigned int *)(g_get_patch[0]) = 0; set_mem_ro(align, 1); - align = (unsigned long)g_put_patch[0] / g_ko_param.pgsize * g_ko_param.pgsize; - set_mem_rw(align, 1); - *(unsigned int *)(g_put_patch[0]) = 0; - set_mem_ro(align, 1); + + if (offset2 > 0) + { + opCode = (unsigned char *)g_ko_param.sym_put_addr; + for (i = offset2 - 1, t = 0; (i > 0) && (t < 24); i--, t++) + { + /* rsi */ + if (opCode[i] == 0x48 && opCode[i + 1] == 0xc7 && opCode[i + 2] == 0xc6) + { + if (*(unsigned int *)(opCode + i + 3) == g_claim_ptr) + { + vdebug("claim_ptr found at put addr 0x%lx\n", g_ko_param.sym_put_addr + i + 3); + g_put_patch[0] = opCode + i + 3; + break; + } + } + } + + if (g_put_patch[0] == 0) + { + vdebug("Claim_ptr not found in put\n"); + return 1; + } + + align = (unsigned long)g_put_patch[0] / g_ko_param.pgsize * g_ko_param.pgsize; + set_mem_rw(align, 1); + *(unsigned int *)(g_put_patch[0]) = 0; + set_mem_ro(align, 1); + } return 0; } @@ -382,7 +423,7 @@ static __always_inline void dmpatch_wrmsr(unsigned int msr, u32 low, u32 high) : : "c" (msr), "a"(low), "d" (high) : "memory"); } -static u64 dmpatch_ibt_save(void) +static u64 notrace dmpatch_ibt_save(void) { u64 msr = 0; u64 val = 0; @@ -394,7 +435,7 @@ static u64 dmpatch_ibt_save(void) return msr; } -static void dmpatch_ibt_restore(u64 save) +static void notrace dmpatch_ibt_restore(u64 save) { u64 msr; @@ -406,8 +447,8 @@ static void dmpatch_ibt_restore(u64 save) dmpatch_wrmsr(MSR_IA32_S_CET, (u32)(msr & 0xffffffffULL), (u32)(msr >> 32)); } #else -static u64 dmpatch_ibt_save(void) { return 0; } -static void dmpatch_ibt_restore(u64 save) { (void)save; } +static u64 notrace dmpatch_ibt_save(void) { return 0; } +static void notrace dmpatch_ibt_restore(u64 save) { (void)save; } #endif static int notrace dmpatch_init(void) @@ -423,8 +464,8 @@ static int notrace dmpatch_init(void) kprintf = (printk_pf)(g_ko_param.printk_addr); - vdebug("dmpatch_init start pagesize=%lu kernel=%lu.%lu ...\n", - g_ko_param.pgsize, g_ko_param.kv_major, g_ko_param.kv_minor); + vdebug("dmpatch_init start pagesize=%lu kernel=%lu.%lu.%lu ...\n", + g_ko_param.pgsize, g_ko_param.kv_major, g_ko_param.kv_minor, g_ko_param.kv_subminor); if (g_ko_param.struct_size != sizeof(ko_param)) { @@ -443,7 +484,7 @@ static int notrace dmpatch_init(void) reg_kprobe = (kprobe_reg_pf)g_ko_param.reg_kprobe_addr; unreg_kprobe = (kprobe_unreg_pf)g_ko_param.unreg_kprobe_addr; - if (g_ko_param.kv_major > 6 || (g_ko_param.kv_major == 6 && g_ko_param.kv_minor >= 5)) + if (dmpatch_kv_above(6, 5, 0)) /* >= kernel 6.5 */ { vdebug("new interface patch dm_get_table_device...\n"); r = dmpatch_patch_claim_ptr(); @@ -466,25 +507,25 @@ static int notrace dmpatch_init(void) if (r) { - rc = -EINVAL; + rc = -EFAULT; goto out; } vdebug("patch dm_get_table_device success\n"); - if (g_ko_param.kv_major >= 6 && g_ko_param.kv_minor >= 5) + if (dmpatch_kv_above(6, 5, 0)) { r = 0; } else { r = dmpatch_replace_code(1, g_ko_param.sym_put_addr, g_ko_param.sym_put_size, 1, "dm_put_table_device", g_put_patch); + if (r) + { + rc = -EFAULT; + goto out; + } + vdebug("patch dm_put_table_device success\n"); } - if (r) - { - rc = -EINVAL; - goto out; - } - vdebug("patch dm_put_table_device success\n"); vdebug("#####################################\n"); vdebug("######## dm patch success ###########\n"); @@ -513,7 +554,10 @@ static void notrace dmpatch_exit(void) if (g_claim_ptr) { dmpatch_restore_code(4, g_get_patch[0], g_claim_ptr); - dmpatch_restore_code(4, g_put_patch[0], g_claim_ptr); + if (g_put_patch[0]) + { + dmpatch_restore_code(4, g_put_patch[0], g_claim_ptr); + } } else {