Virt Disk API Refactoring for safer file injection
The current nova.virt.disk API for file injection is built around the idea that the guest disk image can be mapped into the host filesystem. As a previous security vulnerabilty ([OSSA 2012-008] Arbitrary file injection/corruption through directory traversal issues (CVE-2012-3360, CVE-2012-3361)) has demonstrated, this is a risky design. While mapping to the host filesystem is unavoidable when using loopback/qemu-nbd devices, it is not inherant in use of libguestfs. The libguestfs FUSE code could be replaced by use of the libguestfs APIs, avoiding all interaction with the host filesystem.
The key idea is to introduce the concept of a "VFS" (aka Virtual File System) API. From analysis of the file injection code, it can be seen that a VFS API need only expose the following logical operations
- Append data to file
- Replace data in file
- Read data from file
- Create directory (and its parents)
- Set permissions
- Set user/group owners
- Check if file/dir exists
The abstract base class `nova.virt.disk.vfs.VFS` will define the contract for these operations. Two subclasses will then be provided, `nova.virt.disk.vfs.VFSLocalFS` which accesses guest data via a mapping to the host filesystem, and `nova.virt.disk.vfs.VFSGuestFS` which accesses guest data via libguestfs APIs.
The `VFSLocalFS` will make use of the existing `Mount` module for actually mapping the guest filesystem into the host filesystem. The `Mount` APIs will also be moved to a subdirectory, becoming nova.virt.disk.mount.Mount. The nova.virt.disk.api module will then be updated to use the VFS module, instead of direct filesystem access. Finally the guestfs mount impl will be deleted, since the VFSGuestFS module obsoletes it.
The 'img_handlers' configuration variable is removed. This variable had undesirable interactions with the LXC driver (a libguestfs KVM instance could be spawned for each LXC guest !). With the new design, the correct impl is determined based on the image format type, so dynamic probing is no longer performed. As such the config variable was obsolete.