]>
glassweightruler.freedombox.rocks Git - Ventoy.git/blob - VtoyTool/vtoykmod.c
1 /******************************************************************************
2 * vtoykmod.c ---- ventoy kmod
4 * Copyright (c) 2021, longpanda <admin@ventoy.net>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31 #define _ull unsigned long long
33 #define magic_sig 0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF
35 #define EI_NIDENT (16)
37 #define EI_MAG0 0 /* e_ident[] indexes */
47 #define ELFMAG0 0x7f /* EI_MAG */
51 #define ELFMAG "\177ELF"
54 #define ELFCLASSNONE 0 /* EI_CLASS */
59 #define ELFDATANONE 0 /* e_ident[EI_DATA] */
63 #define EV_NONE 0 /* e_version, EI_VERSION */
67 #define ELFOSABI_NONE 0
68 #define ELFOSABI_LINUX 3
77 unsigned char e_ident
[EI_NIDENT
]; /* Magic number and other info */
78 uint16_t e_type
; /* Object file type */
79 uint16_t e_machine
; /* Architecture */
80 uint32_t e_version
; /* Object file version */
81 uint32_t e_entry
; /* Entry point virtual address */
82 uint32_t e_phoff
; /* Program header table file offset */
83 uint32_t e_shoff
; /* Section header table file offset */
84 uint32_t e_flags
; /* Processor-specific flags */
85 uint16_t e_ehsize
; /* ELF header size in bytes */
86 uint16_t e_phentsize
; /* Program header table entry size */
87 uint16_t e_phnum
; /* Program header table entry count */
88 uint16_t e_shentsize
; /* Section header table entry size */
89 uint16_t e_shnum
; /* Section header table entry count */
90 uint16_t e_shstrndx
; /* Section header string table index */
95 unsigned char e_ident
[EI_NIDENT
]; /* Magic number and other info */
96 uint16_t e_type
; /* Object file type */
97 uint16_t e_machine
; /* Architecture */
98 uint32_t e_version
; /* Object file version */
99 uint64_t e_entry
; /* Entry point virtual address */
100 uint64_t e_phoff
; /* Program header table file offset */
101 uint64_t e_shoff
; /* Section header table file offset */
102 uint32_t e_flags
; /* Processor-specific flags */
103 uint16_t e_ehsize
; /* ELF header size in bytes */
104 uint16_t e_phentsize
; /* Program header table entry size */
105 uint16_t e_phnum
; /* Program header table entry count */
106 uint16_t e_shentsize
; /* Section header table entry size */
107 uint16_t e_shnum
; /* Section header table entry count */
108 uint16_t e_shstrndx
; /* Section header string table index */
113 uint32_t sh_name
; /* Section name (string tbl index) */
114 uint32_t sh_type
; /* Section type */
115 uint32_t sh_flags
; /* Section flags */
116 uint32_t sh_addr
; /* Section virtual addr at execution */
117 uint32_t sh_offset
; /* Section file offset */
118 uint32_t sh_size
; /* Section size in bytes */
119 uint32_t sh_link
; /* Link to another section */
120 uint32_t sh_info
; /* Additional section information */
121 uint32_t sh_addralign
; /* Section alignment */
122 uint32_t sh_entsize
; /* Entry size if section holds table */
127 uint32_t sh_name
; /* Section name (string tbl index) */
128 uint32_t sh_type
; /* Section type */
129 uint64_t sh_flags
; /* Section flags */
130 uint64_t sh_addr
; /* Section virtual addr at execution */
131 uint64_t sh_offset
; /* Section file offset */
132 uint64_t sh_size
; /* Section size in bytes */
133 uint32_t sh_link
; /* Link to another section */
134 uint32_t sh_info
; /* Additional section information */
135 uint64_t sh_addralign
; /* Section alignment */
136 uint64_t sh_entsize
; /* Entry size if section holds table */
139 typedef struct elf32_rel
{
144 typedef struct elf64_rel
{
145 uint64_t r_offset
; /* Location at which to apply the action */
146 uint64_t r_info
; /* index and type of relocation */
149 typedef struct elf32_rela
{
155 typedef struct elf64_rela
{
156 uint64_t r_offset
; /* Location at which to apply the action */
157 uint64_t r_info
; /* index and type of relocation */
158 int64_t r_addend
; /* Constant addend used to compute value */
162 struct modversion_info
{
164 char name
[64 - sizeof(unsigned long)];
168 typedef struct ko_param
170 unsigned char magic
[16];
171 unsigned long struct_size
;
172 unsigned long pgsize
;
173 unsigned long printk_addr
;
174 unsigned long ro_addr
;
175 unsigned long rw_addr
;
176 unsigned long reg_kprobe_addr
;
177 unsigned long unreg_kprobe_addr
;
178 unsigned long sym_get_addr
;
179 unsigned long sym_get_size
;
180 unsigned long sym_put_addr
;
181 unsigned long sym_put_size
;
182 unsigned long kv_major
;
184 unsigned long padding
[1];
189 static int verbose
= 0;
190 #define debug(fmt, ...) if(verbose) printf(fmt, ##__VA_ARGS__)
192 static int vtoykmod_write_file(char *name
, void *buf
, int size
)
196 fp
= fopen(name
, "wb+");
202 fwrite(buf
, 1, size
, fp
);
208 static int vtoykmod_read_file(char *name
, char **buf
)
214 fp
= fopen(name
, "rb");
217 debug("failed to open %s %d\n", name
, errno
);
221 fseek(fp
, 0, SEEK_END
);
222 size
= (int)ftell(fp
);
223 fseek(fp
, 0, SEEK_SET
);
225 databuf
= malloc(size
);
228 debug("failed to open malloc %d\n", size
);
232 fread(databuf
, 1, size
, fp
);
239 static int vtoykmod_find_section64(char *buf
, char *section
, int *offset
, int *len
)
245 Elf64_Ehdr
*elf
= NULL
;
246 Elf64_Shdr
*sec
= NULL
;
248 cmplen
= (int)strlen(section
);
250 elf
= (Elf64_Ehdr
*)buf
;
251 sec
= (Elf64_Shdr
*)(buf
+ elf
->e_shoff
);
252 strtbl
= buf
+ sec
[elf
->e_shstrndx
].sh_offset
;
254 for (i
= 0; i
< elf
->e_shnum
; i
++)
256 name
= strtbl
+ sec
[i
].sh_name
;
257 if (name
&& strncmp(name
, section
, cmplen
) == 0)
259 *offset
= (int)(sec
[i
].sh_offset
);
260 *len
= (int)(sec
[i
].sh_size
);
268 static int vtoykmod_find_section32(char *buf
, char *section
, int *offset
, int *len
)
274 Elf32_Ehdr
*elf
= NULL
;
275 Elf32_Shdr
*sec
= NULL
;
277 cmplen
= (int)strlen(section
);
279 elf
= (Elf32_Ehdr
*)buf
;
280 sec
= (Elf32_Shdr
*)(buf
+ elf
->e_shoff
);
281 strtbl
= buf
+ sec
[elf
->e_shstrndx
].sh_offset
;
283 for (i
= 0; i
< elf
->e_shnum
; i
++)
285 name
= strtbl
+ sec
[i
].sh_name
;
286 if (name
&& strncmp(name
, section
, cmplen
) == 0)
288 *offset
= (int)(sec
[i
].sh_offset
);
289 *len
= (int)(sec
[i
].sh_size
);
297 static int vtoykmod_update_modcrc(char *oldmodver
, int oldcnt
, char *newmodver
, int newcnt
)
300 struct modversion_info
*pold
, *pnew
;
302 pold
= (struct modversion_info
*)oldmodver
;
303 pnew
= (struct modversion_info
*)newmodver
;
305 for (i
= 0; i
< oldcnt
; i
++)
307 for (j
= 0; j
< newcnt
; j
++)
309 if (strcmp(pold
[i
].name
, pnew
[j
].name
) == 0)
311 debug("CRC 0x%08lx --> 0x%08lx %s\n", pold
[i
].crc
, pnew
[i
].crc
, pold
[i
].name
);
312 pold
[i
].crc
= pnew
[j
].crc
;
321 static int vtoykmod_update_vermagic(char *oldbuf
, int oldsize
, char *newbuf
, int newsize
, int *modver
)
329 for (i
= 0; i
< oldsize
- 9; i
++)
331 if (strncmp(oldbuf
+ i
, "vermagic=", 9) == 0)
333 oldver
= oldbuf
+ i
+ 9;
334 debug("Find old vermagic at %d <%s>\n", i
, oldver
);
339 for (i
= 0; i
< newsize
- 9; i
++)
341 if (strncmp(newbuf
+ i
, "vermagic=", 9) == 0)
343 newver
= newbuf
+ i
+ 9;
344 debug("Find new vermagic at %d <%s>\n", i
, newver
);
349 if (oldver
&& newver
)
351 memcpy(oldver
, newver
, strlen(newver
) + 1);
352 //if (strstr(newver, "modversions"))
361 int vtoykmod_update(char *oldko
, char *newko
)
367 int oldsize
, newsize
;
368 char *newbuf
, *oldbuf
;
370 oldsize
= vtoykmod_read_file(oldko
, &oldbuf
);
371 newsize
= vtoykmod_read_file(newko
, &newbuf
);
372 if (oldsize
< 0 || newsize
< 0)
377 /* 1: update vermagic */
378 vtoykmod_update_vermagic(oldbuf
, oldsize
, newbuf
, newsize
, &modver
);
380 /* 2: update modversion crc */
383 if (oldbuf
[EI_CLASS
] == ELFCLASS64
)
385 rc
= vtoykmod_find_section64(oldbuf
, "__versions", &oldoff
, &oldlen
);
386 rc
+= vtoykmod_find_section64(newbuf
, "__versions", &newoff
, &newlen
);
390 rc
= vtoykmod_find_section32(oldbuf
, "__versions", &oldoff
, &oldlen
);
391 rc
+= vtoykmod_find_section32(newbuf
, "__versions", &newoff
, &newlen
);
396 vtoykmod_update_modcrc(oldbuf
+ oldoff
, oldlen
/ 64, newbuf
+ newoff
, newlen
/ 64);
401 debug("no need to proc modversions\n");
404 /* 3: update relocate address */
405 if (oldbuf
[EI_CLASS
] == ELFCLASS64
)
407 Elf64_Rela
*oldRela
, *newRela
;
409 rc
= vtoykmod_find_section64(oldbuf
, ".rela.gnu.linkonce.this_module", &oldoff
, &oldlen
);
410 rc
+= vtoykmod_find_section64(newbuf
, ".rela.gnu.linkonce.this_module", &newoff
, &newlen
);
413 oldRela
= (Elf64_Rela
*)(oldbuf
+ oldoff
);
414 newRela
= (Elf64_Rela
*)(newbuf
+ newoff
);
416 debug("init_module rela: 0x%llx --> 0x%llx\n", (_ull
)(oldRela
[0].r_offset
), (_ull
)(newRela
[0].r_offset
));
417 oldRela
[0].r_offset
= newRela
[0].r_offset
;
418 oldRela
[0].r_addend
= newRela
[0].r_addend
;
420 debug("cleanup_module rela: 0x%llx --> 0x%llx\n", (_ull
)(oldRela
[1].r_offset
), (_ull
)(newRela
[1].r_offset
));
421 oldRela
[1].r_offset
= newRela
[1].r_offset
;
422 oldRela
[1].r_addend
= newRela
[1].r_addend
;
426 debug("section .rela.gnu.linkonce.this_module not found\n");
431 Elf32_Rel
*oldRel
, *newRel
;
433 rc
= vtoykmod_find_section32(oldbuf
, ".rel.gnu.linkonce.this_module", &oldoff
, &oldlen
);
434 rc
+= vtoykmod_find_section32(newbuf
, ".rel.gnu.linkonce.this_module", &newoff
, &newlen
);
437 oldRel
= (Elf32_Rel
*)(oldbuf
+ oldoff
);
438 newRel
= (Elf32_Rel
*)(newbuf
+ newoff
);
440 debug("init_module rel: 0x%x --> 0x%x\n", oldRel
[0].r_offset
, newRel
[0].r_offset
);
441 oldRel
[0].r_offset
= newRel
[0].r_offset
;
443 debug("cleanup_module rel: 0x%x --> 0x%x\n", oldRel
[0].r_offset
, newRel
[0].r_offset
);
444 oldRel
[1].r_offset
= newRel
[1].r_offset
;
448 debug("section .rel.gnu.linkonce.this_module not found\n");
452 vtoykmod_write_file(oldko
, oldbuf
, oldsize
);
460 int vtoykmod_fill_param(char **argv
)
466 unsigned char magic
[16] = { magic_sig
};
468 size
= vtoykmod_read_file(argv
[0], &buf
);
474 for (i
= 0; i
< size
; i
++)
476 if (memcmp(buf
+ i
, magic
, 16) == 0)
478 debug("Find param magic at %d\n", i
);
479 param
= (ko_param
*)(buf
+ i
);
481 param
->struct_size
= (unsigned long)sizeof(ko_param
);
482 param
->pgsize
= strtoul(argv
[1], NULL
, 10);
483 param
->printk_addr
= strtoul(argv
[2], NULL
, 16);
484 param
->ro_addr
= strtoul(argv
[3], NULL
, 16);
485 param
->rw_addr
= strtoul(argv
[4], NULL
, 16);
486 param
->sym_get_addr
= strtoul(argv
[5], NULL
, 16);
487 param
->sym_get_size
= strtoul(argv
[6], NULL
, 10);
488 param
->sym_put_addr
= strtoul(argv
[7], NULL
, 16);
489 param
->sym_put_size
= strtoul(argv
[8], NULL
, 10);
490 param
->reg_kprobe_addr
= strtoul(argv
[9], NULL
, 16);
491 param
->unreg_kprobe_addr
= strtoul(argv
[10], NULL
, 16);
492 param
->kv_major
= (unsigned long)(argv
[11][0] - '0');
493 param
->ibt
= strtoul(argv
[12], NULL
, 16);;
495 debug("pgsize=%lu (%s)\n", param
->pgsize
, argv
[1]);
496 debug("printk_addr=0x%lx (%s)\n", param
->printk_addr
, argv
[2]);
497 debug("ro_addr=0x%lx (%s)\n", param
->ro_addr
, argv
[3]);
498 debug("rw_addr=0x%lx (%s)\n", param
->rw_addr
, argv
[4]);
499 debug("sym_get_addr=0x%lx (%s)\n", param
->sym_get_addr
, argv
[5]);
500 debug("sym_get_size=%lu (%s)\n", param
->sym_get_size
, argv
[6]);
501 debug("sym_put_addr=0x%lx (%s)\n", param
->sym_put_addr
, argv
[7]);
502 debug("sym_put_size=%lu (%s)\n", param
->sym_put_size
, argv
[8]);
503 debug("reg_kprobe_addr=0x%lx (%s)\n", param
->reg_kprobe_addr
, argv
[9]);
504 debug("unreg_kprobe_addr=0x%lx (%s)\n", param
->unreg_kprobe_addr
, argv
[10]);
505 debug("kv_major=%lu (%s)\n", param
->kv_major
, argv
[11]);
506 debug("ibt=0x%lx (%s)\n", param
->ibt
, argv
[12]);
514 debug("### param magic not found \n");
517 vtoykmod_write_file(argv
[0], buf
, size
);
524 static int vtoykmod_check_ibt(void)
526 uint32_t eax
= 0, ebx
= 0, ecx
= 0, edx
= 0;
528 __cpuid_count(7, 0, eax
, ebx
, ecx
, edx
);
537 static int vtoykmod_check_ibt(void)
543 int vtoykmod_main(int argc
, char **argv
)
547 for (i
= 0; i
< argc
; i
++)
549 if (argv
[i
][0] == '-' && argv
[i
][1] == 'v')
556 if (argv
[1][0] == '-' && argv
[1][1] == 'f')
558 return vtoykmod_fill_param(argv
+ 2);
560 else if (argv
[1][0] == '-' && argv
[1][1] == 'u')
562 return vtoykmod_update(argv
[2], argv
[3]);
564 else if (argv
[1][0] == '-' && argv
[1][1] == 'I')
566 return vtoykmod_check_ibt();
573 #ifndef BUILD_VTOY_TOOL
574 int main(int argc
, char **argv
)
576 return vtoykmod_main(argc
, argv
);