Researchers have found that the patch for the original Dirty CoW is incomplete and does not address a condition where a read-only privileged page is marked dirty. The vulnerability has been assigned CVE-2017-1000405. Similar to Dirty CoW the bug allows an unprivileged authenticated local user to gain write access to read only memory mappings. By exploiting this vulnerability an attacker can write in to pages belonging to other processes resulting in DoS due to crash.
Dirty CoW allows attacker to write to a read-only privileged version of a page instead of its writable copy. To fix the issue a new flag ‘FOLL_COW’ was introduced, it is used in conjunction with pte dirty flag to validate Copy-on-Write cycle. A page is marked dirty when it has been modified and has not been backed up in memory.
To improve handling of large amounts of memory, support for huge pages was introduced. Linux usually uses a 4096-bytes and a huge page is 2MB. We can use huge pages through Transparent Huge Pages. This feature can be enabled by setting the _PAGE_PSE in Page Medium Directory (PMD) after which PMD will point to physical 2MB pages.
To patch Dirty CoW ‘FOLL_COW’ flag and can_follow_write_pte() were introduced. can_follow_write_pmd() is a matching function for handling Page Medium Directory (PMD). In the case of PMD a huge page can be marked dirty by touch_pmd() sets dirty bit by calling pmd_mkdirty() without going running through Copy-on-Write cycle.
A PoC has been released which overwrites huge zero pages, this will cause the target process to have invalid initial values and may result in a crash. When a process tries to create a new page, the kernel will not allocate it immediately. Instead it maps a zero page (A page filled with zeroes) in to the processes, it generates a page-fault when the process tries to access that page and then proceeds to allocate the page based on the rights requested by the caller. The same applies to huge pages as well.
Processes often do not initialize this memory before using as they know it is zeroed out by the kernel. Any modification to the zero page may result in improper initialization within a process. So if an attacker can modify the zero page that would cause processes referring to it to crash or behave abnormally. Transparent huge pages are no different. Any process referring to modified huge zero page may crash. As it happens all unwritten anonymous pages for all processes in the system may be sharing a single zero page. This is the crux of the PoC, modifying huge zero pages so that processes referring to it crash which results in DoS.
For the attack to be successful the attacker would need to be local and have a valid user account on the machine. We have tested the PoC on Ubuntu 17.04 32-bit and it resulted crashing Firefox.
touch_pmd() has been patched to set the dirty bit only when the callers asks for write access FOLL_WRITE otherwise it only sets the FOLL_WRITE for the pmd in question and updates the cache. Apart from the usual arguments caller must now include requested access when calling touch_pmd(). A similar fix has been extended to touch_pud() as well.
We request our customers to scan their environment with QID 370666 to detect vulnerable machines and apply the latest patches as soon as they are released by the respective vendors.
Please continue to follow Qualys Threat Protection for information on Huge Dirty CoW.