diff --git a/BUSYBOX/chmod/build.sh b/BUSYBOX/chmod/build.sh index 5db2ae74..e72bc10a 100644 --- a/BUSYBOX/chmod/build.sh +++ b/BUSYBOX/chmod/build.sh @@ -1,9 +1,11 @@ #!/bin/sh -DSTDIR=../../IMG/cpio/ventoy/busybox +DSTDIR1=../../IMG/cpio_x86/ventoy/busybox +DSTDIR2=../../IMG/cpio_arm64/ventoy/busybox +DSTDIR3=../../IMG/cpio_mips64/ventoy/busybox rm -f vtchmod32 vtchmod64 vtchmod64_musl vtchmodaa64 -rm -f $DSTDIR/vtchmod32 $DSTDIR/vtchmod64 $DSTDIR/vtchmodaa64 $DSTDIR/vtchmodm64e +rm -f $DSTDIR1/vtchmod32 $DSTDIR1/vtchmod64 $DSTDIR2/vtchmodaa64 $DSTDIR3/vtchmodm64e /opt/diet32/bin/diet gcc -Os -m32 vtchmod.c -o vtchmod32 /opt/diet64/bin/diet gcc -Os vtchmod.c -o vtchmod64 @@ -23,9 +25,9 @@ chmod 777 vtchmodaa64 chmod 777 vtchmod64_musl chmod 777 vtchmodm64e -cp -a vtchmod32 $DSTDIR/ -cp -a vtchmod64 $DSTDIR/ -cp -a vtchmodaa64 $DSTDIR/ -cp -a vtchmod64_musl $DSTDIR/ -cp -a vtchmodm64e $DSTDIR/ +cp -a vtchmod32 $DSTDIR1/ +cp -a vtchmod64 $DSTDIR1/ +cp -a vtchmod64_musl $DSTDIR1/ +cp -a vtchmodaa64 $DSTDIR2/ +cp -a vtchmodm64e $DSTDIR3/ diff --git a/BUSYBOX/chmod/vtchmod.c b/BUSYBOX/chmod/vtchmod.c index 5a9d833f..ad10d0e8 100644 --- a/BUSYBOX/chmod/vtchmod.c +++ b/BUSYBOX/chmod/vtchmod.c @@ -1,5 +1,8 @@ +#include +#include #include #include +#include int main(int argc, char **argv) { @@ -7,7 +10,25 @@ int main(int argc, char **argv) { return 1; } - + + if (argv[1][0] == '-' && argv[1][1] == '6') + { + struct utsname buf; + if (0 == uname(&buf)) + { + if (strstr(buf.machine, "amd64")) + { + return 0; + } + + if (strstr(buf.machine, "x86_64")) + { + return 0; + } + } + return 1; + } + return chmod(argv[1], 0777); } diff --git a/BUSYBOX/chmod/vtchmod32 b/BUSYBOX/chmod/vtchmod32 index 4b66db3c..2647afb6 100644 Binary files a/BUSYBOX/chmod/vtchmod32 and b/BUSYBOX/chmod/vtchmod32 differ diff --git a/BUSYBOX/chmod/vtchmod64 b/BUSYBOX/chmod/vtchmod64 index 9c799581..4d27c578 100644 Binary files a/BUSYBOX/chmod/vtchmod64 and b/BUSYBOX/chmod/vtchmod64 differ diff --git a/BUSYBOX/chmod/vtchmod64_musl b/BUSYBOX/chmod/vtchmod64_musl index d4cd5c6b..01c80f21 100644 Binary files a/BUSYBOX/chmod/vtchmod64_musl and b/BUSYBOX/chmod/vtchmod64_musl differ diff --git a/BUSYBOX/chmod/vtchmodaa64 b/BUSYBOX/chmod/vtchmodaa64 index 593c021f..6c3811a1 100644 Binary files a/BUSYBOX/chmod/vtchmodaa64 and b/BUSYBOX/chmod/vtchmodaa64 differ diff --git a/BUSYBOX/chmod/vtchmodm64e b/BUSYBOX/chmod/vtchmodm64e index 47e84be6..dc623d52 100644 Binary files a/BUSYBOX/chmod/vtchmodm64e and b/BUSYBOX/chmod/vtchmodm64e differ diff --git a/DMPATCH/Makefile b/DMPATCH/Makefile new file mode 100644 index 00000000..9a4243f1 --- /dev/null +++ b/DMPATCH/Makefile @@ -0,0 +1,7 @@ + +obj-m += dm_patch.o + +EXTRA_CFLAGS := -Wall + +dm_patch-objs := dmpatch.o + diff --git a/DMPATCH/dmpatch.c b/DMPATCH/dmpatch.c new file mode 100644 index 00000000..1106d79e --- /dev/null +++ b/DMPATCH/dmpatch.c @@ -0,0 +1,179 @@ +/****************************************************************************** + * dmpatch.c ---- patch for device-mapper + * + * Copyright (c) 2021, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PATCH 4 + +#define magic_sig 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF + +typedef int (*kprobe_reg_pf)(void *); +typedef void (*kprobe_unreg_pf)(void *); +typedef int (*printk_pf)(const char *fmt, ...); +typedef int (*set_memory_attr_pf)(unsigned long addr, int numpages); + +#pragma pack(1) +typedef struct ko_param +{ + unsigned char magic[16]; + unsigned long struct_size; + unsigned long pgsize; + unsigned long printk_addr; + unsigned long ro_addr; + unsigned long rw_addr; + unsigned long reg_kprobe_addr; + unsigned long unreg_kprobe_addr; + unsigned long sym_get_addr; + unsigned long sym_get_size; + unsigned long sym_put_addr; + unsigned long sym_put_size; + unsigned long padding[3]; +}ko_param; + +#pragma pack() + +static printk_pf kprintf = NULL; +static set_memory_attr_pf set_mem_ro = NULL; +static set_memory_attr_pf set_mem_rw = NULL; +static kprobe_reg_pf reg_kprobe = NULL; +static kprobe_unreg_pf unreg_kprobe = NULL; + +static volatile ko_param g_ko_param = +{ + { magic_sig }, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + + +#define CODE_MATCH(code, i) \ + (code[i] == 0x40 && code[i + 1] == 0x80 && code[i + 2] == 0xce && code[i + 3] == 0x80) + +#define vdebug(fmt, args...) if(kprintf) kprintf(KERN_ERR fmt, ##args) + +static int notrace dmpatch_replace_code(unsigned long addr, unsigned long size, int expect, const char *desc) +{ + int i = 0; + int cnt = 0; + unsigned long align; + unsigned char *patch[MAX_PATCH]; + unsigned char *opCode = (unsigned char *)addr; + + vdebug("patch for %s 0x%lx %d\n", desc, addr, (int)size); + + for (i = 0; i < (int)size - 4; i++) + { + if (CODE_MATCH(opCode, i) && cnt < MAX_PATCH) + { + patch[cnt] = opCode + i + 3; + cnt++; + } + } + + if (cnt != expect || cnt >= MAX_PATCH) + { + vdebug("patch error: cnt=%d expect=%d\n", cnt, expect); + return 1; + } + + + for (i = 0; i < cnt; i++) + { + opCode = patch[i]; + align = (unsigned long)opCode / g_ko_param.pgsize * g_ko_param.pgsize; + + set_mem_rw(align, 1); + *opCode = 0; + set_mem_ro(align, 1); + } + + return 0; +} + +static int notrace dmpatch_init(void) +{ + int r = 0; + int rc = 0; + + kprintf = (printk_pf)(g_ko_param.printk_addr); + + vdebug("dmpatch_init start pagesize=%lu ...\n", g_ko_param.pgsize); + + if (g_ko_param.struct_size != sizeof(ko_param)) + { + vdebug("Invalid struct size %d %d\n", (int)g_ko_param.struct_size, (int)sizeof(ko_param)); + return -EINVAL; + } + + if (g_ko_param.sym_get_addr == 0 || g_ko_param.sym_put_addr == 0 || + g_ko_param.ro_addr == 0 || g_ko_param.rw_addr == 0) + { + return -EINVAL; + } + + set_mem_ro = (set_memory_attr_pf)(g_ko_param.ro_addr); + set_mem_rw = (set_memory_attr_pf)(g_ko_param.rw_addr); + reg_kprobe = (kprobe_reg_pf)g_ko_param.reg_kprobe_addr; + unreg_kprobe = (kprobe_unreg_pf)g_ko_param.unreg_kprobe_addr; + + r = dmpatch_replace_code(g_ko_param.sym_get_addr, g_ko_param.sym_get_size, 2, "dm_get_table_device"); + if (r) + { + rc = -EINVAL; + goto out; + } + vdebug("patch dm_get_table_device success\n"); + + r = dmpatch_replace_code(g_ko_param.sym_put_addr, g_ko_param.sym_put_size, 1, "dm_put_table_device"); + if (r) + { + rc = -EINVAL; + goto out; + } + vdebug("patch dm_put_table_device success\n"); + + vdebug("#####################################\n"); + vdebug("######## dm patch success ###########\n"); + vdebug("#####################################\n"); + +out: + + return rc; +} + +static void notrace dmpatch_exit(void) +{ + +} + +module_init(dmpatch_init); +module_exit(dmpatch_exit); + + +MODULE_DESCRIPTION("dmpatch driver"); +MODULE_AUTHOR("longpanda "); +MODULE_LICENSE("GPL"); + diff --git a/DMPATCH/readme.txt b/DMPATCH/readme.txt new file mode 100644 index 00000000..866dc906 --- /dev/null +++ b/DMPATCH/readme.txt @@ -0,0 +1,35 @@ +1. install ubuntu 21.10 +2. apt-get install build-essential flex ncurse linux-headers-generic linux-source ...... and so on +3. cp /lib/modules/5.13.0-23-generic/build/Module.symvers ./ +4. /boot/config-5.13.0-23-generic as .config make oldconfig +5. make menuconfig + 1. close CONFIG_STACKPROTECTOR + 2. close CONFIG_RETPOLINE + +6. modify ./scripts/mod/modpost.c + 1. skip add_srcversion (just return) + 2. force add_retpoline (#ifdef --> #ifndef) + +7. make modules_prepare LOCALVERSION=-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +8. Append padding at the end of struct module +struct module { + enum module_state state; + + /* Member of list of modules */ + struct list_head list; + + /* Unique handle for this module */ + char name[MODULE_NAME_LEN]; + + .... + + char padding[1024]; +}; + +This is because struct module size is different in different kernel versions or with different CONFIG item. + + +9. make modules M=/home/dmpatch +10. strip --strip-debug /home/dmpatch/dm_patch.ko + diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c index f3d8d458..cc978a1b 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/VDiskChain/VDiskChain.c @@ -249,6 +249,12 @@ EFI_STATUS EFIAPI vdisk_exit_boot_service_wrapper IN UINTN MapKey ) { + if (g_org_get_variable) + { + gRT->GetVariable = g_org_get_variable; + g_org_get_variable = NULL; + } + return g_org_exit_boot_service(ImageHandle, MapKey); } diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c index cfcf4105..5d997225 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.c @@ -71,6 +71,9 @@ STATIC BOOLEAN g_hook_keyboard = FALSE; CHAR16 gFirstTryBootFile[256] = {0}; +STATIC EFI_GET_VARIABLE g_org_get_variable = NULL; +STATIC EFI_EXIT_BOOT_SERVICES g_org_exit_boot_service = NULL; + /* Boot filename */ UINTN gBootFileStartIndex = 1; CONST CHAR16 *gEfiBootFileName[] = @@ -739,6 +742,77 @@ STATIC EFI_STATUS ventoy_proc_img_replace_name(ventoy_grub_param_file_replace *r return EFI_SUCCESS; } +EFI_STATUS EFIAPI ventoy_get_variable_wrapper +( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data OPTIONAL +) +{ + EFI_STATUS Status = EFI_SUCCESS; + + Status = g_org_get_variable(VariableName, VendorGuid, Attributes, DataSize, Data); + if (StrCmp(VariableName, L"SecureBoot") == 0) + { + if ((*DataSize == 1) && Data) + { + *(UINT8 *)Data = 0; + } + } + + return Status; +} + +EFI_STATUS EFIAPI ventoy_exit_boot_service_wrapper +( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey +) +{ + if (g_org_get_variable) + { + gRT->GetVariable = g_org_get_variable; + g_org_get_variable = NULL; + } + + return g_org_exit_boot_service(ImageHandle, MapKey); +} + +STATIC EFI_STATUS EFIAPI ventoy_disable_secure_boot(IN EFI_HANDLE ImageHandle) +{ + UINT8 Value = 0; + UINTN DataSize = 1; + EFI_STATUS Status = EFI_SUCCESS; + + Status = gRT->GetVariable(L"SecureBoot", &gEfiGlobalVariableGuid, NULL, &DataSize, &Value); + if (!EFI_ERROR(Status)) + { + if (DataSize == 1 && Value == 0) + { + debug("Current secure boot is off, no need to disable"); + return EFI_SUCCESS; + } + } + + debug("ventoy_disable_secure_boot"); + + /* step1: wrapper security protocol. */ + /* Do we still need it since we have been loaded ? */ + + + /* step2: fake SecureBoot variable */ + g_org_exit_boot_service = gBS->ExitBootServices; + gBS->ExitBootServices = ventoy_exit_boot_service_wrapper; + + g_org_get_variable = gRT->GetVariable; + gRT->GetVariable = ventoy_get_variable_wrapper; + + return EFI_SUCCESS; +} + + STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) { UINT32 i = 0; @@ -909,6 +983,11 @@ STATIC EFI_STATUS EFIAPI ventoy_parse_cmdline(IN EFI_HANDLE ImageHandle) { g_hook_keyboard = TRUE; } + + if (g_os_param_reserved[5] == 1 && g_os_param_reserved[2] == ventoy_chain_linux) + { + ventoy_disable_secure_boot(ImageHandle); + } debug("internal param: secover:%u keyboard:%u", g_fixup_iso9660_secover_enable, g_hook_keyboard); diff --git a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.inf b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.inf index 892d8c77..374efdd7 100644 --- a/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.inf +++ b/EDK2/edk2_mod/edk2-edk2-stable201911/MdeModulePkg/Application/Ventoy/Ventoy.inf @@ -42,6 +42,7 @@ DebugLib [Guids] + gEfiGlobalVariableGuid gShellVariableGuid gEfiVirtualCdGuid gEfiFileInfoGuid diff --git a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c index 5adcdc65..b5233cce 100644 --- a/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c +++ b/GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_cmd.c @@ -2748,6 +2748,7 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param) { char *pos; const char *fs = NULL; + const char *val = NULL; const char *cdprompt = NULL; grub_uint32_t i; grub_uint8_t chksum = 0; @@ -2794,6 +2795,13 @@ void ventoy_fill_os_param(grub_file_t file, ventoy_os_param *param) param->vtoy_reserved[3] = 1; } + param->vtoy_reserved[5] = 0; + val = ventoy_get_env("VTOY_LINUX_REMOUNT"); + if (val && val[0] == '1' && val[1] == 0) + { + param->vtoy_reserved[5] = 1; + } + /* calculate checksum */ for (i = 0; i < sizeof(ventoy_os_param); i++) { diff --git a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h index 5cb04d8b..0102ef59 100644 --- a/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h +++ b/GRUB2/MOD_SRC/grub-2.04/include/grub/ventoy.h @@ -121,6 +121,7 @@ typedef struct ventoy_os_param * vtoy_reserved[2]: vtoy_chain_type 0:Linux 1:Windows 2:wimfile * vtoy_reserved[3]: vtoy_iso_format 0:iso9660 1:udf * vtoy_reserved[4]: vtoy_windows_cd_prompt + * vtoy_reserved[5]: vtoy_linux_remount * */ grub_uint8_t vtoy_reserved[32]; // Internal use by ventoy diff --git a/IMG/cpio/sbin/init b/IMG/cpio/sbin/init index 17be33fb..3fd3cc5e 100644 --- a/IMG/cpio/sbin/init +++ b/IMG/cpio/sbin/init @@ -48,6 +48,12 @@ else fi fi +if [ "$VTOY_ARCH" = "i386" ]; then + if $BUSYBOX_PATH/vtchmod32 -6; then + export VTOY_ARCH=x86_64 + fi +fi + echo $VTOY_ARCH > $VTOY_PATH/ventoy_arch @@ -81,6 +87,7 @@ export PATH=$BUSYBOX_PATH/:$VTOY_PATH/tool export VTOY_BREAK_LEVEL=$(hexdump -n 1 -s 449 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param) export VTOY_DEBUG_LEVEL=$(hexdump -n 1 -s 450 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param) +export VTOY_LINUX_REMOUNT=$(hexdump -n 1 -s 454 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param) #Fixme: busybox shell output redirect seems to have some bug in rhel5 if uname -a | grep -q el5; then diff --git a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh index 881daef5..a22314fc 100644 --- a/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh +++ b/IMG/cpio/ventoy/hook/ventoy-hook-lib.sh @@ -30,6 +30,7 @@ SLEEP=$BUSYBOX_PATH/sleep HEAD=$BUSYBOX_PATH/head VTOY_DM_PATH=/dev/mapper/ventoy VTOY_DEBUG_LEVEL=$($BUSYBOX_PATH/hexdump -n 1 -s 450 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param) +VTOY_LINUX_REMOUNT=$($BUSYBOX_PATH/hexdump -n 1 -s 454 -e '1/1 "%02x"' $VTOY_PATH/ventoy_os_param) if [ "$VTOY_DEBUG_LEVEL" = "01" ]; then if [ -e /dev/console ]; then @@ -220,6 +221,125 @@ ventoy_check_dm_module() { fi } +ventoy_need_dm_patch() { + if [ "$VTOY_LINUX_REMOUNT" != "01" ]; then + $BUSYBOX_PATH/false; return + fi + + if $GREP -q 'device-mapper' /proc/devices; then + : + else + $BUSYBOX_PATH/false; return + fi + + if $GREP -q 'dm_patch' /proc/modules; then + $BUSYBOX_PATH/false; return + fi + + vtMajorVer=$($BUSYBOX_PATH/uname -r | $AWK -F. '{print $1}') + vtMinorVer=$($BUSYBOX_PATH/uname -r | $AWK -F. '{print $2}') + + if [ $vtMajorVer -lt 3 ]; then + $BUSYBOX_PATH/false; return + elif [ $vtMajorVer -eq 3 -a $vtMinorVer -lt 10 ]; then + $BUSYBOX_PATH/false; return + fi + + + $BUSYBOX_PATH/true +} + +ventoy_dm_patch() { + vtMType=$($BUSYBOX_PATH/uname -m) + + vtlog "######### ventoy_dm_patch ############" + + if echo $vtMType | $EGREP -i -q "x86.64|amd64"; then + vtKoName=dm_patch_64.ko + else + vtlog "unsupported machine type $vtMType" + return + fi + + if [ -f $VTOY_PATH/tool/$vtKoName ]; then + vtlog "/ventoy/tool/$vtKoName exist OK" + else + vtlog "/ventoy/tool/$vtKoName NOT exist" + return + fi + + $CAT /proc/kallsyms | $BUSYBOX_PATH/sort > $VTOY_PATH/kallsyms + + vtLine=$($VTOY_PATH/tool/vtoyksym dm_get_table_device $VTOY_PATH/kallsyms) + get_addr=$(echo $vtLine | $AWK '{print $1}') + get_size=$(echo $vtLine | $AWK '{print $2}') + + vtLine=$($VTOY_PATH/tool/vtoyksym dm_put_table_device $VTOY_PATH/kallsyms) + put_addr=$(echo $vtLine | $AWK '{print $1}') + put_size=$(echo $vtLine | $AWK '{print $2}') + + ro_addr=$($GREP ' set_memory_ro$' /proc/kallsyms | $AWK '{print $1}') + rw_addr=$($GREP ' set_memory_rw$' /proc/kallsyms | $AWK '{print $1}') + kprobe_reg_addr=$($GREP ' register_kprobe$' /proc/kallsyms | $AWK '{print $1}') + kprobe_unreg_addr=$($GREP ' unregister_kprobe$' /proc/kallsyms | $AWK '{print $1}') + + if [ "$VTOY_DEBUG_LEVEL" = "01" ]; then + printk_addr=$($GREP ' printk$' /proc/kallsyms | $AWK '{print $1}') + vtDebug="-v" + else + printk_addr=0 + fi + + #printk_addr=$($GREP ' printk$' /proc/kallsyms | $AWK '{print $1}') + #vtDebug="-v" + + vtlog get_addr=$get_addr get_size=$get_size + vtlog put_addr=$put_addr put_size=$put_size + vtlog kprobe_reg_addr=$kprobe_reg_addr kprobe_unreg_addr=$kprobe_unreg_addr + vtlog ro_addr=$ro_addr rw_addr=$rw_addr printk_addr=$printk_addr + + if [ "$get_addr" = "0" -o "$put_addr" = "0" ]; then + vtlog "Invalid symbol address" + return + fi + if [ "$ro_addr" = "0" -o "$rw_addr" = "0" ]; then + vtlog "Invalid symbol address" + return + fi + + + vtKv=$($BUSYBOX_PATH/uname -r) + vtModPath=$($FIND /lib/modules/$vtKv/kernel/fs/ -name "*.ko*" | $HEAD -n1) + vtModName=$($BUSYBOX_PATH/basename $vtModPath) + + vtlog "template module is $vtModPath $vtModName" + + if echo $vtModPath | $GREP -q "[.]ko$"; then + $BUSYBOX_PATH/cp -a $vtModPath $VTOY_PATH/$vtModName + elif echo $vtModPath | $GREP -q "[.]ko[.]xz$"; then + $BUSYBOX_PATH/xzcat $vtModPath > $VTOY_PATH/$vtModName + elif echo $vtModPath | $GREP -q "[.]ko[.]gz$"; then + $BUSYBOX_PATH/zcat $vtModPath > $VTOY_PATH/$vtModName + else + vtlog "unsupport module type" + return + fi + + #step1: modify vermagic/mod crc/relocation + $VTOY_PATH/tool/vtoykmod -u $VTOY_PATH/tool/$vtKoName $VTOY_PATH/$vtModName $vtDebug + + #step2: fill parameters + vtPgsize=$($VTOY_PATH/tool/vtoyksym -p) + $VTOY_PATH/tool/vtoykmod -f $VTOY_PATH/tool/$vtKoName $vtPgsize 0x$printk_addr 0x$ro_addr 0x$rw_addr $get_addr $get_size $put_addr $put_size 0x$kprobe_reg_addr 0x$kprobe_unreg_addr $vtDebug + + $BUSYBOX_PATH/insmod $VTOY_PATH/tool/$vtKoName + + if $GREP -q 'dm_patch' /proc/modules; then + echo "done" > $VTOY_PATH/dm_patch_done + fi + +} + create_ventoy_device_mapper() { vtlog "create_ventoy_device_mapper $*" @@ -230,19 +350,36 @@ create_ventoy_device_mapper() { fi vtlog "dmsetup avaliable in system $VT_DM_BIN" - + if ventoy_check_dm_module "$1"; then vtlog "device-mapper module check success" else vterr "Error: no dm module avaliable" fi - $VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/ventoy_dm_table + $VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_image_map -d $1 > $VTOY_PATH/ventoy_dm_table + + + vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}') + vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}') + vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}') + vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}') + if ventoy_need_dm_patch; then + ventoy_dm_patch + #suppress printk message + echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk + fi + if [ -z "$2" ]; then $VT_DM_BIN create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1 else $VT_DM_BIN "$2" create ventoy $VTOY_PATH/ventoy_dm_table >>$VTLOG 2>&1 - fi + fi + + if ventoy_need_dm_patch; then + #recover printk level + echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk + fi } create_persistent_device_mapper() { @@ -262,8 +399,24 @@ create_persistent_device_mapper() { vterr "Error: no dm module avaliable" fi - $VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_persistent_map -d $1 > $VTOY_PATH/persistent_dm_table + $VTOY_PATH/tool/vtoydm -p -f $VTOY_PATH/ventoy_persistent_map -d $1 > $VTOY_PATH/persistent_dm_table + + + vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}') + vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}') + vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}') + vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}') + if [ -f $VTOY_PATH/dm_patch_done ]; then + #suppress printk message + echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk + fi + $VT_DM_BIN create vtoy_persistent $VTOY_PATH/persistent_dm_table >>$VTLOG 2>&1 + + if [ -f $VTOY_PATH/dm_patch_done ]; then + #recover printk level + echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk + fi } @@ -493,6 +646,22 @@ ventoy_create_persistent_link() { fi } +ventoy_partname_to_diskname() { + if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then + echo -n "${1:0:-2}" + else + echo -n "${1:0:-1}" + fi +} + +ventoy_diskname_to_partname() { + if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then + echo -n "${1}p$2" + else + echo -n "${1}$2" + fi +} + ventoy_udev_disk_common_hook() { if echo $1 | $EGREP -q "nvme.*p[0-9]$|mmc.*p[0-9]$|nbd.*p[0-9]$"; then VTDISK="${1:0:-2}" @@ -541,6 +710,10 @@ ventoy_udev_disk_common_hook() { create_persistent_device_mapper "/dev/$VTDISK" ventoy_create_persistent_link fi + + if $GREP -q 'dm_patch' /proc/modules; then + $BUSYBOX_PATH/rmmod dm_patch + fi } ventoy_create_dev_ventoy_part() { @@ -550,6 +723,15 @@ ventoy_create_dev_ventoy_part() { if [ -e /vtoy_dm_table ]; then vtPartid=1 + vtLevel1=$($CAT /proc/sys/kernel/printk | $AWK '{print $1}') + vtLevel2=$($CAT /proc/sys/kernel/printk | $AWK '{print $2}') + vtLevel3=$($CAT /proc/sys/kernel/printk | $AWK '{print $3}') + vtLevel4=$($CAT /proc/sys/kernel/printk | $AWK '{print $4}') + if [ -f $VTOY_PATH/dm_patch_done ]; then + #suppress printk message + echo 0 $vtLevel2 0 $vtLevel4 > /proc/sys/kernel/printk + fi + $CAT /vtoy_dm_table | while read vtline; do echo $vtline > /ventoy/dm_table_part${vtPartid} $VTOY_PATH/tool/dmsetup create ventoy${vtPartid} /ventoy/dm_table_part${vtPartid} @@ -558,7 +740,12 @@ ventoy_create_dev_ventoy_part() { $BUSYBOX_PATH/mknod -m 0666 /dev/ventoy${vtPartid} b $blkdev_num vtPartid=$(expr $vtPartid + 1) - done + done + + if [ -f $VTOY_PATH/dm_patch_done ]; then + #recover printk level + echo $vtLevel1 $vtLevel2 $vtLevel3 $vtLevel4 > /proc/sys/kernel/printk + fi fi } diff --git a/IMG/cpio_arm64/ventoy/busybox/vtchmodaa64 b/IMG/cpio_arm64/ventoy/busybox/vtchmodaa64 index 593c021f..6c3811a1 100644 Binary files a/IMG/cpio_arm64/ventoy/busybox/vtchmodaa64 and b/IMG/cpio_arm64/ventoy/busybox/vtchmodaa64 differ diff --git a/IMG/cpio_mips64/ventoy/busybox/vtchmodm64e b/IMG/cpio_mips64/ventoy/busybox/vtchmodm64e index 47e84be6..dc623d52 100644 Binary files a/IMG/cpio_mips64/ventoy/busybox/vtchmodm64e and b/IMG/cpio_mips64/ventoy/busybox/vtchmodm64e differ diff --git a/IMG/cpio_x86/ventoy/busybox/vtchmod32 b/IMG/cpio_x86/ventoy/busybox/vtchmod32 index 4b66db3c..2647afb6 100644 Binary files a/IMG/cpio_x86/ventoy/busybox/vtchmod32 and b/IMG/cpio_x86/ventoy/busybox/vtchmod32 differ diff --git a/IMG/cpio_x86/ventoy/busybox/vtchmod64 b/IMG/cpio_x86/ventoy/busybox/vtchmod64 index 9c799581..4d27c578 100644 Binary files a/IMG/cpio_x86/ventoy/busybox/vtchmod64 and b/IMG/cpio_x86/ventoy/busybox/vtchmod64 differ diff --git a/IMG/cpio_x86/ventoy/busybox/vtchmod64_musl b/IMG/cpio_x86/ventoy/busybox/vtchmod64_musl index d4cd5c6b..01c80f21 100644 Binary files a/IMG/cpio_x86/ventoy/busybox/vtchmod64_musl and b/IMG/cpio_x86/ventoy/busybox/vtchmod64_musl differ diff --git a/IMG/cpio_x86/ventoy/tool/dm_patch_64.ko b/IMG/cpio_x86/ventoy/tool/dm_patch_64.ko new file mode 100644 index 00000000..789e3599 Binary files /dev/null and b/IMG/cpio_x86/ventoy/tool/dm_patch_64.ko differ diff --git a/INSTALL/grub/grub.cfg b/INSTALL/grub/grub.cfg index c32ef947..d84a9d38 100644 --- a/INSTALL/grub/grub.cfg +++ b/INSTALL/grub/grub.cfg @@ -2022,7 +2022,7 @@ function img_unsupport_menuentry { ############################################################# ############################################################# -set VENTOY_VERSION="1.0.63" +set VENTOY_VERSION="1.0.64" #ACPI not compatible with Window7/8, so disable by default set VTOY_PARAM_NO_ACPI=1 diff --git a/Plugson/src/Web/ventoy_http.c b/Plugson/src/Web/ventoy_http.c index 7f17a4b5..96a6fa51 100644 --- a/Plugson/src/Web/ventoy_http.c +++ b/Plugson/src/Web/ventoy_http.c @@ -505,6 +505,7 @@ int ventoy_data_cmp_control(data_control *data1, data_control *data2) data1->filter_vhd != data2->filter_vhd || data1->filter_vtoy != data2->filter_vtoy || data1->win11_bypass_check != data2->win11_bypass_check || + data1->linux_remount != data2->linux_remount || data1->menu_timeout != data2->menu_timeout) { return 1; @@ -549,6 +550,7 @@ int ventoy_data_save_control(data_control *data, const char *title, char *buf, i VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_FILE_FLT_VHD", filter_vhd); VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_FILE_FLT_VTOY", filter_vtoy); VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_WIN11_BYPASS_CHECK", win11_bypass_check); + VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_LINUX_REMOUNT", linux_remount); VTOY_JSON_FMT_CTRL_INT(L2, "VTOY_MENU_TIMEOUT", menu_timeout); VTOY_JSON_FMT_CTRL_STRN(L2, "VTOY_DEFAULT_KBD_LAYOUT", default_kbd_layout); @@ -593,6 +595,7 @@ int ventoy_data_json_control(data_control *ctrl, char *buf, int buflen) VTOY_JSON_FMT_SINT("filter_vhd", ctrl->filter_vhd); VTOY_JSON_FMT_SINT("filter_vtoy", ctrl->filter_vtoy); VTOY_JSON_FMT_SINT("win11_bypass_check", ctrl->win11_bypass_check); + VTOY_JSON_FMT_SINT("linux_remount", ctrl->linux_remount); VTOY_JSON_FMT_SINT("menu_timeout", ctrl->menu_timeout); VTOY_JSON_FMT_STRN("default_kbd_layout", ctrl->default_kbd_layout); VTOY_JSON_FMT_STRN("help_text_language", ctrl->help_text_language); @@ -658,6 +661,7 @@ static int ventoy_api_save_control(struct mg_connection *conn, VTOY_JSON *json) VTOY_JSON_INT("filter_vhd", ctrl->filter_vhd); VTOY_JSON_INT("filter_vtoy", ctrl->filter_vtoy); VTOY_JSON_INT("win11_bypass_check", ctrl->win11_bypass_check); + VTOY_JSON_INT("linux_remount", ctrl->linux_remount); VTOY_JSON_INT("menu_timeout", ctrl->menu_timeout); VTOY_JSON_STR("default_image", ctrl->default_image); @@ -3790,6 +3794,10 @@ static int ventoy_parse_control(VTOY_JSON *json, void *p) { CONTROL_PARSE_INT(child, data->win11_bypass_check); } + else if (strcmp(child->pcName, "VTOY_LINUX_REMOUNT") == 0) + { + CONTROL_PARSE_INT(child, data->linux_remount); + } else if (strcmp(child->pcName, "VTOY_TREE_VIEW_MENU_STYLE") == 0) { CONTROL_PARSE_INT(child, data->treeview_style); diff --git a/Plugson/src/Web/ventoy_http.h b/Plugson/src/Web/ventoy_http.h index d5607df1..17b21bf0 100644 --- a/Plugson/src/Web/ventoy_http.h +++ b/Plugson/src/Web/ventoy_http.h @@ -58,6 +58,7 @@ typedef struct data_control int filter_vtoy; int win11_bypass_check; int menu_timeout; + int linux_remount; char default_search_root[MAX_PATH]; char default_image[MAX_PATH]; char default_kbd_layout[32]; diff --git a/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe b/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe index 79fbbbef..8efd516b 100644 Binary files a/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe and b/Plugson/vs/VentoyPlugson/Release/VentoyPlugson.exe differ diff --git a/Plugson/www/buildtime b/Plugson/www/buildtime index 483a8bfc..bbcb4d7c 100644 --- a/Plugson/www/buildtime +++ b/Plugson/www/buildtime @@ -1 +1 @@ -20211203 17:44:10 \ No newline at end of file +20220108 22:41:02 \ No newline at end of file diff --git a/Plugson/www/index.html b/Plugson/www/index.html index ed601cda..45731a0c 100644 --- a/Plugson/www/index.html +++ b/Plugson/www/index.html @@ -723,7 +723,7 @@ diff --git a/Plugson/www/plugson_control.html b/Plugson/www/plugson_control.html index 6c39190a..60c8fc75 100644 --- a/Plugson/www/plugson_control.html +++ b/Plugson/www/plugson_control.html @@ -337,6 +337,57 @@ + +
+
+

