mirror of
https://github.com/dynup/kpatch
synced 2025-04-22 15:05:20 +00:00
commit
7618f12f45
@ -1,5 +1,5 @@
|
|||||||
# make rules
|
# make rules
|
||||||
KPATCH_BUILD ?= /usr/src/kernels/$(shell uname -r)
|
KPATCH_BUILD ?= /lib/modules/$(shell uname -r)/build
|
||||||
THISDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
THISDIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST))))
|
||||||
|
|
||||||
ifeq ($(wildcard $(KPATCH_BUILD)),)
|
ifeq ($(wildcard $(KPATCH_BUILD)),)
|
||||||
|
@ -171,7 +171,8 @@ static void create_symlist(struct elf *elf, struct symlist *symlist)
|
|||||||
if (!data)
|
if (!data)
|
||||||
ERROR("elf_getdata");
|
ERROR("elf_getdata");
|
||||||
|
|
||||||
/* find (local) function symbols
|
/*
|
||||||
|
* find (local) function symbols
|
||||||
* NOTE: If the function symbol is in the kpatch-gen file, it needs
|
* NOTE: If the function symbol is in the kpatch-gen file, it needs
|
||||||
* to be patched. If the function didn't need to be patched,
|
* to be patched. If the function didn't need to be patched,
|
||||||
* it wouldn't have been incldued in the kpatch-gen file.
|
* it wouldn't have been incldued in the kpatch-gen file.
|
||||||
@ -228,26 +229,6 @@ int main(int argc, char **argv)
|
|||||||
create_symlist(&elf, &symlist);
|
create_symlist(&elf, &symlist);
|
||||||
create_symlist(&elfv, &symlistv);
|
create_symlist(&elfv, &symlistv);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* lookup patched functions in vmlinux */
|
|
||||||
for_each_sym(&symlist, cur) {
|
|
||||||
if (GELF_ST_TYPE(cur->sym.st_info) != STT_FUNC)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
printf("found patched function %s\n", cur->name);
|
|
||||||
|
|
||||||
vsym = find_symbol_by_name(&symlistv, cur->name);
|
|
||||||
if (!vsym)
|
|
||||||
ERROR("couldn't find patched function in vmlinux");
|
|
||||||
cur->vm_addr = vsym->sym.st_value;
|
|
||||||
cur->vm_len = vsym->sym.st_size;
|
|
||||||
cur->action = PATCH;
|
|
||||||
printf("original function at address %016lx (length %d)\n",
|
|
||||||
cur->vm_addr, cur->vm_len);
|
|
||||||
patches_nr++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* lookup non-exported globals and insert vmlinux address */
|
/* lookup non-exported globals and insert vmlinux address */
|
||||||
for_each_sym(&symlist, cur) {
|
for_each_sym(&symlist, cur) {
|
||||||
if (GELF_ST_TYPE(cur->sym.st_info) != STT_NOTYPE ||
|
if (GELF_ST_TYPE(cur->sym.st_info) != STT_NOTYPE ||
|
||||||
@ -279,83 +260,13 @@ int main(int argc, char **argv)
|
|||||||
elf_end(elfv.elf);
|
elf_end(elfv.elf);
|
||||||
close(elfv.fd);
|
close(elfv.fd);
|
||||||
|
|
||||||
#if 0
|
|
||||||
printf("patches_nr = %d\n", patches_nr);
|
|
||||||
|
|
||||||
/* allocate new section data buffers */
|
|
||||||
patches_size = sizeof(*patches_data) * patches_nr;
|
|
||||||
patches_data = malloc(patches_size);
|
|
||||||
if (!patches_data)
|
|
||||||
ERROR("malloc");
|
|
||||||
memset(patches_data, 0, patches_size);
|
|
||||||
|
|
||||||
relas_size = sizeof(*relas_data) * patches_nr;
|
|
||||||
relas_data = malloc(relas_size);
|
|
||||||
if (!relas_data)
|
|
||||||
ERROR("malloc");
|
|
||||||
memset(relas_data, 0, relas_size);
|
|
||||||
|
|
||||||
printf("patches_size = %d\n",patches_size);
|
|
||||||
printf("relas_size = %d\n",relas_size);
|
|
||||||
|
|
||||||
/* populate new section data buffers */
|
|
||||||
i = 0;
|
|
||||||
for_each_sym(&symlist, cur) {
|
|
||||||
if (cur->action != PATCH)
|
|
||||||
continue;
|
|
||||||
patches_data[i].orig = cur->vm_addr;
|
|
||||||
patches_data[i].orig_end = cur->vm_addr + cur->vm_len;
|
|
||||||
relas_data[i].r_offset = i * sizeof(struct kpatch_patch);
|
|
||||||
relas_data[i].r_info = GELF_R_INFO(cur->index, R_X86_64_64);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get next section index from elf header */
|
|
||||||
if (!gelf_getehdr(elf.elf, &eh))
|
|
||||||
ERROR("gelf_getehdr");
|
|
||||||
patches_index = eh.e_shnum;
|
|
||||||
relas_index = patches_index + 1;
|
|
||||||
|
|
||||||
/* add new section names to shstrtab */
|
|
||||||
scn = elf.shstrtab.scn;
|
|
||||||
shp = &elf.shstrtab.sh;
|
|
||||||
|
|
||||||
data = elf_getdata(scn, NULL);
|
|
||||||
if (!data)
|
|
||||||
ERROR("elf_getdata");
|
|
||||||
|
|
||||||
len = strlen(".patches") + strlen(".rela.patches") + 2;
|
|
||||||
buf = malloc(data->d_size + len);
|
|
||||||
memcpy(buf, data->d_buf, data->d_size);
|
|
||||||
|
|
||||||
data->d_buf = buf;
|
|
||||||
buf = data->d_buf + data->d_size;
|
|
||||||
|
|
||||||
len = strlen(".patches") + 1;
|
|
||||||
memcpy(buf, ".patches", len);
|
|
||||||
patches_offset = buf - data->d_buf;
|
|
||||||
printf("patches_offset = %d\n", patches_offset);
|
|
||||||
buf += len;
|
|
||||||
len = strlen(".rela.patches") + 1;
|
|
||||||
memcpy(buf, ".rela.patches", len);
|
|
||||||
relas_offset = buf - data->d_buf;
|
|
||||||
printf("relas_offset = %d\n", relas_offset);
|
|
||||||
buf += len;
|
|
||||||
data->d_size = buf - data->d_buf;
|
|
||||||
|
|
||||||
if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
|
|
||||||
ERROR("elf_flagdata");
|
|
||||||
|
|
||||||
if (!gelf_update_shdr(scn, shp))
|
|
||||||
ERROR("gelf_update_shdr");
|
|
||||||
|
|
||||||
/* get symtab vars */
|
|
||||||
#endif
|
|
||||||
find_section_by_name(&elf, ".symtab", &symtab);
|
find_section_by_name(&elf, ".symtab", &symtab);
|
||||||
scn = symtab.scn;
|
scn = symtab.scn;
|
||||||
|
|
||||||
data = elf_getdata(scn, NULL);
|
data = elf_getdata(scn, NULL);
|
||||||
if (!data)
|
if (!data)
|
||||||
ERROR("elf_getdata");
|
ERROR("elf_getdata");
|
||||||
|
|
||||||
/* update LINK symbols */
|
/* update LINK symbols */
|
||||||
for_each_sym(&symlist, cur) {
|
for_each_sym(&symlist, cur) {
|
||||||
if (cur->action != LINK)
|
if (cur->action != LINK)
|
||||||
@ -366,84 +277,6 @@ int main(int argc, char **argv)
|
|||||||
gelf_update_sym(data, cur->index, &cur->sym);
|
gelf_update_sym(data, cur->index, &cur->sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* add new section symbols to symtab */
|
|
||||||
len = sizeof(GElf_Sym) * 2;
|
|
||||||
buf = malloc(data->d_size + len);
|
|
||||||
memcpy(buf, data->d_buf, data->d_size);
|
|
||||||
|
|
||||||
data->d_buf = buf;
|
|
||||||
buf = data->d_buf + data->d_size;
|
|
||||||
|
|
||||||
memset(&sym, 0, sizeof(GElf_Sym));
|
|
||||||
sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION);
|
|
||||||
|
|
||||||
len = sizeof(GElf_Sym);
|
|
||||||
sym.st_shndx = patches_index;
|
|
||||||
memcpy(buf, &sym, len);
|
|
||||||
buf += len;
|
|
||||||
sym.st_shndx = relas_index;
|
|
||||||
memcpy(buf, &sym, len);
|
|
||||||
buf += len;
|
|
||||||
data->d_size = buf - data->d_buf;
|
|
||||||
|
|
||||||
if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
|
|
||||||
ERROR("elf_flagdata");
|
|
||||||
|
|
||||||
if (!gelf_update_shdr(scn, shp))
|
|
||||||
ERROR("gelf_update_shdr");
|
|
||||||
|
|
||||||
/* create .patches section */
|
|
||||||
scn = elf_newscn(elf.elf);
|
|
||||||
if (!scn)
|
|
||||||
ERROR("elf_newscn");
|
|
||||||
|
|
||||||
data = elf_newdata(scn);
|
|
||||||
if (!data)
|
|
||||||
ERROR("elf_newdata");
|
|
||||||
|
|
||||||
data->d_size = patches_size;
|
|
||||||
data->d_buf = patches_data;
|
|
||||||
data->d_type = ELF_T_BYTE;
|
|
||||||
|
|
||||||
memset(&sh, 0, sizeof(sh));
|
|
||||||
sh.sh_type = SHT_PROGBITS;
|
|
||||||
sh.sh_name = patches_offset;
|
|
||||||
sh.sh_entsize = sizeof(struct kpatch_patch);
|
|
||||||
sh.sh_addralign = 8;
|
|
||||||
sh.sh_flags = SHF_ALLOC;
|
|
||||||
sh.sh_size = data->d_size;
|
|
||||||
|
|
||||||
if (!gelf_update_shdr(scn, &sh))
|
|
||||||
ERROR("gelf_update_shdr");
|
|
||||||
|
|
||||||
/* create .rela.patches section */
|
|
||||||
scn = elf_newscn(elf.elf);
|
|
||||||
if (!scn)
|
|
||||||
ERROR("elf_newscn");
|
|
||||||
|
|
||||||
data = elf_newdata(scn);
|
|
||||||
if (!data)
|
|
||||||
ERROR("elf_newdata");
|
|
||||||
|
|
||||||
data->d_size = relas_size;
|
|
||||||
data->d_buf = relas_data;
|
|
||||||
data->d_type = ELF_T_RELA;
|
|
||||||
|
|
||||||
memset(&sh, 0, sizeof(sh));
|
|
||||||
sh.sh_type = SHT_RELA;
|
|
||||||
sh.sh_name = relas_offset;
|
|
||||||
sh.sh_entsize = sizeof(GElf_Rela);
|
|
||||||
sh.sh_addralign = 8;
|
|
||||||
sh.sh_flags = SHF_ALLOC;
|
|
||||||
sh.sh_link = elf_ndxscn(elf.symtab.scn);
|
|
||||||
sh.sh_info = patches_index;
|
|
||||||
sh.sh_size = data->d_size;
|
|
||||||
|
|
||||||
if (!gelf_update_shdr(scn, &sh))
|
|
||||||
ERROR("gelf_update_shdr");
|
|
||||||
|
|
||||||
#endif
|
|
||||||
if (elf_update(elf.elf, ELF_C_WRITE) < 0)
|
if (elf_update(elf.elf, ELF_C_WRITE) < 0)
|
||||||
ERROR("elf_update %s", elf_errmsg(-1));
|
ERROR("elf_update %s", elf_errmsg(-1));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user