Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 2006

kernel-2.6.18-238.el5.src.rpm

From: Frantisek Hrbata <fhrbata@redhat.com>
Date: Tue, 30 Nov 2010 16:09:52 -0500
Subject: [misc] kernel: restrict unprivileged access to dmesg
Message-id: <1291133393-23442-2-git-send-email-fhrbata@redhat.com>
Patchwork-id: 29688
O-Subject: [RHEL5.6 PATCH BZ653250 v2 1/2] kernel: restrict unprivileged access
	to kernel syslog
Bugzilla: 653250

Bugzilla: 653250
https://bugzilla.redhat.com/show_bug.cgi?id=653250

Description:
This patch adds a new sysctl parameter called dmesg_restrict. If on(1), only
tasks with the CAP_SYS_ADMIN capability are able to read syslog messages via
dmesg.

Upstream status: eaf06b241b091357e72b76863ba16e89610d31bd

    Restrict unprivileged access to kernel syslog

    The kernel syslog contains debugging information that is often useful
    during exploitation of other vulnerabilities, such as kernel heap
    addresses.  Rather than futilely attempt to sanitize hundreds (or
    thousands) of printk statements and simultaneously cripple useful
    debugging functionality, it is far simpler to create an option that
    prevents unprivileged users from reading the syslog.

    This patch, loosely based on grsecurity's GRKERNSEC_DMESG, creates the
    dmesg_restrict sysctl.  When set to "0", the default, no restrictions are
    enforced.  When set to "1", only users with CAP_SYS_ADMIN can read the
    kernel syslog via dmesg(8) or other mechanisms.

    [akpm@linux-foundation.org: explain the config option in kernel.txt]
    Signed-off-by: Dan Rosenberg <drosenberg@vsecurity.com>
    Acked-by: Ingo Molnar <mingo@elte.hu>
    Acked-by: Eugene Teo <eugeneteo@kernel.org>
    Acked-by: Kees Cook <kees.cook@canonical.com>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Notes:
Since the upstream ctl_table does not require ctl_name in definition, but the
rhel5.6 code does, this patch adds CTL_UNNUMBERED(-2), so we can use it as a
ctl_name for dmesg_restrict. This means that as in upstream the dmesg_restrict
can be modified only via /proc, not via sysctl syscall. Here follows why not to
add new binary sysctl ids to sysctl.h from
Documentation/sysctl/ctl_unnumbered.txt.
----------------------8<------------------
Except for a few extremely rare exceptions user space applications do not use
the binary sysctl interface.  Instead everyone uses /proc/sys/...  with
readable ascii names.

Recently the kernel has started supporting setting the binary sysctl value to
CTL_UNNUMBERED so we no longer need to assign a binary sysctl path to allow
sysctls to show up in /proc/sys.

Assigning binary sysctl numbers is an endless source of conflicts in sysctl.h,
breaking of the user space ABI (because of those conflicts), and maintenance
problems.  A complete pass through all of the sysctl users revealed multiple
instances where the sysctl binary interface was broken and had gone undetected
for years.

So please do not add new binary sysctl numbers.  They are unneeded and
problematic.

If you really need a new binary sysctl number please first merge your sysctl
into the kernel and then as a separate patch allocate a binary sysctl number.

(ebiederm@xmission.com, June 2007)
----------------------8<------------------

Brew build: 2922755
https://brewweb.devel.redhat.com/taskinfo?taskID=2922755

Test Status: tested by me
[root@amd-pence-01 ~]# cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.6 Beta (Tikanga)
[root@amd-pence-01 ~]# uname -a
Linux amd-pence-01.lab.bos.redhat.com 2.6.18-233.el5.bz653250_3 #1 SMP Tue Nov
30 06:34:22 EST 2010 x86_64 x86_64 x86_64 GNU/Linux
[root@amd-pence-01 ~]# sysctl kernel.dmesg_restrict
kernel.dmesg_restrict = 0
[root@amd-pence-01 ~]# dmesg
dmesg output
[root@amd-pence-01 ~]# su test
[test@amd-pence-01 root]$ dmesg
dmesg output
[test@amd-pence-01 root]$ exit
[root@amd-pence-01 ~]# sysctl -w kernel.dmesg_restrict=1
kernel.dmesg_restrict = 1
[root@amd-pence-01 ~]# dmesg
dmesg output
[root@amd-pence-01 ~]# su test
[test@amd-pence-01 root]$ dmesg
klogctl: Operation not permitted

