Google's gVisor sandboxed kernel had a bug that would allow an attacker to escape their container and overwrite files in the host filesystem – according to Google Project Zero's Jann Horn.

Horn popped his advisory up once Google's open-source folk posted fixes for the software at its GitHub repository.

The high-severity bug, Horn wrote, "can be used to overwrite files in the host filesystem ( /etc/crontab in my PoC) from inside a Docker container that uses gVisor's runsc ".

For those not familiar with *nix architecture, "everything is a file", as the saying goes – disks, keyboards, mice, displays are filesystem entries, so if you can write to any file, you can wreak a lot of harm. In Horn's proof-of-concept, writing to the host system's crontab (a list of task schedules) means someone supposed to be confined to their Docker container could tell the host system to run software.

Horn tweeted the advisory with a little commentary:

two interesting bug patterns in this one https://t.co/hTWHlOIb0V :

- temporarily drop mutex, revalidate state afterwards, but miss an aspect

- de-synchronization of multiple layers of directory entry caches leads to symlink traversal — Jann Horn (@tehjh) October 31, 2018

The advisory said the breakout occurs via a "filesystem cache desync", continuing: "The VFS layer in the sandboxed helper process attempts to ensure consistency between its dentry cache, the hostPaths in the unsandboxed helper, and the host filesystem."

( Dentry associates filenames with inode numbers; hostPaths mounts a file or directory from the host for access by the user.)

Horn discovered that "there is a race condition that can be abused to desynchronize the dentry cache of the sandboxed helper such that two dentries refer to the same backing file".

To trigger this, my PoC does the following: - create a working directory for the attack and chdir() into it - mkdir("old_") - create a file "old_/file" - rename "old_" to "old"; this forces the dentry for "old_/file" to be flushed via .Busy(), which in turn causes the dentry for "old_" / "old" to no longer have any strong references; therefore, after rename, the dentry disappears - perform the following two operations in parallel: - open "old" as `dirfd`, with O_PATH - rename "old" to "new" - verify that the race was successful by attempting to open "{dirfd}/file" for writing. if the race was successful, this will fail with -ENOENT.

Horn found the bug in August, and the patches were completed last week – so if you're a gVisor user, get the fix. ®