Bug 903192

Summary: kernel.dmesg_restrict=1 does not restrict dmesg(1)
Product: [Fedora] Fedora Reporter: Christian Kujau <redhat>
Component: kernelAssignee: Eric Paris <eparis>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 18CC: gansalmon, itamar, jonathan, kernel-maint, madhu.chinakonda
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: i686   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2013-03-22 00:17:20 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Christian Kujau 2013-01-23 12:45:16 UTC
Description of problem:

Setting kernel.dmesg_restrict=1 does not prevent normal users from getting dmesg output.

Version-Release number of selected component (if applicable):

$ uname -rv
3.7.2-204.fc18.i686 #1 SMP Wed Jan 16 16:42:52 UTC 2013

How reproducible:

Steps to Reproduce:
1. $ useradd -d /home/foo -m -s /bin/bash -U foo
2. $ su - foo
3. $ sysctl kernel.dmesg_restrict
   kernel.dmesg_restrict = 1
   $ ls -l `which dmesg`
   -rwxr-xr-x. 1 root root 40200 Dec  3 09:55 /bin/dmesg

Actual results:

$ dmesg | head -1
[    0.000000] Initializing cgroup subsys cpuset
 
Expected results:

$ dmesg | head -1
klogctl: Operation not permitted

Additional info:

If I parse this output correctly, the new user appears to have CAP_SYSLOG set (amongst many other flags):

----------
$ capsh --print
Current: =
Bounding set =cap_chown,cap_dac_override,cap_dac_read_search,cap_fowner,cap_fsetid,cap_kill,cap_setgid,cap_setuid,cap_setpcap,cap_linux_immutable,cap_net_bind_service,cap_net_broadcast,cap_net_admin,cap_net_raw,cap_ipc_lock,cap_ipc_owner,cap_sys_module,cap_sys_rawio,cap_sys_chroot,cap_sys_ptrace,cap_sys_pacct,cap_sys_admin,cap_sys_boot,cap_sys_nice,cap_sys_resource,cap_sys_time,cap_sys_tty_config,cap_mknod,cap_lease,cap_audit_write,cap_audit_control,cap_setfcap,cap_mac_override,cap_mac_admin,cap_syslog,35,36,37
Securebits: 00/0x0/1'b0
 secure-noroot: no (unlocked)
 secure-no-suid-fixup: no (unlocked)
 secure-keep-caps: no (unlocked)
uid=1003(foo)
gid=1003(foo)
groups=1003(foo)
-----------

IIRC this was not the case in F17. Other distribution seem to honor kernel.dmesg_restrict as well.

Comment 1 Josh Boyer 2013-02-20 15:33:26 UTC
From what I can tell, dmesg(8) is now reading directly from /dev/kmsg instead of going through syslog.  That started with the 3.5.0 kernel I believe.  If you specify the -S option to dmesg to force it to use syslog, it will honor the setting.

The /dev/kmsg code does call security_syslog to see if the process should be allowed to open the device, which calls into SELinux.  I'm going to guess that dmesg is granted the proper permissions through the SELinux label it has:

[jwboyer@zod linux]$ ls -lZ `which dmesg`
-rwxr-xr-x. root root system_u:object_r:dmesg_exec_t:s0 /usr/bin/dmesg

The original commit that added this seems to be squarely targeted at the syslog method:

commit eaf06b241b091357e72b76863ba16e89610d31bd
Author: Dan Rosenberg <drosenberg>
Date:   Thu Nov 11 14:05:18 2010 -0800

    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.

Now that dmesg doesn't use syslog by default, it kind of makes sense that the sysctl check isn't done when working on the raw device.

Whether or not the check was left off of the /dev/kmsg device intentionally or not is something that I need to look into.

Comment 2 Josh Boyer 2013-02-20 15:41:20 UTC
OK.  So it looks like Eric Paris accidentally left /dev/kmsg unprotected.

As I mentioned in the comment above, the /dev/kmsg code does call security_syslog.  The SELinux code used to call cap_syslog before it did the
SELinux checks.  However, with commit:

commit 12b3052c3ee8f508b2c7ee4ddd63ed03423409d8
Author: Eric Paris <eparis>
Date:   Mon Nov 15 18:36:29 2010 -0500

    capabilities/syslog: open code cap_syslog logic to fix build failure

Eric moved the cap checks into the do_syslog function itself and the selinux_syslog function no longer does any capabilities checks, so the call to
security_syslog isn't actually honoring dmesg_restrict like it used to.

Eric?

Comment 3 Josh Boyer 2013-02-20 15:42:40 UTC
As an aside, you aren't reading the output of capsh correctly.  The Bounding set is just the list of possible caps the process can have, not what it actually has.

Comment 4 Josh Boyer 2013-02-20 15:52:15 UTC
Something like this might work as expected (not tested), but I'm concerned the SELinux hook isn't calling a cap check anymore.

diff --git a/kernel/printk.c b/kernel/printk.c
index 267ce78..048d124 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -614,6 +614,11 @@ static int devkmsg_open(struct inode *inode, struct file *file)
 	struct devkmsg_user *user;
 	int err;
 
+	if (dmesg_restrict) {
+		if (!capable(CAP_SYSLOG))
+			return -EPERM;
+	}
+
 	/* write-only does not need any file context */
 	if ((file->f_flags & O_ACCMODE) == O_WRONLY)
 		return 0;

Comment 5 Christian Kujau 2013-02-20 20:11:53 UTC
Thanks for the insight. If this isn't resolved here, we should report this upstream, right?

FWIW, "dmesg" from util-linux-2.22.2-3.fc18.i686 does indeed read from /dev/kmsg while util-linux-2.20 on a Debian system uses syslog and I only *thought* "dmesg" was restricted. Whooha!

Workaround: chmod 0600 /dev/kmsg

Comment 6 Josh Boyer 2013-02-22 18:19:27 UTC
I sent a patch upstream with you on CC.  We'll see what they say.

Comment 7 Josh Boyer 2013-02-25 15:05:48 UTC
Patch applied to all branches.

Comment 8 Fedora Update System 2013-02-28 14:52:34 UTC
kernel-3.7.10-101.fc17 has been submitted as an update for Fedora 17.
https://admin.fedoraproject.org/updates/kernel-3.7.10-101.fc17

Comment 9 Fedora Update System 2013-03-02 20:04:48 UTC
Package kernel-3.7.10-101.fc17:
* should fix your issue,
* was pushed to the Fedora 17 testing repository,
* should be available at your local mirror within two days.
Update it with:
# su -c 'yum update --enablerepo=updates-testing kernel-3.7.10-101.fc17'
as soon as you are able to, then reboot.
Please go to the following url:
https://admin.fedoraproject.org/updates/FEDORA-2013-3252/kernel-3.7.10-101.fc17
then log in and leave karma (feedback).

Comment 10 Christian Kujau 2013-03-04 20:14:59 UTC
I'm on Fedora18 and kernel-3.8.1-201.fc18.i686 fixed this for me:

$ ls -l /dev/kmsg
crw-r--r--. 1 root root 1, 11 Mar  3 23:48 /dev/kmsg

$ id
uid=1002(foo) gid=1002(foo) groups=1002(foo),100(users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023

$ cat /dev/kmsg
cat: /dev/kmsg: Permission denied

$ dmesg
dmesg: read kernel buffer failed: Operation not permitted


$ LC_ALL=C strace -s1024 -tt -f dmesg 2>&1 | grep -- -1
12:13:20.997296 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7722000
12:13:20.998288 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
12:13:21.004953 mmap2(0x47600000, 10972, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x47600000
12:13:21.007602 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7713000
12:13:21.008574 set_thread_area({entry_number:-1 -> 6, base_addr:0xb77136c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0
12:13:21.014704 open("/dev/kmsg", O_RDONLY|O_NONBLOCK|O_LARGEFILE) = -1 EACCES (Permission denied)
12:13:21.015513 syslog(SYSLOG_ACTION_SIZE_BUFFER, 0, 0) = -1 EPERM (Operation not permitted)
12:13:21.016993 syslog(SYSLOG_ACTION_READ_ALL, 0x8397038, 16392) = -1 EPERM (Operation not permitted)

Comment 11 Fedora Update System 2013-03-08 22:16:51 UTC
kernel-3.8.2-105.fc17 has been submitted as an update for Fedora 17.
https://admin.fedoraproject.org/updates/kernel-3.8.2-105.fc17

Comment 12 Fedora Update System 2013-03-14 15:20:26 UTC
kernel-3.8.2-105.fc17 has been submitted as an update for Fedora 17.
https://admin.fedoraproject.org/updates/FEDORA-2013-3638/kernel-3.8.2-105.fc17

Comment 13 Fedora Update System 2013-03-14 22:56:25 UTC
kernel-3.8.3-101.fc17 has been submitted as an update for Fedora 17.
https://admin.fedoraproject.org/updates/kernel-3.8.3-101.fc17

Comment 14 Fedora Update System 2013-03-22 00:17:23 UTC
kernel-3.8.3-103.fc17 has been pushed to the Fedora 17 stable repository.  If problems still persist, please make note of it in this bug report.