diff -durN linux-2.6.12.1-seal-orig/include/linux/kernel.h linux-2.6.12.1-seal/include/linux/kernel.h --- linux-2.6.12.1-seal-orig/include/linux/kernel.h 2005-06-27 19:28:54.000000000 +0100 +++ linux-2.6.12.1-seal/include/linux/kernel.h 2005-06-27 22:21:48.000000000 +0100 @@ -165,6 +165,9 @@ extern int tainted; extern const char *print_tainted(void); extern void add_taint(unsigned); +#ifdef CONFIG_MODULE_SEAL +extern int module_seal; +#endif /* Values used for system_state */ extern enum system_states { diff -durN linux-2.6.12.1-seal-orig/include/linux/sysctl.h linux-2.6.12.1-seal/include/linux/sysctl.h --- linux-2.6.12.1-seal-orig/include/linux/sysctl.h 2005-06-27 19:28:57.000000000 +0100 +++ linux-2.6.12.1-seal/include/linux/sysctl.h 2005-06-27 22:26:12.000000000 +0100 @@ -136,6 +136,7 @@ KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */ KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */ KERN_RANDOMIZE=68, /* int: randomize virtual address space */ + KERN_MODULE_SEAL=69, /* int: module loading forbidden */ }; @@ -801,6 +802,8 @@ void __user *, size_t *, loff_t *); extern int proc_dointvec_bset(ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); +extern int proc_dointvec_seal(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos); extern int proc_dointvec_minmax(ctl_table *, int, struct file *, void __user *, size_t *, loff_t *); extern int proc_dointvec_jiffies(ctl_table *, int, struct file *, diff -durN linux-2.6.12.1-seal-orig/init/Kconfig linux-2.6.12.1-seal/init/Kconfig --- linux-2.6.12.1-seal-orig/init/Kconfig 2005-06-27 19:28:59.000000000 +0100 +++ linux-2.6.12.1-seal/init/Kconfig 2005-06-27 22:21:49.000000000 +0100 @@ -463,6 +463,16 @@ the version). With this option, such a "srcversion" field will be created for all modules. If unsure, say N. +config MODULE_SEAL + bool "Module sealing support" + depends on MODULES && PROC_FS + help + This option provides a file /proc/sys/kernel/module_seal, + initially containing the value 0. If it is set to a non-zero + value, all module loading and unloading will be prohibited + until the next reboot: further changes to the flag will be + ignored. + config KMOD bool "Automatic kernel module loading" depends on MODULES diff -durN linux-2.6.12.1-seal-orig/kernel/module.c linux-2.6.12.1-seal/kernel/module.c --- linux-2.6.12.1-seal-orig/kernel/module.c 2005-06-27 19:28:59.000000000 +0100 +++ linux-2.6.12.1-seal/kernel/module.c 2005-06-27 22:21:49.000000000 +0100 @@ -49,6 +49,10 @@ #define ARCH_SHF_SMALL 0 #endif +#ifdef CONFIG_MODULE_SEAL +int module_seal = 0; +#endif + /* If this is set, the section belongs in the init part of the module */ #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) @@ -1765,6 +1769,12 @@ if (!capable(CAP_SYS_MODULE)) return -EPERM; +#ifdef CONFIG_MODULE_SEAL + /* Must not be sealed */ + if (module_seal) + return -EPERM; +#endif + /* Only one module load at a time, please */ if (down_interruptible(&module_mutex) != 0) return -EINTR; diff -durN linux-2.6.12.1-seal-orig/kernel/sysctl.c linux-2.6.12.1-seal/kernel/sysctl.c --- linux-2.6.12.1-seal-orig/kernel/sysctl.c 2005-06-27 19:29:00.000000000 +0100 +++ linux-2.6.12.1-seal/kernel/sysctl.c 2005-06-27 22:21:49.000000000 +0100 @@ -589,6 +589,16 @@ .mode = 0644, .proc_handler = &proc_dointvec, }, +#ifdef CONFIG_MODULE_SEAL + { + .ctl_name = KERN_MODULE_SEAL, + .procname = "module_seal", + .data = &module_seal, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = &proc_dointvec_seal, + }, +#endif { .ctl_name = KERN_PRINTK_RATELIMIT, .procname = "printk_ratelimit", @@ -1663,6 +1673,22 @@ do_proc_dointvec_bset_conv,&op); } +#ifdef CONFIG_MODULE_SEAL +/* + * You can't change the seal unless it's zero. + */ + +int proc_dointvec_seal(ctl_table *table, int write, struct file *filp, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + if (module_seal != 0) { + return -EPERM; + } + + return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,NULL,NULL); +} +#endif + struct do_proc_dointvec_minmax_conv_param { int *min; int *max;