Re: Automatic Configuration of a Kernel

Valdis.Kletnieks
2005-09-15T20:37:00Z

[-- Attachment #1: Type: text/plain, Size: 4231 bytes --]

On Thu, 15 Sep 2005 15:58:38 BST, Nix said:
> On 15 Sep 2005, David Lang yowled:
> > 5. once kmem and mem can be made read-only there is a security
> > advantage in not having kernel modules available (yes the machine can
> > be rebooted into a new kernel, but that's easier to detect then a
> > module getting loaded)
>
> Here, have a small patch (against 2.6.12.x, but easily forward-portable)
> that eliminates that advantage:

Two comments:

1) This patch is pointless without other kernel magic to guarantee that
even root can't open /dev/kmem - either SELinux and/or the 'devmem.patch'
that's in current Fedora kernels. There's well-known ways to do the equivalent of
an insmod even if the kernel is built with 'CONFIG_MODULES=n'.

2) Guess it's time to re-post my sysctl patch to provide a general-purpose
one-shot... (Diffed against 2.6.11-mm4, but applies cleanly to 2.6.13-mm1 as well).

--- cut here for patch

Quite often, we see re-inventions of "allow a sysctl until/unless a given
flag is set to zero/one". The following code implements a general-purpose
one-shot facility to assist in building such "lockdown/jail" modes.

Usage: In a sysctl definition, we use something like:

int security_enable = 1;
int security_myflag = 0;

{
.ctl_name = ,
.procname = "myflag",
.data = &security_myflag,
.maxlen = sizeof(security_myflag),
.mode = 0644,
.proc_handler = &proc_dointvec_gated,
.extra1 = &security_enable,
},
{
.ctl_name = ,
.procname = "security_lock",
.data = &security_enable,
.maxlen = sizeof(security_enable),
.mode = 0644,
.proc_handler = &proc_dointvec_gated,
.extra1 = &security_enable,
}

Writes to myflag are allowed until a 0 is written to security_lock, at
which point both myflag and security_lock go read-only...

Signed-off-by: <valdis.kletnieks@vt.edu>

--- linux-2.6.11-mm4/include/linux/sysctl.h.sysctl 2005-03-17 02:16:12.000000000 -0500
+++ linux-2.6.11-mm4/include/linux/sysctl.h 2005-03-17 02:17:02.000000000 -0500
@@ -798,6 +798,8 @@ extern int proc_dointvec(ctl_table *, in
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_gated(ctl_table *, int, struct file *,
+ void __user *, size_t *, loff_t *);
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 *,
--- linux-2.6.11-mm4/kernel/sysctl.c.sysctl 2005-03-17 02:16:14.000000000 -0500
+++ linux-2.6.11-mm4/kernel/sysctl.c 2005-03-17 02:17:02.000000000 -0500
@@ -16,6 +16,7 @@
* Wendling.
* The list_for_each() macro wasn't appropriate for the sysctl loop.
* Removed it and replaced it with older style, 03/23/00, Bill Wendling
+ * Added proc_dointvec_gated, 06/14/04, Valdis Kletnieks
*/

#include <linux/config.h>
@@ -1693,6 +1694,37 @@ static int do_proc_dointvec_minmax_conv(
}

/**
+ * proc_dointvec_gated - read a vector of integers only if a specified flag
+ * word is non-zero
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string.
+ *
+ * This is identical to proc_dointvec, except that we additionally
+ * check that the location pointed to by table->extra1 is non-zero
+ * (useful for creating a 'lockdown' sysctl that allows setting of
+ * the variable only until some specified condition is fulfilled).
+ *
+ * Returns 0 on success.
+ */
+int proc_dointvec_gated(ctl_table *table, int write, struct file *filp,
+ void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+ int *flag = (int *) (table->extra1);
+ if (write && flag && !(*flag)) {
+ return -EPERM;
+ }
+ return do_proc_dointvec(table, write, filp, buffer, lenp, ppos,
+ do_proc_dointvec_conv, NULL);
+}
+
+
+/**
* proc_dointvec_minmax - read a vector of integers with min/max values
* @table: the sysctl table
* @write: %TRUE if this is a write to the sysctl file

[-- Attachment #2: Type: application/pgp-signature, Size: 226 bytes --]