Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kpatch-build/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
include ../Makefile.inc

CFLAGS += -std=gnu11 -MMD -MP -I../kmod/patch -Iinsn -Wall -Wsign-compare \
-Wconversion -Wno-sign-conversion -g -Werror
-Wconversion -Wno-sign-conversion -g -Werror -D_GNU_SOURCE
LDLIBS = -lelf

TARGETS = create-diff-object create-klp-module create-kpatch-module
Expand Down
78 changes: 78 additions & 0 deletions kpatch-build/create-diff-object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1804,6 +1804,74 @@ static void kpatch_include_symbol(struct symbol *sym)
kpatch_include_section(sym->sec);
}

/*
* Module namespaces are saved as key value pairs in the .modinfo
* section. For modules, they are in the form "import_ns=<value" and
* for built-ins, "<object>.import_ns=<value>". Extract just these
* namespace strings from the patched .modinfo to put back into the
* output ELF.
*/
static void kpatch_get_modinfo_namespaces(struct kpatch_elf *kelf_patched,
struct section *sec)
{
char *data = NULL;
int data_len = 0;
const char *p, *end;

if (!sec->data || !sec->data->d_buf)
return;

/*
* Copy all the "import_ns=<value>" strings into
* a temporary data array (ignore other key-values)
*/
p = sec->data->d_buf;
end = p + sec->sh.sh_size;

while (p < end) {
const char *match;
char *new_data;
size_t match_len;

match = memmem(p, end - p, "import_ns=", 10);
if (!match)
break;
match_len = strlen(match) + 1;

new_data = realloc(data, data_len + match_len);
if (!new_data)
ERROR("realloc");
data = new_data;

memcpy(data + data_len, match, match_len);
data_len += (int) match_len;

p = match + match_len;
}

/*
* Update the patched elf modinfo data array with namespace
* strings for kpatch_put_modinfo_namespaces()
*/
kelf_patched->modinfo_data = data;
kelf_patched->modinfo_data_len = data_len;
}

static void kpatch_put_modinfo_namespaces(struct kpatch_elf *kelf_patched,
struct kpatch_elf *kelf_out)
{
struct section *sec;

if (!kelf_patched->modinfo_data)
return;

sec = create_section(kelf_out, ".modinfo",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be skipped if .modinfo doesn't exist in the patched object?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, no need to create an empty section.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I suppose it should only create .modinfo if kelf_patched->modinfo_data is non-NULL?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, that's a better test, as it would skip instances with .modinfo but no imports.

kelf_patched->modinfo_data_len, 1);
memcpy(sec->data->d_buf, kelf_patched->modinfo_data,
kelf_patched->modinfo_data_len);
sec->include = 1;
}

static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
{
struct section *sec;
Expand Down Expand Up @@ -2870,6 +2938,15 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
!strncmp(sec->name, ".llvm.", 6))
sec->ignore = 1;

/*
* Ignore .modinfo changes, but do stash any module
* namespaces for kpatch_put_modinfo_namespaces()
*/
if (!strcmp(sec->name, ".modinfo")) {
kpatch_get_modinfo_namespaces(kelf, sec);
sec->ignore = 1;
}

if (kelf->arch == X86_64) {
if (!strcmp(sec->name, ".rela__patchable_function_entries") ||
!strcmp(sec->name, "__patchable_function_entries"))
Expand Down Expand Up @@ -4250,6 +4327,7 @@ int main(int argc, char *argv[])

/* this is destructive to kelf_patched */
kpatch_migrate_included_elements(kelf_patched, &kelf_out);
kpatch_put_modinfo_namespaces(kelf_patched, kelf_out);

/*
* Teardown kelf_patched since we shouldn't access sections or symbols
Expand Down
31 changes: 21 additions & 10 deletions kpatch-build/kpatch-elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,19 +896,12 @@ void kpatch_create_symtab(struct kpatch_elf *kelf)
symtab->sh.sh_info = nr_local;
}

struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
int entsize, int nr)
struct section *create_section(struct kpatch_elf *kelf, char *name,
int entsize, int nr)
{
char *relaname;
struct section *sec, *relasec;
struct section *sec;
int size = entsize * nr;

relaname = malloc(strlen(name) + strlen(".rela") + 1);
if (!relaname)
ERROR("malloc");
strcpy(relaname, ".rela");
strcat(relaname, name);

/* allocate text section resources */
ALLOC_LINK(sec, &kelf->sections);
sec->name = name;
Expand All @@ -931,6 +924,24 @@ struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
sec->sh.sh_flags = SHF_ALLOC;
sec->sh.sh_size = size;

return sec;

}

struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
int entsize, int nr)
{
char *relaname;
struct section *sec, *relasec;

relaname = malloc(strlen(name) + strlen(".rela") + 1);
if (!relaname)
ERROR("malloc");
strcpy(relaname, ".rela");
strcat(relaname, name);

sec = create_section(kelf, name, entsize, nr);

/* allocate rela section resources */
ALLOC_LINK(relasec, &kelf->sections);
relasec->name = relaname;
Expand Down
4 changes: 4 additions & 0 deletions kpatch-build/kpatch-elf.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ struct kpatch_elf {
int fd;
bool has_pfe;
bool pfe_ordered;
int modinfo_data_len;
char *modinfo_data;
};

/*******************
Expand Down Expand Up @@ -181,6 +183,8 @@ void print_strtab(char *buf, size_t size);
void kpatch_create_shstrtab(struct kpatch_elf *kelf);
void kpatch_create_strtab(struct kpatch_elf *kelf);
void kpatch_create_symtab(struct kpatch_elf *kelf);
struct section *create_section(struct kpatch_elf *kelf, char *name,
int entsize, int nr);
struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
int entsize, int nr);
void kpatch_remove_and_free_section(struct kpatch_elf *kelf, char *secname);
Expand Down
2 changes: 1 addition & 1 deletion test/unit/objs