Signed-off-by: Frantisek Hrbata <fhrbata@redhat.com>

diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
index 3cb3334..c6d14c1 100644
--- a/Documentation/sysctl/kernel.txt
+++ b/Documentation/sysctl/kernel.txt
@@ -22,6 +22,7 @@ show up in /proc/sys/kernel:
 - core_uses_pid
 - ctrl-alt-del
 - dentry-state
+- dmesg_restrict
 - domainname
 - hostname
 - hotplug
@@ -133,6 +134,19 @@ to decide what to do with it.
 
 ==============================================================
 
+dmesg_restrict:
+
+This toggle indicates whether unprivileged users are prevented from using
+dmesg(8) to view messages from the kernel's log buffer.  When
+dmesg_restrict is set to (0) there are no restrictions.  When
+dmesg_restrict is set set to (1), users must have CAP_SYS_ADMIN to use
+dmesg(8).
+
+The kernel config option CONFIG_SECURITY_DMESG_RESTRICT sets the default
+value of dmesg_restrict.
+
+==============================================================
+
 domainname & hostname:
 
 These files can be used to set the NIS/YP domainname and the
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index f35db2f..d6bb0f6 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -179,6 +179,7 @@ asmlinkage int vprintk(const char *fmt, va_list args)
 asmlinkage int printk(const char * fmt, ...)
 	__attribute__ ((format (printf, 1, 2)));
 extern void log_buf_kexec_setup(void);
+extern int dmesg_restrict;
 #else
 static inline int vprintk(const char *s, va_list args)
 	__attribute__ ((format (printf, 1, 0)));
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index bb53eb8..8a8ea29 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -47,6 +47,7 @@ struct __sysctl_args {
 /* For internal pattern-matching use only: */
 #ifdef __KERNEL__
 #define CTL_ANY		-1	/* Matches any name */
+#define CTL_UNNUMBERED	-2
 #define CTL_NONE	0
 #endif
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 4f162c0..b6bdd58 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -205,6 +205,12 @@ static void boot_delay_msec(int millisecs)
 
 #endif
 
+#ifdef CONFIG_SECURITY_DMESG_RESTRICT
+int dmesg_restrict = 1;
+#else
+int dmesg_restrict;
+#endif
+
 /*
  * Commands to do_syslog:
  *
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index aa68a76..e9339a9 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -736,6 +736,16 @@ static ctl_table kern_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= CTL_UNNUMBERED,
+		.procname       = "dmesg_restrict",
+		.data           = &dmesg_restrict,
+		.maxlen         = sizeof(int),
+		.mode           = 0644,
+		.proc_handler   = &proc_dointvec_minmax,
+		.extra1         = &zero,
+		.extra2         = &one,
+	},
+	{
 		.ctl_name	= KERN_NGROUPS_MAX,
 		.procname	= "ngroups_max",
 		.data		= &ngroups_max,
diff --git a/security/Kconfig b/security/Kconfig
index 59f332d..444b7e4 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -39,6 +39,18 @@ config KEYS_DEBUG_PROC_KEYS
 
 	  If you are unsure as to whether this is required, answer N.
 
+config SECURITY_DMESG_RESTRICT
+	bool "Restrict unprivileged access to the kernel syslog"
+	default n
+	help
+	  This enforces restrictions on unprivileged users reading the kernel
+	  syslog via dmesg(8).
+
+	  If this option is not selected, no restrictions will be enforced
+	  unless the dmesg_restrict sysctl is explicitly set to (1).
+
+	  If you are unsure how to answer this question, answer N.
+
 config SECURITY
 	bool "Enable different security models"
 	depends on SYSFS
diff --git a/security/commoncap.c b/security/commoncap.c
index 8d217b6..1e2cf91 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -311,6 +311,9 @@ void cap_task_reparent_to_init (struct task_struct *p)
 
 int cap_syslog (int type)
 {
+	if (dmesg_restrict && !capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
 	if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN))
 		return -EPERM;
 	return 0;