1.0.64 release

pull/1401/head
longpanda 2 years ago
parent 25dc323522
commit 1f49265f29

@ -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/

@ -1,5 +1,8 @@
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
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);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -0,0 +1,7 @@
obj-m += dm_patch.o
EXTRA_CFLAGS := -Wall
dm_patch-objs := dmpatch.o

@ -0,0 +1,179 @@
/******************************************************************************
* dmpatch.c ---- patch for device-mapper
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kallsyms.h>
#include <linux/mutex.h>
#include <linux/mempool.h>
#include <linux/delay.h>
#include <linux/wait.h>
#include <linux/slab.h>
#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 <admin@ventoy.net>");
MODULE_LICENSE("GPL");

@ -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 <include/linux/module.h>
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

@ -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);
}

@ -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);

@ -42,6 +42,7 @@
DebugLib
[Guids]
gEfiGlobalVariableGuid
gShellVariableGuid
gEfiVirtualCdGuid
gEfiFileInfoGuid

@ -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++)
{

@ -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

@ -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

@ -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
}

@ -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

@ -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);

@ -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];

@ -1 +1 @@
20211203 17:44:10
20220108 22:41:02

@ -723,7 +723,7 @@
<footer class="main-footer">
<div class="pull-right hidden-xs">
<b id="plugson_build_date">20211203 17:44:10</b>
<b id="plugson_build_date">20220108 22:41:02</b>
</div>
<strong><a href="https://www.ventoy.net" target="_blank">https://www.ventoy.net</a></strong>
</footer>

@ -337,6 +337,57 @@
</div><!-- /.box -->
<div class="box box-primary box-solid">
<div class="box-header with-border">
<h3 class="box-title" style="font-size: 14px;font-weight: bold;">VTOY_LINUX_REMOUNT
<span id="id_span_desc_cn"> —— Linux 启动后继续访问ISO文件所在分区</span></h3>
<div class="box-tools pull-right">
<button class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-minus"></i></button>
</div><!-- /.box-tools -->
</div><!-- /.box-header -->
<div class="box-body no-padding">
<table class="table table-bordered no-padding">
<tr style="font-weight:bold;">
<td class="td_ctrl_col" id="td_title_setting">选项设置</td>
<td>
<label class="radio-inline">
<input type="radio" id="id_ctrl_linux_remount_radio0" name="id_ctrl_linux_remount_radio" data-type="0" value="0"/> <span style="font-weight:bold;">0</span>
</label>&nbsp;&nbsp;&nbsp;&nbsp;
<label class="radio-inline">
<input type="radio" id="id_ctrl_linux_remount_radio1" name="id_ctrl_linux_remount_radio" data-type="1" value="1"/> <span style="font-weight:bold;">1</span>
</label>
</td>
</tr>
<tr id="tr_title_desc_cn">
<td class="td_ctrl_col" id="td_title_desc">选项说明</td>
<td>
<code style="font-weight: bold;">0</code> Linux启动后不需要继续访问ISO文件所在的分区。<br/>
<code style="font-weight: bold;">1</code> Linux启动后需要继续访问ISO文件所在的分区。<br/><br/>
该选项只对 Linux 系统镜像有效。<br/>
默认情况下受Linux内核相关功能的限制对于Linux系统在启动后无法继续访问ISO文件所在的分区。在mount的时候会提示 device busy。<br/>
如果这里选择 1则 Ventoy 会尝试通过一些特殊的手段绕过内核的这个限制,但是这个功能是实验性质的,没有经过大规模和长时间的验证。
</td>
</tr>
<tr id="tr_title_desc_en">
<td class="td_ctrl_col" id="td_title_desc">Option Description</td>
<td>
<code style="font-weight: bold;">0</code> I don't need to access the image partition after boot.<br/>
<code style="font-weight: bold;">1</code> I need to access the image partition after boot. <br/><br/>
This option is only avaliable for Linux distro image files. <br/>
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).<br/>
If you select 1 here, Ventoy will try to bypass the restriction with some special mechanism.<br/>
But it should be noted that, this is an experimental feature and is not fully tested.
</td>
</tr>
</table>
</div><!-- /.box-body -->
</div><!-- /.box -->
<div class="box box-primary box-solid">
@ -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,

@ -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.<br/>
Both MBR and GPT partition style are supported in the same way.<br/>
Most type of OS supported(Windows/WinPE/Linux/Unix/ChromeOS/Vmware/Xen...) <br/>
770+ ISO files are tested (<a href="https://www.ventoy.net/en/isolist.html">List</a>). 90%+ distros in <a href="https://distrowatch.com/">distrowatch.com</a> supported (<a href="https://www.ventoy.net/en/distrowatch.html">Details</a>). <br/>
780+ ISO files are tested (<a href="https://www.ventoy.net/en/isolist.html">List</a>). 90%+ distros in <a href="https://distrowatch.com/">distrowatch.com</a> supported (<a href="https://www.ventoy.net/en/distrowatch.html">Details</a>). <br/>
<br/>Official Website: <a href=https://www.ventoy.net>https://www.ventoy.net</a>
</h4>
@ -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

@ -0,0 +1,546 @@
/******************************************************************************
* vtoykmod.c ---- ventoy kmod
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#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

@ -0,0 +1,113 @@
/******************************************************************************
* vtoyksym.c ---- ventoy ksym
*
* Copyright (c) 2021, longpanda <admin@ventoy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
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

@ -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 },
};

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save