mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00:00
Merge branch 'for-6.4/doc' into for-linus
This commit is contained in:
commit
c9c8133080
7 changed files with 36 additions and 34 deletions
|
@ -1,8 +1,8 @@
|
||||||
===========================
|
===========================
|
||||||
Livepatch module Elf format
|
Livepatch module ELF format
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
This document outlines the Elf format requirements that livepatch modules must follow.
|
This document outlines the ELF format requirements that livepatch modules must follow.
|
||||||
|
|
||||||
|
|
||||||
.. Table of Contents
|
.. Table of Contents
|
||||||
|
@ -20,17 +20,17 @@ code. So, instead of duplicating code and re-implementing what the module
|
||||||
loader can already do, livepatch leverages existing code in the module
|
loader can already do, livepatch leverages existing code in the module
|
||||||
loader to perform the all the arch-specific relocation work. Specifically,
|
loader to perform the all the arch-specific relocation work. Specifically,
|
||||||
livepatch reuses the apply_relocate_add() function in the module loader to
|
livepatch reuses the apply_relocate_add() function in the module loader to
|
||||||
write relocations. The patch module Elf format described in this document
|
write relocations. The patch module ELF format described in this document
|
||||||
enables livepatch to be able to do this. The hope is that this will make
|
enables livepatch to be able to do this. The hope is that this will make
|
||||||
livepatch more easily portable to other architectures and reduce the amount
|
livepatch more easily portable to other architectures and reduce the amount
|
||||||
of arch-specific code required to port livepatch to a particular
|
of arch-specific code required to port livepatch to a particular
|
||||||
architecture.
|
architecture.
|
||||||
|
|
||||||
Since apply_relocate_add() requires access to a module's section header
|
Since apply_relocate_add() requires access to a module's section header
|
||||||
table, symbol table, and relocation section indices, Elf information is
|
table, symbol table, and relocation section indices, ELF information is
|
||||||
preserved for livepatch modules (see section 5). Livepatch manages its own
|
preserved for livepatch modules (see section 5). Livepatch manages its own
|
||||||
relocation sections and symbols, which are described in this document. The
|
relocation sections and symbols, which are described in this document. The
|
||||||
Elf constants used to mark livepatch symbols and relocation sections were
|
ELF constants used to mark livepatch symbols and relocation sections were
|
||||||
selected from OS-specific ranges according to the definitions from glibc.
|
selected from OS-specific ranges according to the definitions from glibc.
|
||||||
|
|
||||||
Why does livepatch need to write its own relocations?
|
Why does livepatch need to write its own relocations?
|
||||||
|
@ -43,7 +43,7 @@ reject the livepatch module. Furthermore, we cannot apply relocations that
|
||||||
affect modules not yet loaded at patch module load time (e.g. a patch to a
|
affect modules not yet loaded at patch module load time (e.g. a patch to a
|
||||||
driver that is not loaded). Formerly, livepatch solved this problem by
|
driver that is not loaded). Formerly, livepatch solved this problem by
|
||||||
embedding special "dynrela" (dynamic rela) sections in the resulting patch
|
embedding special "dynrela" (dynamic rela) sections in the resulting patch
|
||||||
module Elf output. Using these dynrela sections, livepatch could resolve
|
module ELF output. Using these dynrela sections, livepatch could resolve
|
||||||
symbols while taking into account its scope and what module the symbol
|
symbols while taking into account its scope and what module the symbol
|
||||||
belongs to, and then manually apply the dynamic relocations. However this
|
belongs to, and then manually apply the dynamic relocations. However this
|
||||||
approach required livepatch to supply arch-specific code in order to write
|
approach required livepatch to supply arch-specific code in order to write
|
||||||
|
@ -80,7 +80,7 @@ Example:
|
||||||
3. Livepatch relocation sections
|
3. Livepatch relocation sections
|
||||||
================================
|
================================
|
||||||
|
|
||||||
A livepatch module manages its own Elf relocation sections to apply
|
A livepatch module manages its own ELF relocation sections to apply
|
||||||
relocations to modules as well as to the kernel (vmlinux) at the
|
relocations to modules as well as to the kernel (vmlinux) at the
|
||||||
appropriate time. For example, if a patch module patches a driver that is
|
appropriate time. For example, if a patch module patches a driver that is
|
||||||
not currently loaded, livepatch will apply the corresponding livepatch
|
not currently loaded, livepatch will apply the corresponding livepatch
|
||||||
|
@ -95,7 +95,7 @@ also possible for a livepatch module to have no livepatch relocation
|
||||||
sections, as in the case of the sample livepatch module (see
|
sections, as in the case of the sample livepatch module (see
|
||||||
samples/livepatch).
|
samples/livepatch).
|
||||||
|
|
||||||
Since Elf information is preserved for livepatch modules (see Section 5), a
|
Since ELF information is preserved for livepatch modules (see Section 5), a
|
||||||
livepatch relocation section can be applied simply by passing in the
|
livepatch relocation section can be applied simply by passing in the
|
||||||
appropriate section index to apply_relocate_add(), which then uses it to
|
appropriate section index to apply_relocate_add(), which then uses it to
|
||||||
access the relocation section and apply the relocations.
|
access the relocation section and apply the relocations.
|
||||||
|
@ -291,19 +291,12 @@ Examples:
|
||||||
Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
|
Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
|
||||||
"OS" means OS-specific.
|
"OS" means OS-specific.
|
||||||
|
|
||||||
5. Symbol table and Elf section access
|
5. Symbol table and ELF section access
|
||||||
======================================
|
======================================
|
||||||
A livepatch module's symbol table is accessible through module->symtab.
|
A livepatch module's symbol table is accessible through module->symtab.
|
||||||
|
|
||||||
Since apply_relocate_add() requires access to a module's section headers,
|
Since apply_relocate_add() requires access to a module's section headers,
|
||||||
symbol table, and relocation section indices, Elf information is preserved for
|
symbol table, and relocation section indices, ELF information is preserved for
|
||||||
livepatch modules and is made accessible by the module loader through
|
livepatch modules and is made accessible by the module loader through
|
||||||
module->klp_info, which is a klp_modinfo struct. When a livepatch module loads,
|
module->klp_info, which is a :c:type:`klp_modinfo` struct. When a livepatch module
|
||||||
this struct is filled in by the module loader. Its fields are documented below::
|
loads, this struct is filled in by the module loader.
|
||||||
|
|
||||||
struct klp_modinfo {
|
|
||||||
Elf_Ehdr hdr; /* Elf header */
|
|
||||||
Elf_Shdr *sechdrs; /* Section header table */
|
|
||||||
char *secstrings; /* String table for the section headers */
|
|
||||||
unsigned int symndx; /* The symbol table section index */
|
|
||||||
};
|
|
||||||
|
|
|
@ -352,6 +352,14 @@ struct mod_kallsyms {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_LIVEPATCH
|
#ifdef CONFIG_LIVEPATCH
|
||||||
|
/**
|
||||||
|
* struct klp_modinfo - ELF information preserved from the livepatch module
|
||||||
|
*
|
||||||
|
* @hdr: ELF header
|
||||||
|
* @sechdrs: Section header table
|
||||||
|
* @secstrings: String table for the section headers
|
||||||
|
* @symndx: The symbol table section index
|
||||||
|
*/
|
||||||
struct klp_modinfo {
|
struct klp_modinfo {
|
||||||
Elf_Ehdr hdr;
|
Elf_Ehdr hdr;
|
||||||
Elf_Shdr *sechdrs;
|
Elf_Shdr *sechdrs;
|
||||||
|
@ -515,7 +523,7 @@ struct module {
|
||||||
bool klp; /* Is this a livepatch module? */
|
bool klp; /* Is this a livepatch module? */
|
||||||
bool klp_alive;
|
bool klp_alive;
|
||||||
|
|
||||||
/* Elf information */
|
/* ELF information */
|
||||||
struct klp_modinfo *klp_info;
|
struct klp_modinfo *klp_info;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Persist Elf information about a module. Copy the Elf header,
|
* Persist ELF information about a module. Copy the ELF header,
|
||||||
* section header table, section string table, and symtab section
|
* section header table, section string table, and symtab section
|
||||||
* index from info to mod->klp_info.
|
* index from info to mod->klp_info.
|
||||||
*/
|
*/
|
||||||
|
@ -25,11 +25,11 @@ int copy_module_elf(struct module *mod, struct load_info *info)
|
||||||
if (!mod->klp_info)
|
if (!mod->klp_info)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
/* Elf header */
|
/* ELF header */
|
||||||
size = sizeof(mod->klp_info->hdr);
|
size = sizeof(mod->klp_info->hdr);
|
||||||
memcpy(&mod->klp_info->hdr, info->hdr, size);
|
memcpy(&mod->klp_info->hdr, info->hdr, size);
|
||||||
|
|
||||||
/* Elf section header table */
|
/* ELF section header table */
|
||||||
size = sizeof(*info->sechdrs) * info->hdr->e_shnum;
|
size = sizeof(*info->sechdrs) * info->hdr->e_shnum;
|
||||||
mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL);
|
mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL);
|
||||||
if (!mod->klp_info->sechdrs) {
|
if (!mod->klp_info->sechdrs) {
|
||||||
|
@ -37,7 +37,7 @@ int copy_module_elf(struct module *mod, struct load_info *info)
|
||||||
goto free_info;
|
goto free_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Elf section name string table */
|
/* ELF section name string table */
|
||||||
size = info->sechdrs[info->hdr->e_shstrndx].sh_size;
|
size = info->sechdrs[info->hdr->e_shstrndx].sh_size;
|
||||||
mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL);
|
mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL);
|
||||||
if (!mod->klp_info->secstrings) {
|
if (!mod->klp_info->secstrings) {
|
||||||
|
@ -45,7 +45,7 @@ int copy_module_elf(struct module *mod, struct load_info *info)
|
||||||
goto free_sechdrs;
|
goto free_sechdrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Elf symbol section index */
|
/* ELF symbol section index */
|
||||||
symndx = info->index.sym;
|
symndx = info->index.sym;
|
||||||
mod->klp_info->symndx = symndx;
|
mod->klp_info->symndx = symndx;
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/fs.h>
|
#include <linux/fs.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/kernel_read_file.h>
|
#include <linux/kernel_read_file.h>
|
||||||
|
#include <linux/kstrtox.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/vmalloc.h>
|
#include <linux/vmalloc.h>
|
||||||
#include <linux/elf.h>
|
#include <linux/elf.h>
|
||||||
|
@ -2675,7 +2676,7 @@ static int unknown_module_param_cb(char *param, char *val, const char *modname,
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (strcmp(param, "async_probe") == 0) {
|
if (strcmp(param, "async_probe") == 0) {
|
||||||
if (strtobool(val, &mod->async_probe_requested))
|
if (kstrtobool(val, &mod->async_probe_requested))
|
||||||
mod->async_probe_requested = true;
|
mod->async_probe_requested = true;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/kstrtox.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -310,7 +311,7 @@ int param_set_bool(const char *val, const struct kernel_param *kp)
|
||||||
if (!val) val = "1";
|
if (!val) val = "1";
|
||||||
|
|
||||||
/* One of =[yYnN01] */
|
/* One of =[yYnN01] */
|
||||||
return strtobool(val, kp->arg);
|
return kstrtobool(val, kp->arg);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(param_set_bool);
|
EXPORT_SYMBOL(param_set_bool);
|
||||||
|
|
||||||
|
|
|
@ -51,12 +51,11 @@ static int num_test_devs;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* enum kmod_test_case - linker table test case
|
* enum kmod_test_case - linker table test case
|
||||||
*
|
|
||||||
* If you add a test case, please be sure to review if you need to se
|
|
||||||
* @need_mod_put for your tests case.
|
|
||||||
*
|
|
||||||
* @TEST_KMOD_DRIVER: stress tests request_module()
|
* @TEST_KMOD_DRIVER: stress tests request_module()
|
||||||
* @TEST_KMOD_FS_TYPE: stress tests get_fs_type()
|
* @TEST_KMOD_FS_TYPE: stress tests get_fs_type()
|
||||||
|
*
|
||||||
|
* If you add a test case, please be sure to review if you need to set
|
||||||
|
* @need_mod_put for your tests case.
|
||||||
*/
|
*/
|
||||||
enum kmod_test_case {
|
enum kmod_test_case {
|
||||||
__TEST_KMOD_INVALID = 0,
|
__TEST_KMOD_INVALID = 0,
|
||||||
|
@ -78,7 +77,7 @@ struct test_config {
|
||||||
struct kmod_test_device;
|
struct kmod_test_device;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmod_test_device_info - thread info
|
* struct kmod_test_device_info - thread info
|
||||||
*
|
*
|
||||||
* @ret_sync: return value if request_module() is used, sync request for
|
* @ret_sync: return value if request_module() is used, sync request for
|
||||||
* @TEST_KMOD_DRIVER
|
* @TEST_KMOD_DRIVER
|
||||||
|
@ -101,7 +100,7 @@ struct kmod_test_device_info {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kmod_test_device - test device to help test kmod
|
* struct kmod_test_device - test device to help test kmod
|
||||||
*
|
*
|
||||||
* @dev_idx: unique ID for test device
|
* @dev_idx: unique ID for test device
|
||||||
* @config: configuration for the test
|
* @config: configuration for the test
|
||||||
|
|
|
@ -14,7 +14,7 @@ modules := $(call read-file, $(MODORDER))
|
||||||
ifeq ($(KBUILD_EXTMOD),)
|
ifeq ($(KBUILD_EXTMOD),)
|
||||||
dst := $(MODLIB)/kernel
|
dst := $(MODLIB)/kernel
|
||||||
else
|
else
|
||||||
INSTALL_MOD_DIR ?= extra
|
INSTALL_MOD_DIR ?= updates
|
||||||
dst := $(MODLIB)/$(INSTALL_MOD_DIR)
|
dst := $(MODLIB)/$(INSTALL_MOD_DIR)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue