Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Module livepatch support
0004  *
0005  * Copyright (C) 2016 Jessica Yu <jeyu@redhat.com>
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/string.h>
0010 #include <linux/slab.h>
0011 #include "internal.h"
0012 
0013 /*
0014  * Persist Elf information about a module. Copy the Elf header,
0015  * section header table, section string table, and symtab section
0016  * index from info to mod->klp_info.
0017  */
0018 int copy_module_elf(struct module *mod, struct load_info *info)
0019 {
0020     unsigned int size, symndx;
0021     int ret;
0022 
0023     size = sizeof(*mod->klp_info);
0024     mod->klp_info = kmalloc(size, GFP_KERNEL);
0025     if (!mod->klp_info)
0026         return -ENOMEM;
0027 
0028     /* Elf header */
0029     size = sizeof(mod->klp_info->hdr);
0030     memcpy(&mod->klp_info->hdr, info->hdr, size);
0031 
0032     /* Elf section header table */
0033     size = sizeof(*info->sechdrs) * info->hdr->e_shnum;
0034     mod->klp_info->sechdrs = kmemdup(info->sechdrs, size, GFP_KERNEL);
0035     if (!mod->klp_info->sechdrs) {
0036         ret = -ENOMEM;
0037         goto free_info;
0038     }
0039 
0040     /* Elf section name string table */
0041     size = info->sechdrs[info->hdr->e_shstrndx].sh_size;
0042     mod->klp_info->secstrings = kmemdup(info->secstrings, size, GFP_KERNEL);
0043     if (!mod->klp_info->secstrings) {
0044         ret = -ENOMEM;
0045         goto free_sechdrs;
0046     }
0047 
0048     /* Elf symbol section index */
0049     symndx = info->index.sym;
0050     mod->klp_info->symndx = symndx;
0051 
0052     /*
0053      * For livepatch modules, core_kallsyms.symtab is a complete
0054      * copy of the original symbol table. Adjust sh_addr to point
0055      * to core_kallsyms.symtab since the copy of the symtab in module
0056      * init memory is freed at the end of do_init_module().
0057      */
0058     mod->klp_info->sechdrs[symndx].sh_addr = (unsigned long)mod->core_kallsyms.symtab;
0059 
0060     return 0;
0061 
0062 free_sechdrs:
0063     kfree(mod->klp_info->sechdrs);
0064 free_info:
0065     kfree(mod->klp_info);
0066     return ret;
0067 }
0068 
0069 void free_module_elf(struct module *mod)
0070 {
0071     kfree(mod->klp_info->sechdrs);
0072     kfree(mod->klp_info->secstrings);
0073     kfree(mod->klp_info);
0074 }