mirror of https://github.com/ventoy/Ventoy.git
parent
25dc323522
commit
1f49265f29
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
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1 +1 @@
|
||||
20211203 17:44:10
|
||||
20220108 22:41:02
|
@ -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);
|
||||