Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Module strict rwx
0004  *
0005  * Copyright (C) 2015 Rusty Russell
0006  */
0007 
0008 #include <linux/module.h>
0009 #include <linux/mm.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/set_memory.h>
0012 #include "internal.h"
0013 
0014 /*
0015  * LKM RO/NX protection: protect module's text/ro-data
0016  * from modification and any data from execution.
0017  *
0018  * General layout of module is:
0019  *          [text] [read-only-data] [ro-after-init] [writable data]
0020  * text_size -----^                ^               ^               ^
0021  * ro_size ------------------------|               |               |
0022  * ro_after_init_size -----------------------------|               |
0023  * size -----------------------------------------------------------|
0024  *
0025  * These values are always page-aligned (as is base) when
0026  * CONFIG_STRICT_MODULE_RWX is set.
0027  */
0028 
0029 /*
0030  * Since some arches are moving towards PAGE_KERNEL module allocations instead
0031  * of PAGE_KERNEL_EXEC, keep frob_text() and module_enable_x() independent of
0032  * CONFIG_STRICT_MODULE_RWX because they are needed regardless of whether we
0033  * are strict.
0034  */
0035 static void frob_text(const struct module_layout *layout,
0036               int (*set_memory)(unsigned long start, int num_pages))
0037 {
0038     set_memory((unsigned long)layout->base,
0039            PAGE_ALIGN(layout->text_size) >> PAGE_SHIFT);
0040 }
0041 
0042 static void frob_rodata(const struct module_layout *layout,
0043          int (*set_memory)(unsigned long start, int num_pages))
0044 {
0045     set_memory((unsigned long)layout->base + layout->text_size,
0046            (layout->ro_size - layout->text_size) >> PAGE_SHIFT);
0047 }
0048 
0049 static void frob_ro_after_init(const struct module_layout *layout,
0050             int (*set_memory)(unsigned long start, int num_pages))
0051 {
0052     set_memory((unsigned long)layout->base + layout->ro_size,
0053            (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
0054 }
0055 
0056 static void frob_writable_data(const struct module_layout *layout,
0057             int (*set_memory)(unsigned long start, int num_pages))
0058 {
0059     set_memory((unsigned long)layout->base + layout->ro_after_init_size,
0060            (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
0061 }
0062 
0063 static bool layout_check_misalignment(const struct module_layout *layout)
0064 {
0065     return WARN_ON(!PAGE_ALIGNED(layout->base)) ||
0066            WARN_ON(!PAGE_ALIGNED(layout->text_size)) ||
0067            WARN_ON(!PAGE_ALIGNED(layout->ro_size)) ||
0068            WARN_ON(!PAGE_ALIGNED(layout->ro_after_init_size)) ||
0069            WARN_ON(!PAGE_ALIGNED(layout->size));
0070 }
0071 
0072 bool module_check_misalignment(const struct module *mod)
0073 {
0074     if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
0075         return false;
0076 
0077     return layout_check_misalignment(&mod->core_layout) ||
0078            layout_check_misalignment(&mod->data_layout) ||
0079            layout_check_misalignment(&mod->init_layout);
0080 }
0081 
0082 void module_enable_x(const struct module *mod)
0083 {
0084     if (!PAGE_ALIGNED(mod->core_layout.base) ||
0085         !PAGE_ALIGNED(mod->init_layout.base))
0086         return;
0087 
0088     frob_text(&mod->core_layout, set_memory_x);
0089     frob_text(&mod->init_layout, set_memory_x);
0090 }
0091 
0092 void module_enable_ro(const struct module *mod, bool after_init)
0093 {
0094     if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
0095         return;
0096 #ifdef CONFIG_STRICT_MODULE_RWX
0097     if (!rodata_enabled)
0098         return;
0099 #endif
0100 
0101     set_vm_flush_reset_perms(mod->core_layout.base);
0102     set_vm_flush_reset_perms(mod->init_layout.base);
0103     frob_text(&mod->core_layout, set_memory_ro);
0104 
0105     frob_rodata(&mod->data_layout, set_memory_ro);
0106     frob_text(&mod->init_layout, set_memory_ro);
0107     frob_rodata(&mod->init_layout, set_memory_ro);
0108 
0109     if (after_init)
0110         frob_ro_after_init(&mod->data_layout, set_memory_ro);
0111 }
0112 
0113 void module_enable_nx(const struct module *mod)
0114 {
0115     if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
0116         return;
0117 
0118     frob_rodata(&mod->data_layout, set_memory_nx);
0119     frob_ro_after_init(&mod->data_layout, set_memory_nx);
0120     frob_writable_data(&mod->data_layout, set_memory_nx);
0121     frob_rodata(&mod->init_layout, set_memory_nx);
0122     frob_writable_data(&mod->init_layout, set_memory_nx);
0123 }
0124 
0125 int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
0126                 char *secstrings, struct module *mod)
0127 {
0128     const unsigned long shf_wx = SHF_WRITE | SHF_EXECINSTR;
0129     int i;
0130 
0131     if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
0132         return 0;
0133 
0134     for (i = 0; i < hdr->e_shnum; i++) {
0135         if ((sechdrs[i].sh_flags & shf_wx) == shf_wx) {
0136             pr_err("%s: section %s (index %d) has invalid WRITE|EXEC flags\n",
0137                    mod->name, secstrings + sechdrs[i].sh_name, i);
0138             return -ENOEXEC;
0139         }
0140     }
0141 
0142     return 0;
0143 }