VTOY_LINUX_REMOUNT + —— Linux 启动后继续访问ISO文件所在分区

+
+ +
+
+
+ + + + + + + + + + + + + +
选项设置 +      + +
选项说明 + 0 Linux启动后不需要继续访问ISO文件所在的分区。
+ 1 Linux启动后需要继续访问ISO文件所在的分区。

+ 该选项只对 Linux 系统镜像有效。
+ 默认情况下,受Linux内核相关功能的限制,对于Linux系统,在启动后无法继续访问ISO文件所在的分区。在mount的时候会提示 device busy。
+ 如果这里选择 1,则 Ventoy 会尝试通过一些特殊的手段绕过内核的这个限制,但是这个功能是实验性质的,没有经过大规模和长时间的验证。 +
Option Description + 0 I don't need to access the image partition after boot.
+ 1 I need to access the image partition after boot.

+ This option is only avaliable for Linux distro image files.
+ + By default, the image partition where the ISO files locate can not be accessed after boot. When you try to mount it you will get device busy error. + This is due to linux kernel restriction (device-mapper module).
+ If you select 1 here, Ventoy will try to bypass the restriction with some special mechanism.
+ But it should be noted that, this is an experimental feature and is not fully tested. + +
+
+
+ +
@@ -881,6 +932,7 @@ var level; data.win11_bypass_check = parseInt($('input:radio[name=id_ctrl_bypass_win11_radio]:checked').val()); + data.linux_remount = parseInt($('input:radio[name=id_ctrl_linux_remount_radio]:checked').val()); data.default_search_root = $('input:text[id=id_ctrl_text_search_root]').val(); data.menu_timeout = parseInt($('input:text[id=id_ctrl_text_timeout]').val()); data.default_image = $('input:text[id=id_ctrl_text_default_img]').val(); @@ -913,6 +965,7 @@ function VtoyFillCurrentPageItem(data) { //VTOY_WIN11_BYPASS_CHECK $('input:radio[name=id_ctrl_bypass_win11_radio]')[data.win11_bypass_check].checked = true; + $('input:radio[name=id_ctrl_linux_remount_radio]')[data.linux_remount].checked = true; //VTOY_DEFAULT_SEARCH_ROOT $('input:text[id=id_ctrl_text_search_root]').val(data.default_search_root); @@ -1014,6 +1067,7 @@ method : 'save_control', index: current_tab_index, win11_bypass_check: data.win11_bypass_check, + linux_remount:data.linux_remount, default_search_root: data.default_search_root, menu_timeout: data.menu_timeout, default_image: data.default_image, diff --git a/README.md b/README.md index 6d30a1cd..863da1d0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ You can copy many image files at a time and ventoy will give you a boot menu to x86 Legacy BIOS, IA32 UEFI, x86_64 UEFI, ARM64 UEFI and MIPS64EL UEFI are supported in the same way.
Both MBR and GPT partition style are supported in the same way.
Most type of OS supported(Windows/WinPE/Linux/Unix/ChromeOS/Vmware/Xen...)
- 770+ ISO files are tested (List). 90%+ distros in distrowatch.com supported (Details).
+ 780+ ISO files are tested (List). 90%+ distros in distrowatch.com supported (Details).

Official Website: https://www.ventoy.net @@ -58,7 +58,7 @@ A GUI Ventoy plugin configurator. [VentoyPlugson](https://www.ventoy.net/en/plug * FAT32/exFAT/NTFS/UDF/XFS/Ext2(3)(4) supported for main partition * ISO files larger than 4GB supported * Native boot menu style for Legacy & UEFI -* Most type of OS supported, 770+ iso files tested +* Most type of OS supported, 780+ iso files tested * Linux vDisk boot supported * Not only boot but also complete installation process * Menu dynamically switchable between List/TreeView mode diff --git a/VtoyTool/vtoykmod.c b/VtoyTool/vtoykmod.c new file mode 100644 index 00000000..b3519f38 --- /dev/null +++ b/VtoyTool/vtoykmod.c @@ -0,0 +1,546 @@ +/****************************************************************************** + * vtoykmod.c ---- ventoy kmod + * + * Copyright (c) 2021, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include +#include + +#define _ull unsigned long long + +#define magic_sig 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF + +#define EI_NIDENT (16) + +#define EI_MAG0 0 /* e_ident[] indexes */ +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f /* EI_MAG */ +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 /* EI_CLASS */ +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 /* e_ident[EI_DATA] */ +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 /* e_version, EI_VERSION */ +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#define SHT_STRTAB 3 + +#pragma pack(1) + + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + uint16_t e_type; /* Object file type */ + uint16_t e_machine; /* Architecture */ + uint32_t e_version; /* Object file version */ + uint32_t e_entry; /* Entry point virtual address */ + uint32_t e_phoff; /* Program header table file offset */ + uint32_t e_shoff; /* Section header table file offset */ + uint32_t e_flags; /* Processor-specific flags */ + uint16_t e_ehsize; /* ELF header size in bytes */ + uint16_t e_phentsize; /* Program header table entry size */ + uint16_t e_phnum; /* Program header table entry count */ + uint16_t e_shentsize; /* Section header table entry size */ + uint16_t e_shnum; /* Section header table entry count */ + uint16_t e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + uint16_t e_type; /* Object file type */ + uint16_t e_machine; /* Architecture */ + uint32_t e_version; /* Object file version */ + uint64_t e_entry; /* Entry point virtual address */ + uint64_t e_phoff; /* Program header table file offset */ + uint64_t e_shoff; /* Section header table file offset */ + uint32_t e_flags; /* Processor-specific flags */ + uint16_t e_ehsize; /* ELF header size in bytes */ + uint16_t e_phentsize; /* Program header table entry size */ + uint16_t e_phnum; /* Program header table entry count */ + uint16_t e_shentsize; /* Section header table entry size */ + uint16_t e_shnum; /* Section header table entry count */ + uint16_t e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +typedef struct +{ + uint32_t sh_name; /* Section name (string tbl index) */ + uint32_t sh_type; /* Section type */ + uint32_t sh_flags; /* Section flags */ + uint32_t sh_addr; /* Section virtual addr at execution */ + uint32_t sh_offset; /* Section file offset */ + uint32_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint32_t sh_addralign; /* Section alignment */ + uint32_t sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + uint32_t sh_name; /* Section name (string tbl index) */ + uint32_t sh_type; /* Section type */ + uint64_t sh_flags; /* Section flags */ + uint64_t sh_addr; /* Section virtual addr at execution */ + uint64_t sh_offset; /* Section file offset */ + uint64_t sh_size; /* Section size in bytes */ + uint32_t sh_link; /* Link to another section */ + uint32_t sh_info; /* Additional section information */ + uint64_t sh_addralign; /* Section alignment */ + uint64_t sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +typedef struct elf32_rel { + uint32_t r_offset; + uint32_t r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + uint64_t r_offset; /* Location at which to apply the action */ + uint64_t r_info; /* index and type of relocation */ +} Elf64_Rel; + +typedef struct elf32_rela{ + uint32_t r_offset; + uint32_t r_info; + int32_t r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + uint64_t r_offset; /* Location at which to apply the action */ + uint64_t r_info; /* index and type of relocation */ + int64_t r_addend; /* Constant addend used to compute value */ +} Elf64_Rela; + + +struct modversion_info { + unsigned long crc; + char name[64 - sizeof(unsigned long)]; +}; + + +typedef struct ko_param +{ + unsigned char magic[16]; + unsigned long struct_size; + unsigned long pgsize; + unsigned long printk_addr; + unsigned long ro_addr; + unsigned long rw_addr; + unsigned long reg_kprobe_addr; + unsigned long unreg_kprobe_addr; + unsigned long sym_get_addr; + unsigned long sym_get_size; + unsigned long sym_put_addr; + unsigned long sym_put_size; + unsigned long padding[3]; +}ko_param; + +#pragma pack() + +static int verbose = 0; +#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__) + +static int vtoykmod_write_file(char *name, void *buf, int size) +{ + FILE *fp; + + fp = fopen(name, "wb+"); + if (!fp) + { + return -1; + } + + fwrite(buf, 1, size, fp); + fclose(fp); + + return 0; +} + +static int vtoykmod_read_file(char *name, char **buf) +{ + int size; + FILE *fp; + char *databuf; + + fp = fopen(name, "rb"); + if (!fp) + { + debug("failed to open %s %d\n", name, errno); + return -1; + } + + fseek(fp, 0, SEEK_END); + size = (int)ftell(fp); + fseek(fp, 0, SEEK_SET); + + databuf = malloc(size); + if (!databuf) + { + debug("failed to open malloc %d\n", size); + return -1; + } + + fread(databuf, 1, size, fp); + fclose(fp); + + *buf = databuf; + return size; +} + +static int vtoykmod_find_section64(char *buf, char *section, int *offset, int *len) +{ + uint16_t i; + int cmplen; + char *name = NULL; + char *strtbl = NULL; + Elf64_Ehdr *elf = NULL; + Elf64_Shdr *sec = NULL; + + cmplen = (int)strlen(section); + + elf = (Elf64_Ehdr *)buf; + sec = (Elf64_Shdr *)(buf + elf->e_shoff); + strtbl = buf + sec[elf->e_shstrndx].sh_offset; + + for (i = 0; i < elf->e_shnum; i++) + { + name = strtbl + sec[i].sh_name; + if (name && strncmp(name, section, cmplen) == 0) + { + *offset = (int)(sec[i].sh_offset); + *len = (int)(sec[i].sh_size); + return 0; + } + } + + return 1; +} + +static int vtoykmod_find_section32(char *buf, char *section, int *offset, int *len) +{ + uint16_t i; + int cmplen; + char *name = NULL; + char *strtbl = NULL; + Elf32_Ehdr *elf = NULL; + Elf32_Shdr *sec = NULL; + + cmplen = (int)strlen(section); + + elf = (Elf32_Ehdr *)buf; + sec = (Elf32_Shdr *)(buf + elf->e_shoff); + strtbl = buf + sec[elf->e_shstrndx].sh_offset; + + for (i = 0; i < elf->e_shnum; i++) + { + name = strtbl + sec[i].sh_name; + if (name && strncmp(name, section, cmplen) == 0) + { + *offset = (int)(sec[i].sh_offset); + *len = (int)(sec[i].sh_size); + return 0; + } + } + + return 1; +} + +static int vtoykmod_update_modcrc(char *oldmodver, int oldcnt, char *newmodver, int newcnt) +{ + int i, j; + struct modversion_info *pold, *pnew; + + pold = (struct modversion_info *)oldmodver; + pnew = (struct modversion_info *)newmodver; + + for (i = 0; i < oldcnt; i++) + { + for (j = 0; j < newcnt; j++) + { + if (strcmp(pold[i].name, pnew[j].name) == 0) + { + debug("CRC 0x%08lx --> 0x%08lx %s\n", pold[i].crc, pnew[i].crc, pold[i].name); + pold[i].crc = pnew[j].crc; + break; + } + } + } + + return 0; +} + +static int vtoykmod_update_vermagic(char *oldbuf, int oldsize, char *newbuf, int newsize, int *modver) +{ + int i = 0; + char *oldver = NULL; + char *newver = NULL; + + *modver = 0; + + for (i = 0; i < oldsize - 9; i++) + { + if (strncmp(oldbuf + i, "vermagic=", 9) == 0) + { + oldver = oldbuf + i + 9; + debug("Find old vermagic at %d <%s>\n", i, oldver); + break; + } + } + + for (i = 0; i < newsize - 9; i++) + { + if (strncmp(newbuf + i, "vermagic=", 9) == 0) + { + newver = newbuf + i + 9; + debug("Find new vermagic at %d <%s>\n", i, newver); + break; + } + } + + if (oldver && newver) + { + memcpy(oldver, newver, strlen(newver) + 1); + if (strstr(newver, "modversions")) + { + *modver = 1; + } + } + + return 0; +} + +int vtoykmod_update(char *oldko, char *newko) +{ + int rc = 0; + int modver = 0; + int oldoff, oldlen; + int newoff, newlen; + int oldsize, newsize; + char *newbuf, *oldbuf; + + oldsize = vtoykmod_read_file(oldko, &oldbuf); + newsize = vtoykmod_read_file(newko, &newbuf); + if (oldsize < 0 || newsize < 0) + { + return 1; + } + + /* 1: update vermagic */ + vtoykmod_update_vermagic(oldbuf, oldsize, newbuf, newsize, &modver); + + /* 2: update modversion crc */ + if (modver) + { + if (oldbuf[EI_CLASS] == ELFCLASS64) + { + rc = vtoykmod_find_section64(oldbuf, "__versions", &oldoff, &oldlen); + rc += vtoykmod_find_section64(newbuf, "__versions", &newoff, &newlen); + } + else + { + rc = vtoykmod_find_section32(oldbuf, "__versions", &oldoff, &oldlen); + rc += vtoykmod_find_section32(newbuf, "__versions", &newoff, &newlen); + } + + if (rc == 0) + { + vtoykmod_update_modcrc(oldbuf + oldoff, oldlen / 64, newbuf + newoff, newlen / 64); + } + } + else + { + debug("no need to proc modversions\n"); + } + + /* 3: update relocate address */ + if (oldbuf[EI_CLASS] == ELFCLASS64) + { + Elf64_Rela *oldRela, *newRela; + + rc = vtoykmod_find_section64(oldbuf, ".rela.gnu.linkonce.this_module", &oldoff, &oldlen); + rc += vtoykmod_find_section64(newbuf, ".rela.gnu.linkonce.this_module", &newoff, &newlen); + if (rc == 0) + { + oldRela = (Elf64_Rela *)(oldbuf + oldoff); + newRela = (Elf64_Rela *)(newbuf + newoff); + + debug("init_module rela: 0x%llx --> 0x%llx\n", (_ull)(oldRela[0].r_offset), (_ull)(newRela[0].r_offset)); + oldRela[0].r_offset = newRela[0].r_offset; + oldRela[0].r_addend = newRela[0].r_addend; + + debug("cleanup_module rela: 0x%llx --> 0x%llx\n", (_ull)(oldRela[1].r_offset), (_ull)(newRela[1].r_offset)); + oldRela[1].r_offset = newRela[1].r_offset; + oldRela[1].r_addend = newRela[1].r_addend; + } + else + { + debug("section .rela.gnu.linkonce.this_module not found\n"); + } + } + else + { + Elf32_Rel *oldRel, *newRel; + + rc = vtoykmod_find_section32(oldbuf, ".rel.gnu.linkonce.this_module", &oldoff, &oldlen); + rc += vtoykmod_find_section32(newbuf, ".rel.gnu.linkonce.this_module", &newoff, &newlen); + if (rc == 0) + { + oldRel = (Elf32_Rel *)(oldbuf + oldoff); + newRel = (Elf32_Rel *)(newbuf + newoff); + + debug("init_module rel: 0x%x --> 0x%x\n", oldRel[0].r_offset, newRel[0].r_offset); + oldRel[0].r_offset = newRel[0].r_offset; + + debug("cleanup_module rel: 0x%x --> 0x%x\n", oldRel[0].r_offset, newRel[0].r_offset); + oldRel[1].r_offset = newRel[1].r_offset; + } + else + { + debug("section .rel.gnu.linkonce.this_module not found\n"); + } + } + + vtoykmod_write_file(oldko, oldbuf, oldsize); + + free(oldbuf); + free(newbuf); + + return 0; +} + +int vtoykmod_fill_param(char **argv) +{ + int i; + int size; + char *buf = NULL; + ko_param *param; + unsigned char magic[16] = { magic_sig }; + + size = vtoykmod_read_file(argv[0], &buf); + if (size < 0) + { + return 1; + } + + for (i = 0; i < size; i++) + { + if (memcmp(buf + i, magic, 16) == 0) + { + debug("Find param magic at %d\n", i); + param = (ko_param *)(buf + i); + + param->struct_size = (unsigned long)sizeof(ko_param); + param->pgsize = strtoul(argv[1], NULL, 10); + param->printk_addr = strtoul(argv[2], NULL, 16); + param->ro_addr = strtoul(argv[3], NULL, 16); + param->rw_addr = strtoul(argv[4], NULL, 16); + param->sym_get_addr = strtoul(argv[5], NULL, 16); + param->sym_get_size = strtoul(argv[6], NULL, 10); + param->sym_put_addr = strtoul(argv[7], NULL, 16); + param->sym_put_size = strtoul(argv[8], NULL, 10); + param->reg_kprobe_addr = strtoul(argv[9], NULL, 16); + param->unreg_kprobe_addr = strtoul(argv[10], NULL, 16); + + debug("pgsize=%lu (%s)\n", param->pgsize, argv[1]); + debug("printk_addr=0x%lx (%s)\n", param->printk_addr, argv[2]); + debug("ro_addr=0x%lx (%s)\n", param->ro_addr, argv[3]); + debug("rw_addr=0x%lx (%s)\n", param->rw_addr, argv[4]); + debug("sym_get_addr=0x%lx (%s)\n", param->sym_get_addr, argv[5]); + debug("sym_get_size=%lu (%s)\n", param->sym_get_size, argv[6]); + debug("sym_put_addr=0x%lx (%s)\n", param->sym_put_addr, argv[7]); + debug("sym_put_size=%lu (%s)\n", param->sym_put_size, argv[8]); + debug("reg_kprobe_addr=0x%lx (%s)\n", param->reg_kprobe_addr, argv[9]); + debug("unreg_kprobe_addr=0x%lx (%s)\n", param->unreg_kprobe_addr, argv[10]); + + break; + } + } + + if (i >= size) + { + debug("### param magic not found \n"); + } + + vtoykmod_write_file(argv[0], buf, size); + + free(buf); + return 0; +} + +int vtoykmod_main(int argc, char **argv) +{ + int i; + + for (i = 0; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == 'v') + { + verbose = 1; + break; + } + } + + if (argv[1][0] == '-' && argv[1][1] == 'f') + { + return vtoykmod_fill_param(argv + 2); + } + else if (argv[1][0] == '-' && argv[1][1] == 'u') + { + return vtoykmod_update(argv[2], argv[3]); + } + + return 0; +} + +// wrapper main +#ifndef BUILD_VTOY_TOOL +int main(int argc, char **argv) +{ + return vtoykmod_main(argc, argv); +} +#endif + diff --git a/VtoyTool/vtoyksym.c b/VtoyTool/vtoyksym.c new file mode 100644 index 00000000..187f54c4 --- /dev/null +++ b/VtoyTool/vtoyksym.c @@ -0,0 +1,113 @@ +/****************************************************************************** + * vtoyksym.c ---- ventoy ksym + * + * Copyright (c) 2021, longpanda + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + * + */ + +#include +#include +#include +#include +#include + +static int verbose = 0; +#define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__) + +int vtoyksym_main(int argc, char **argv) +{ + int i; + unsigned long long addr1 = 0; + unsigned long long addr2 = 0; + char sym[256]; + char line[1024]; + const char *name = NULL; + FILE *fp; + + for (i = 0; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == 'p') + { + printf("%d", getpagesize()); + return 0; + } + } + + for (i = 0; i < argc; i++) + { + if (argv[i][0] == '-' && argv[i][1] == 'v') + { + verbose = 1; + break; + } + } + + name = argv[2] ? argv[2] : "/proc/kallsyms"; + fp = fopen(name, "r"); + if (!fp) + { + fprintf(stderr, "Failed to open file %s err:%d\n", name, errno); + return 1; + } + + debug("open %s success\n", name); + + snprintf(sym, sizeof(sym), " %s", argv[1]); + debug("lookup for <%s>\n", sym); + + while (fgets(line, sizeof(line), fp)) + { + if (strstr(line, sym)) + { + addr1 = strtoull(line, NULL, 16); + if (!fgets(line, sizeof(line), fp)) + { + addr1 = 0; + fprintf(stderr, "Failed to read next line\n"); + } + else + { + addr2 = strtoull(line, NULL, 16); + } + + debug("addr1=<0x%llx> addr2=<0x%llx>\n", addr1, addr2); + break; + } + } + + if (addr1 > addr2) + { + debug("Invalid addr range\n"); + printf("0 0\n"); + } + else + { + printf("0x%llx %llu\n", addr1, addr2 - addr1); + } + + fclose(fp); + + return 0; +} + +// wrapper main +#ifndef BUILD_VTOY_TOOL +int main(int argc, char **argv) +{ + return vtoyksym_main(argc, argv); +} +#endif + diff --git a/VtoyTool/vtoytool.c b/VtoyTool/vtoytool.c index 454063d2..f6896860 100644 --- a/VtoyTool/vtoytool.c +++ b/VtoyTool/vtoytool.c @@ -36,6 +36,8 @@ int vtoydm_main(int argc, char **argv); int vtoytool_install(int argc, char **argv); int vtoyloader_main(int argc, char **argv); int vtoyvine_main(int argc, char **argv); +int vtoyksym_main(int argc, char **argv); +int vtoykmod_main(int argc, char **argv); static char *g_vtoytool_name = NULL; static cmd_def g_cmd_list[] = @@ -44,6 +46,8 @@ static cmd_def g_cmd_list[] = { "vtoydump", vtoydump_main }, { "vtoydm", vtoydm_main }, { "loader", vtoyloader_main }, + { "vtoyksym", vtoyksym_main }, + { "vtoykmod", vtoykmod_main }, { "--install", vtoytool_install }, }; diff --git a/VtoyTool/vtoytool/00/vtoytool_32 b/VtoyTool/vtoytool/00/vtoytool_32 index b4f1dd77..0b430bd9 100644 Binary files a/VtoyTool/vtoytool/00/vtoytool_32 and b/VtoyTool/vtoytool/00/vtoytool_32 differ diff --git a/VtoyTool/vtoytool/00/vtoytool_64 b/VtoyTool/vtoytool/00/vtoytool_64 index 4c52cb54..7680fe37 100644 Binary files a/VtoyTool/vtoytool/00/vtoytool_64 and b/VtoyTool/vtoytool/00/vtoytool_64 differ diff --git a/VtoyTool/vtoytool/00/vtoytool_aa64 b/VtoyTool/vtoytool/00/vtoytool_aa64 index c0284031..c3ce4004 100644 Binary files a/VtoyTool/vtoytool/00/vtoytool_aa64 and b/VtoyTool/vtoytool/00/vtoytool_aa64 differ diff --git a/VtoyTool/vtoytool/00/vtoytool_m64e b/VtoyTool/vtoytool/00/vtoytool_m64e index 5deb5e77..d4d03d52 100644 Binary files a/VtoyTool/vtoytool/00/vtoytool_m64e and b/VtoyTool/vtoytool/00/vtoytool_m64e differ