Commit 1d411b80 authored by Kai Germaschewski's avatar Kai Germaschewski

Module Sanity Check

This patch, based on Rusty's implementation, adds a special section
to vmlinux and all modules, which contain the kernel version
string, values of some particularly important config options
(SMP,preempt,proc family) and the gcc version.

When inserting a module, the version string is checked against the
kernel version string and loading is rejected if they don't match.

The version string is actually added to the modules during the
final .ko generation, so that a changed version string does only
cause relinking, not recompilation, which is a major performance
improvement over the old 2.4 way of doing things.
parent 9552d6bc
......@@ -394,6 +394,17 @@ $(SUBDIRS): .hdepend prepare
prepare: include/linux/version.h include/asm include/config/MARKER
@echo ' Starting the build. KBUILD_BUILTIN=$(KBUILD_BUILTIN) KBUILD_MODULES=$(KBUILD_MODULES)'
# We need to build init/vermagic.o before descending since all modules
# (*.ko) need it already
ifdef CONFIG_MODULES
prepare: init/vermagic.o
init/vermagic.o: include/linux/version.h
endif
# This can be used by arch/$ARCH/Makefile to preprocess
# their vmlinux.lds.S file
......
......@@ -47,6 +47,7 @@ SECTIONS
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
.rodata : { *(.rodata) *(.rodata.*) }
/* Startup code */
......
......@@ -64,6 +64,7 @@ SECTIONS
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16);
__ex_table : { /* Exception table */
......
......@@ -67,6 +67,7 @@ SECTIONS
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16);
__ex_table : { /* Exception table */
......
......@@ -33,6 +33,7 @@ SECTIONS
.rodata : { *(.rodata) *(.rodata.__*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(4); /* Exception table */
__start___ex_table = .;
......
......@@ -20,6 +20,7 @@ SECTIONS
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -90,6 +90,8 @@ SECTIONS
{ *(.rodata) *(.rodata.*) }
.kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET)
{ *(.kstrtab) }
__vermagic : AT(ADDR(__vermagic) - PAGE_OFFSET)
{ *(__vermagic) }
.opd : AT(ADDR(.opd) - PAGE_OFFSET)
{ *(.opd) }
......
......@@ -14,6 +14,7 @@ SECTIONS
} = 0x4e75
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -14,7 +14,7 @@ SECTIONS
*(.gnu.warning)
} = 0x4e75
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
_etext = .; /* End of text section */
......
......@@ -224,6 +224,7 @@ SECTIONS {
. = ALIGN(0x4) ;
*(.kstrtab)
*(__vermagic)
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -15,6 +15,7 @@ SECTIONS
*(.gnu.warning)
} =0
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -25,6 +25,7 @@ SECTIONS
*(.gnu.warning)
} = 0
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -14,6 +14,7 @@ SECTIONS
*(.gnu.warning)
} =0
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -34,6 +34,7 @@ SECTIONS
. = ALIGN(16);
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
.data BLOCK(8192) : { /* Data without special */
data_start = .;
......
......@@ -47,6 +47,7 @@ SECTIONS
*(.rodata1)
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
......
......@@ -42,6 +42,7 @@ SECTIONS
*(.rodata1)
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
.fini : { *(.fini) } =0
.ctors : { *(.ctors) }
.dtors : { *(.dtors) }
......
......@@ -19,6 +19,7 @@ SECTIONS
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -19,6 +19,7 @@ SECTIONS
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -27,6 +27,7 @@ SECTIONS
} = 0x0009
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -43,6 +43,7 @@ SECTIONS
__gpl_ksymtab : { *(__gpl_ksymtab) }
__stop___gpl_ksymtab = .;
__kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
__start___kallsyms = .; /* All kernel symbols */
__kallsyms : { *(__kallsyms) }
__stop___kallsyms = .;
......
......@@ -32,6 +32,7 @@ SECTIONS
*(.gnu.linkonce.t*)
}
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
......@@ -41,6 +41,7 @@
*(.rodata) \
. = ALIGN (0x4) ; \
*(.kstrtab) \
*(__vermagic) \
. = ALIGN (4) ; \
*(.call_table_data) \
*(.call_table_text) \
......
......@@ -20,6 +20,7 @@ SECTIONS
.rodata : { *(.rodata) *(.rodata.*) }
.kstrtab : { *(.kstrtab) }
__vermagic : { *(__vermagic) }
. = ALIGN(16); /* Exception table */
__start___ex_table = .;
......
#ifndef _ASM_I386_MODULE_H
#define _ASM_I386_MODULE_H
/* x86 is simple */
struct mod_arch_specific
{
......@@ -8,4 +9,47 @@ struct mod_arch_specific
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Ehdr Elf32_Ehdr
#ifdef CONFIG_M386
#define MODULE_PROC_FAMILY "386 "
#elif CONFIG_M486
#define MODULE_PROC_FAMILY "486 "
#elif CONFIG_M586
#define MODULE_PROC_FAMILY "586 "
#elif CONFIG_M586TSC
#define MODULE_PROC_FAMILY "586TSC "
#elif CONFIG_M586MMX
#define MODULE_PROC_FAMILY "586MMX "
#elif CONFIG_M686
#define MODULE_PROC_FAMILY "686 "
#elif CONFIG_MPENTIUMII
#define MODULE_PROC_FAMILY "PENTIUMII "
#elif CONFIG_MPENTIUMIII
#define MODULE_PROC_FAMILY "PENTIUMIII "
#elif CONFIG_MPENTIUM4
#define MODULE_PROC_FAMILY "PENTIUM4 "
#elif CONFIG_MK6
#define MODULE_PROC_FAMILY "K6 "
#elif CONFIG_MK7
#define MODULE_PROC_FAMILY "K7 "
#elif CONFIG_MK8
#define MODULE_PROC_FAMILY "K8 "
#elif CONFIG_MELAN
#define MODULE_PROC_FAMILY "ELAN "
#elif CONFIG_MCRUSOE
#define MODULE_PROC_FAMILY "CRUSOE "
#elif CONFIG_MWINCHIPC6
#define MODULE_PROC_FAMILY "WINCHIPC6 "
#elif CONFIG_MWINCHIP2
#define MODULE_PROC_FAMILY "WINCHIP2 "
#elif CONFIG_MWINCHIP3D
#define MODULE_PROC_FAMILY "WINCHIP3D "
#elif CONFIG_MCYRIXIII
#define MODULE_PROC_FAMILY "CYRIXIII "
#else
#error unknown processor family
#endif
#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY
#endif /* _ASM_I386_MODULE_H */
......@@ -2,7 +2,8 @@
# Makefile for the linux kernel.
#
obj-y := main.o version.o do_mounts.o initramfs.o
obj-y := main.o version.o do_mounts.o initramfs.o
obj-$(CONFIG_MODULES) += vermagic.o
# files to be removed upon make clean
clean-files := ../include/linux/compile.h
......
#include <linux/version.h>
#include <linux/module.h>
/* Simply sanity version stamp for modules. */
#ifdef CONFIG_SMP
#define MODULE_VERMAGIC_SMP "SMP "
#else
#define MODULE_VERMAGIC_SMP ""
#endif
#ifdef CONFIG_PREEMPT
#define MODULE_VERMAGIC_PREEMPT "preempt "
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
#ifndef MODULE_ARCH_VERMAGIC
#define MODULE_ARCH_VERMAGIC ""
#endif
const char vermagic[] __attribute__((section("__vermagic"))) =
UTS_RELEASE " "
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT MODULE_ARCH_VERMAGIC
"gcc-" __stringify(__GNUC__) "." __stringify(__GNUC_MINOR__);
......@@ -963,6 +963,9 @@ static void set_license(struct module *mod, Elf_Shdr *sechdrs, int licenseidx)
}
}
/* From init/vermagic.o */
extern char vermagic[];
/* Allocate and load the module: note that size of section 0 is always
zero, and we rely on this for optional sections. */
static struct module *load_module(void *umod,
......@@ -973,7 +976,7 @@ static struct module *load_module(void *umod,
Elf_Shdr *sechdrs;
char *secstrings, *args;
unsigned int i, symindex, exportindex, strindex, setupindex, exindex,
modindex, obsparmindex, licenseindex, gplindex;
modindex, obsparmindex, licenseindex, gplindex, vmagindex;
long arglen;
struct module *mod;
long err = 0;
......@@ -1012,7 +1015,7 @@ static struct module *load_module(void *umod,
exportindex = setupindex = obsparmindex = gplindex = licenseindex = 0;
/* And these should exist, but gcc whinges if we don't init them */
symindex = strindex = exindex = modindex = 0;
symindex = strindex = exindex = modindex = vmagindex = 0;
/* Find where important sections are */
for (i = 1; i < hdr->e_shnum; i++) {
......@@ -1062,6 +1065,11 @@ static struct module *load_module(void *umod,
/* EXPORT_SYMBOL_GPL() */
DEBUGP("GPL symbols found in section %u\n", i);
gplindex = i;
} else if (strcmp(secstrings+sechdrs[i].sh_name,
"__vermagic") == 0) {
/* Version magic. */
DEBUGP("Version magic found in section %u\n", i);
vmagindex = i;
}
#ifdef CONFIG_KALLSYMS
/* symbol and string tables for decoding later. */
......@@ -1082,6 +1090,18 @@ static struct module *load_module(void *umod,
}
mod = (void *)sechdrs[modindex].sh_addr;
/* This is allowed: modprobe --force will strip it. */
if (!vmagindex) {
tainted |= TAINT_FORCED_MODULE;
printk(KERN_WARNING "%s: no version magic, tainting kernel.\n",
mod->name);
} else if (strcmp((char *)sechdrs[vmagindex].sh_addr, vermagic) != 0) {
printk(KERN_ERR "%s: version magic '%s' should be '%s'\n",
mod->name, (char*)sechdrs[vmagindex].sh_addr, vermagic);
err = -ENOEXEC;
goto free_hdr;
}
/* Now copy in args */
arglen = strlen_user(uargs);
if (!arglen) {
......
......@@ -176,10 +176,15 @@ quiet_cmd_link_multi-y = LD $@
cmd_link_multi-y = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^)
quiet_cmd_link_multi-m = LD [M] $@
cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^)
cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^) init/vermagic.o
quiet_cmd_link_single-m = LD [M] $@
cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $<
cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o
# Don't rebuilt vermagic.o unless we actually are in the init/ dir
ifneq ($(obj),init)
init/vermagic.o: ;
endif
# We would rather have a list of rules like
# foo.o: $(foo-objs)
......@@ -188,10 +193,10 @@ cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $<
$(multi-used-y) : %.o: $(multi-objs-y) FORCE
$(call if_changed,link_multi-y)
$(multi-used-m:.o=.ko) : %.ko: $(multi-objs-m) FORCE
$(multi-used-m:.o=.ko) : %.ko: $(multi-objs-m) init/vermagic.o FORCE
$(call if_changed,link_multi-m)
$(single-used-m:.o=.ko) : %.ko: %.o FORCE
$(single-used-m:.o=.ko) : %.ko: %.o init/vermagic.o FORCE
$(call if_changed,link_single-m)
targets += $(multi-used-y) $(multi-used-m:.o=.ko) $(single-used-m:.o=.ko)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment