Technical Notes on the Dirty Cow Vulnerability

Timesys Factory has been updated to fix the “Dirty COW” security vulnerability for all supported kernel versions as of November 1, 2016 (factory-20161101).

What is “Dirty COW”

The security vulnerability CVE-2016-5195, published in late October 2016, is a Linux kernel bug that can be exploited to elevate permissions. The bug affects kernels at least as far back as 2007, since kernel version 2.6.22. Dirty Cow gets its nickname from the Copy-On-Write (COW) mechanism in the kernel.

How to Update

See the Factory document on Upgrading the Factory Build Engine or download the latest release from LinuxLink here.

Patching Without a Factory Upgrade

If you don't want to upgrade your Factory, you can pull the patch for your kernel version from the Timesys Source Repository. For each kernel version, the patch is named linux-<version>-dirty-cow.patch. Find it in the folder corresponding to your kernel.

Linus Torvalds pushed the original fix for the issue here.

Applying the Patch

For best practices on adding the patch locally, refer to Factory Best Practices: How do I add my custom patch to a package?.

If the kernel rebuilds successfully, then the patch applied cleanly, and the new kernel will include the fix. If it does not apply cleanly, you may contact Timesys Support via the LinuxLink Support page for advice. Include your Factory .config, and the local patch you used.

Testing the Fix

There is a long list of Proof of Concepts here. We have used dirtyc0w.c for some of our testing and it seems to illustrate the issue. Below is an example of building and running that test.

Cross-compile dirtyc0w.c for your target

You may use the toolchain in your Factory for this, or run the SDK installer from a finished build and use the toolchain there. This example assumes an ARM target; your cross-gcc binary may differ. With the toolchain in your PATH:

$ armv7l-timesys-linux-gnueabi-gcc -pthread dirtyc0w.c -o dirtyc0w

Copy the resulting binary to your target

If your target supports it, the simplest thing to do is copy the dirtyc0w binary to some removable media, such as a USB drive or SD card, and copy it from there to the target board. Otherwise, you can update your RFS image with this custom file using the RFS Overlay functionality and deploy the new RFS to your target.

Run the test

Run the following when connected to your target (e.g. via serial or ssh).
  1. Create a file owned by root with read-only permissions for everyone else
    # echo foobar > foo
    # chmod 0444 foo
    
  2. Create an unprivileged user account and switch to that user
    # adduser notroot
    # su notroot
    
  3. Confirm that you can't modify the file
    $ echo m00 > foo
    -sh: can't create foo: Permission denied
    
  4. Run dirtyc0w. When unfixed, the contents of the read-only, root owned file will be changed. It should fail to modify the file if the kernel is patched.
    $ ./dirtyc0w foo m00
    mmap 76ff8000
    
    madvise 0
    
    procselfmem 1800000000
    
    $ cat foo
    m00
    

Other Related Links:

How Bad is Dirty Cow? - Linux.com

https://dirtycow.ninja/ - An active site pertaining to the issue

A description by the Guardian

https://github.com/gbonacini/CVE-2016-5195 - an alternative test