aboutsummaryrefslogtreecommitdiff
path: root/hw/9pfs
AgeCommit message (Collapse)Author
2017-04-26Merge remote-tracking branch 'remotes/sstabellini/tags/xen-20170421-v2-tag' ↵Peter Maydell
into staging Xen 2017/04/21 + fix # gpg: Signature made Tue 25 Apr 2017 19:10:37 BST # gpg: using RSA key 0x894F8F4870E1AE90 # gpg: Good signature from "Stefano Stabellini <stefano.stabellini@eu.citrix.com>" # gpg: aka "Stefano Stabellini <sstabellini@kernel.org>" # Primary key fingerprint: D04E 33AB A51F 67BA 07D3 0AEA 894F 8F48 70E1 AE90 * remotes/sstabellini/tags/xen-20170421-v2-tag: (21 commits) move xen-mapcache.c to hw/i386/xen/ move xen-hvm.c to hw/i386/xen/ move xen-common.c to hw/xen/ add xen-9p-backend to MAINTAINERS under Xen xen/9pfs: build and register Xen 9pfs backend xen/9pfs: send responses back to the frontend xen/9pfs: implement in/out_iov_from_pdu and vmarshal/vunmarshal xen/9pfs: receive requests from the frontend xen/9pfs: connect to the frontend xen/9pfs: introduce Xen 9pfs backend 9p: introduce a type for the 9p header xen: import ring.h from xen configure: use pkg-config for obtaining xen version xen: additionally restrict xenforeignmemory operations xen: use libxendevice model to restrict operations xen: use 5 digit xen versions xen: use libxendevicemodel when available configure: detect presence of libxendevicemodel xen: create wrappers for all other uses of xc_hvm_XXX() functions xen: rename xen_modified_memory() to xen_hvm_modified_memory() ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-04-25xen/9pfs: build and register Xen 9pfs backendStefano Stabellini
Signed-off-by: Stefano Stabellini <stefano@aporeto.com> Reviewed-by: Greg Kurz <groug@kaod.org> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-25xen/9pfs: send responses back to the frontendStefano Stabellini
Once a request is completed, xen_9pfs_push_and_notify gets called. In xen_9pfs_push_and_notify, update the indexes (data has already been copied to the sg by the common code) and send a notification to the frontend. Schedule the bottom-half to check if we already have any other requests pending. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-25xen/9pfs: implement in/out_iov_from_pdu and vmarshal/vunmarshalStefano Stabellini
Implement xen_9pfs_init_in/out_iov_from_pdu and xen_9pfs_pdu_vmarshal/vunmarshall by creating new sg pointing to the data on the ring. This is safe as we only handle one request per ring at any given time. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-25xen/9pfs: receive requests from the frontendStefano Stabellini
Upon receiving an event channel notification from the frontend, schedule the bottom half. From the bottom half, read one request from the ring, create a pdu and call pdu_submit to handle it. For now, only handle one request per ring at a time. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-25xen/9pfs: connect to the frontendStefano Stabellini
Write the limits of the backend to xenstore. Connect to the frontend. Upon connection, allocate the rings according to the protocol specification. Initialize a QEMUBH to schedule work upon receiving an event channel notification from the frontend. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-25xen/9pfs: introduce Xen 9pfs backendStefano Stabellini
Introduce the Xen 9pfs backend: add struct XenDevOps to register as a Xen backend and add struct V9fsTransport to register as v9fs transport. All functions are empty stubs for now. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> Reviewed-by: Greg Kurz <groug@kaod.org> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-219p: introduce a type for the 9p headerStefano Stabellini
Use the new type in virtio-9p-device. Signed-off-by: Stefano Stabellini <stefano@aporeto.com> Reviewed-by: Greg Kurz <groug@kaod.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> CC: anthony.perard@citrix.com CC: jgross@suse.com CC: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> CC: Greg Kurz <groug@kaod.org>
2017-04-189pfs: local: set the path of the export root to "."Greg Kurz
The local backend was recently converted to using "at*()" syscalls in order to ensure all accesses happen below the shared directory. This requires that we only pass relative paths, otherwise the dirfd argument to the "at*()" syscalls is ignored and the path is treated as an absolute path in the host. This is actually the case for paths in all fids, with the notable exception of the root fid, whose path is "/". This causes the following backend ops to act on the "/" directory of the host instead of the virtfs shared directory when the export root is involved: - lstat - chmod - chown - utimensat ie, chmod /9p_mount_point in the guest will be converted to chmod / in the host for example. This could cause security issues with a privileged QEMU. All "*at()" syscalls are being passed an open file descriptor. In the case of the export root, this file descriptor points to the path in the host that was passed to -fsdev. The fix is thus as simple as changing the path of the export root fid to be "." instead of "/". This is CVE-2017-7471. Cc: qemu-stable@nongnu.org Reported-by: Léo Gaspard <leo@gaspard.io> Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-04-109pfs: xattr: fix memory leak in v9fs_list_xattrLi Qiang
Free 'orig_value' in error path. Signed-off-by: Li Qiang <liqiang6-s@360.cn> Signed-off-by: Greg Kurz <groug@kaod.org>
2017-04-049pfs: clear migration blocker at session resetGreg Kurz
The migration blocker survives a device reset: if the guest mounts a 9p share and then gets rebooted with system_reset, it will be unmigratable until it remounts and umounts the 9p share again. This happens because the migration blocker is supposed to be cleared when we put the last reference on the root fid, but virtfs_reset() wrongly calls free_fid() instead of put_fid(). This patch fixes virtfs_reset() so that it honor the way fids are supposed to be manipulated: first get a reference and later put it back when you're done. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Li Qiang <liqiang6-s@360.cn>
2017-04-049pfs: fix multiple flush for same requestGreg Kurz
If a client tries to flush the same outstanding request several times, only the first flush completes. Subsequent ones keep waiting for the request completion in v9fs_flush() and, therefore, leak a PDU. This will cause QEMU to hang when draining active PDUs the next time the device is reset. Let have each flush request wake up the next one if any. The last waiter frees the cancelled PDU. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Eric Blake <eblake@redhat.com>
2017-03-279pfs: fix file descriptor leakLi Qiang
The v9fs_create() and v9fs_lcreate() functions are used to create a file on the backend and to associate it to a fid. The fid shouldn't be already in-use, otherwise both functions may silently leak a file descriptor or allocated memory. The current code doesn't check that. This patch ensures that the fid isn't already associated to anything before using it. Signed-off-by: Li Qiang <liqiang6-s@360.cn> (reworded the changelog, Greg Kurz) Signed-off-by: Greg Kurz <groug@kaod.org>
2017-03-219pfs: proxy: assert if unmarshal failsGreg Kurz
Replies from the virtfs proxy are made up of a fixed-size header (8 bytes) and a payload of variable size (maximum 64kb). When receiving a reply, the proxy backend first reads the whole header and then unmarshals it. If the header is okay, it then does the same operation with the payload. Since the proxy backend uses a pre-allocated buffer which has enough room for a header and the maximum payload size, marshalling should never fail with fixed size arguments. Any error here is likely to result from a more serious corruption in QEMU and we'd better dump core right away. This patch adds error checks where they are missing and converts the associated error paths into assertions. This should also address Coverity's complaints CID 1348519 and CID 1348520, about not always checking the return value of proxy_unmarshal(). Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2017-03-219pfs: don't try to flush self and avoid QEMU hang on resetGreg Kurz
According to the 9P spec [*], when a client wants to cancel a pending I/O request identified by a given tag (uint16), it must send a Tflush message and wait for the server to respond with a Rflush message before reusing this tag for another I/O. The server may still send a completion message for the I/O if it wasn't actually cancelled but the Rflush message must arrive after that. QEMU hence waits for the flushed PDU to complete before sending the Rflush message back to the client. If a client sends 'Tflush tag oldtag' and tag == oldtag, QEMU will then allocate a PDU identified by tag, find it in the PDU list and wait for this same PDU to complete... i.e. wait for a completion that will never happen. This causes a tag and ring slot leak in the guest, and a PDU leak in QEMU, all of them limited by the maximal number of PDUs (128). But, worse, this causes QEMU to hang on device reset since v9fs_reset() wants to drain all pending I/O. This insane behavior is likely to denote a bug in the client, and it would deserve an Rerror message to be sent back. Unfortunately, the protocol allows it and requires all flush requests to suceed (only a Tflush response is expected). The only option is to detect when we have to handle a self-referencing flush request and report success to the client right away. [*] http://man.cat-v.org/plan_9/5/flush Reported-by: Al Viro <viro@ZenIV.linux.org.uk> Signed-off-by: Greg Kurz <groug@kaod.org>
2017-03-069pfs: fix vulnerability in openat_dir() and local_unlinkat_common()Greg Kurz
We should pass O_NOFOLLOW otherwise openat() will follow symlinks and make QEMU vulnerable. While here, we also fix local_unlinkat_common() to use openat_dir() for the same reasons (it was a leftover in the original patchset actually). This fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com>
2017-03-069pfs: fix O_PATH build break with older glibc versionsGreg Kurz
When O_PATH is used with O_DIRECTORY, it only acts as an optimization: the openat() syscall simply finds the name in the VFS, and doesn't trigger the underlying filesystem. On systems that don't define O_PATH, because they have glibc version 2.13 or older for example, we can safely omit it. We don't want to deactivate O_PATH globally though, in case it is used without O_DIRECTORY. The is done with a dedicated macro. Systems without O_PATH may thus fail to resolve names that involve unreadable directories, compared to newer systems succeeding, but such corner case failure is our only option on those older systems to avoid the security hole of chasing symlinks inappropriately. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Eric Blake <eblake@redhat.com> (added last paragraph to changelog as suggested by Eric Blake) Signed-off-by: Greg Kurz <groug@kaod.org>
2017-03-069pfs: don't use AT_EMPTY_PATH in local_set_cred_passthrough()Greg Kurz
The name argument can never be an empty string, and dirfd always point to the containing directory of the file name. AT_EMPTY_PATH is hence useless here. Also it breaks build with glibc version 2.13 and older. It is actually an oversight of a previous tentative patch to implement this function. We can safely drop it. Reported-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Signed-off-by: Greg Kurz <groug@kaod.org> Tested-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> Reviewed-by: Eric Blake <eblake@redhat.com>
2017-03-069pfs: fail local_statfs() earlierGreg Kurz
If we cannot open the given path, we can return right away instead of passing -1 to fstatfs() and close(). This will make Coverity happy. (Coverity issue CID1371729) Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Daniel P. berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2017-03-069pfs: fix fd leak in local_opendir()Greg Kurz
Coverity issue CID1371731 Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2017-03-069pfs: fix bogus fd check in local_remove()Greg Kurz
This was spotted by Coverity as a fd leak. This is certainly true, but also local_remove() would always return without doing anything, unless the fd is zero, which is very unlikely. (Coverity issue CID1371732) Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Eric Blake <eblake@redhat.com>
2017-03-01Merge remote-tracking branch 'remotes/gkurz/tags/cve-2016-9602-for-upstream' ↵Peter Maydell
into staging This pull request have all the fixes for CVE-2016-9602, so that it can be easily picked up by downstreams, as suggested by Michel Tokarev. # gpg: Signature made Tue 28 Feb 2017 10:21:32 GMT # gpg: using DSA key 0x02FC3AEB0101DBC2 # gpg: Good signature from "Greg Kurz <groug@kaod.org>" # gpg: aka "Greg Kurz <groug@free.fr>" # gpg: aka "Greg Kurz <gkurz@linux.vnet.ibm.com>" # gpg: aka "Gregory Kurz (Groug) <groug@free.fr>" # gpg: aka "[jpeg image of size 3330]" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 2BD4 3B44 535E C0A7 9894 DBA2 02FC 3AEB 0101 DBC2 * remotes/gkurz/tags/cve-2016-9602-for-upstream: (28 commits) 9pfs: local: drop unused code 9pfs: local: open2: don't follow symlinks 9pfs: local: mkdir: don't follow symlinks 9pfs: local: mknod: don't follow symlinks 9pfs: local: symlink: don't follow symlinks 9pfs: local: chown: don't follow symlinks 9pfs: local: chmod: don't follow symlinks 9pfs: local: link: don't follow symlinks 9pfs: local: improve error handling in link op 9pfs: local: rename: use renameat 9pfs: local: renameat: don't follow symlinks 9pfs: local: lstat: don't follow symlinks 9pfs: local: readlink: don't follow symlinks 9pfs: local: truncate: don't follow symlinks 9pfs: local: statfs: don't follow symlinks 9pfs: local: utimensat: don't follow symlinks 9pfs: local: remove: don't follow symlinks 9pfs: local: unlinkat: don't follow symlinks 9pfs: local: lremovexattr: don't follow symlinks 9pfs: local: lsetxattr: don't follow symlinks ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2017-02-289pfs: local: drop unused codeGreg Kurz
Now that the all callbacks have been converted to use "at" syscalls, we can drop this code. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: open2: don't follow symlinksGreg Kurz
The local_open2() callback is vulnerable to symlink attacks because it calls: (1) open() which follows symbolic links for all path elements but the rightmost one (2) local_set_xattr()->setxattr() which follows symbolic links for all path elements (3) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one (4) local_post_create_passthrough() which calls in turn lchown() and chmod(), both functions also following symbolic links This patch converts local_open2() to rely on opendir_nofollow() and mkdirat() to fix (1), as well as local_set_xattrat(), local_set_mapped_file_attrat() and local_set_cred_passthrough() to fix (2), (3) and (4) respectively. Since local_open2() already opens a descriptor to the target file, local_set_cred_passthrough() is modified to reuse it instead of opening a new one. The mapped and mapped-file security modes are supposed to be identical, except for the place where credentials and file modes are stored. While here, we also make that explicit by sharing the call to openat(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: mkdir: don't follow symlinksGreg Kurz
The local_mkdir() callback is vulnerable to symlink attacks because it calls: (1) mkdir() which follows symbolic links for all path elements but the rightmost one (2) local_set_xattr()->setxattr() which follows symbolic links for all path elements (3) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one (4) local_post_create_passthrough() which calls in turn lchown() and chmod(), both functions also following symbolic links This patch converts local_mkdir() to rely on opendir_nofollow() and mkdirat() to fix (1), as well as local_set_xattrat(), local_set_mapped_file_attrat() and local_set_cred_passthrough() to fix (2), (3) and (4) respectively. The mapped and mapped-file security modes are supposed to be identical, except for the place where credentials and file modes are stored. While here, we also make that explicit by sharing the call to mkdirat(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: mknod: don't follow symlinksGreg Kurz
The local_mknod() callback is vulnerable to symlink attacks because it calls: (1) mknod() which follows symbolic links for all path elements but the rightmost one (2) local_set_xattr()->setxattr() which follows symbolic links for all path elements (3) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one (4) local_post_create_passthrough() which calls in turn lchown() and chmod(), both functions also following symbolic links This patch converts local_mknod() to rely on opendir_nofollow() and mknodat() to fix (1), as well as local_set_xattrat() and local_set_mapped_file_attrat() to fix (2) and (3) respectively. A new local_set_cred_passthrough() helper based on fchownat() and fchmodat_nofollow() is introduced as a replacement to local_post_create_passthrough() to fix (4). The mapped and mapped-file security modes are supposed to be identical, except for the place where credentials and file modes are stored. While here, we also make that explicit by sharing the call to mknodat(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: symlink: don't follow symlinksGreg Kurz
The local_symlink() callback is vulnerable to symlink attacks because it calls: (1) symlink() which follows symbolic links for all path elements but the rightmost one (2) open(O_NOFOLLOW) which follows symbolic links for all path elements but the rightmost one (3) local_set_xattr()->setxattr() which follows symbolic links for all path elements (4) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one This patch converts local_symlink() to rely on opendir_nofollow() and symlinkat() to fix (1), openat(O_NOFOLLOW) to fix (2), as well as local_set_xattrat() and local_set_mapped_file_attrat() to fix (3) and (4) respectively. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: chown: don't follow symlinksGreg Kurz
The local_chown() callback is vulnerable to symlink attacks because it calls: (1) lchown() which follows symbolic links for all path elements but the rightmost one (2) local_set_xattr()->setxattr() which follows symbolic links for all path elements (3) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one This patch converts local_chown() to rely on open_nofollow() and fchownat() to fix (1), as well as local_set_xattrat() and local_set_mapped_file_attrat() to fix (2) and (3) respectively. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: chmod: don't follow symlinksGreg Kurz
The local_chmod() callback is vulnerable to symlink attacks because it calls: (1) chmod() which follows symbolic links for all path elements (2) local_set_xattr()->setxattr() which follows symbolic links for all path elements (3) local_set_mapped_file_attr() which calls in turn local_fopen() and mkdir(), both functions following symbolic links for all path elements but the rightmost one We would need fchmodat() to implement AT_SYMLINK_NOFOLLOW to fix (1). This isn't the case on linux unfortunately: the kernel doesn't even have a flags argument to the syscall :-\ It is impossible to fix it in userspace in a race-free manner. This patch hence converts local_chmod() to rely on open_nofollow() and fchmod(). This fixes the vulnerability but introduces a limitation: the target file must readable and/or writable for the call to openat() to succeed. It introduces a local_set_xattrat() replacement to local_set_xattr() based on fsetxattrat() to fix (2), and a local_set_mapped_file_attrat() replacement to local_set_mapped_file_attr() based on local_fopenat() and mkdirat() to fix (3). No effort is made to factor out code because both local_set_xattr() and local_set_mapped_file_attr() will be dropped when all users have been converted to use the "at" versions. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: link: don't follow symlinksGreg Kurz
The local_link() callback is vulnerable to symlink attacks because it calls: (1) link() which follows symbolic links for all path elements but the rightmost one (2) local_create_mapped_attr_dir()->mkdir() which follows symbolic links for all path elements but the rightmost one This patch converts local_link() to rely on opendir_nofollow() and linkat() to fix (1), mkdirat() to fix (2). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: improve error handling in link opGreg Kurz
When using the mapped-file security model, we also have to create a link for the metadata file if it exists. In case of failure, we should rollback. That's what this patch does. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: rename: use renameatGreg Kurz
The local_rename() callback is vulnerable to symlink attacks because it uses rename() which follows symbolic links in all path elements but the rightmost one. This patch simply transforms local_rename() into a wrapper around local_renameat() which is symlink-attack safe. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: renameat: don't follow symlinksGreg Kurz
The local_renameat() callback is currently a wrapper around local_rename() which is vulnerable to symlink attacks. This patch rewrites local_renameat() to have its own implementation, based on local_opendir_nofollow() and renameat(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: lstat: don't follow symlinksGreg Kurz
The local_lstat() callback is vulnerable to symlink attacks because it calls: (1) lstat() which follows symbolic links in all path elements but the rightmost one (2) getxattr() which follows symbolic links in all path elements (3) local_mapped_file_attr()->local_fopen()->openat(O_NOFOLLOW) which follows symbolic links in all path elements but the rightmost one This patch converts local_lstat() to rely on opendir_nofollow() and fstatat(AT_SYMLINK_NOFOLLOW) to fix (1), fgetxattrat_nofollow() to fix (2). A new local_fopenat() helper is introduced as a replacement to local_fopen() to fix (3). No effort is made to factor out code because local_fopen() will be dropped when all users have been converted to call local_fopenat(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: readlink: don't follow symlinksGreg Kurz
The local_readlink() callback is vulnerable to symlink attacks because it calls: (1) open(O_NOFOLLOW) which follows symbolic links for all path elements but the rightmost one (2) readlink() which follows symbolic links for all path elements but the rightmost one This patch converts local_readlink() to rely on open_nofollow() to fix (1) and opendir_nofollow(), readlinkat() to fix (2). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: truncate: don't follow symlinksGreg Kurz
The local_truncate() callback is vulnerable to symlink attacks because it calls truncate() which follows symbolic links in all path elements. This patch converts local_truncate() to rely on open_nofollow() and ftruncate() instead. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: statfs: don't follow symlinksGreg Kurz
The local_statfs() callback is vulnerable to symlink attacks because it calls statfs() which follows symbolic links in all path elements. This patch converts local_statfs() to rely on open_nofollow() and fstatfs() instead. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: utimensat: don't follow symlinksGreg Kurz
The local_utimensat() callback is vulnerable to symlink attacks because it calls qemu_utimens()->utimensat(AT_SYMLINK_NOFOLLOW) which follows symbolic links in all path elements but the rightmost one or qemu_utimens()->utimes() which follows symbolic links for all path elements. This patch converts local_utimensat() to rely on opendir_nofollow() and utimensat(AT_SYMLINK_NOFOLLOW) directly instead of using qemu_utimens(). It is hence assumed that the OS supports utimensat(), i.e. has glibc 2.6 or higher and linux 2.6.22 or higher, which seems reasonable nowadays. This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: remove: don't follow symlinksGreg Kurz
The local_remove() callback is vulnerable to symlink attacks because it calls: (1) lstat() which follows symbolic links in all path elements but the rightmost one (2) remove() which follows symbolic links in all path elements but the rightmost one This patch converts local_remove() to rely on opendir_nofollow(), fstatat(AT_SYMLINK_NOFOLLOW) to fix (1) and unlinkat() to fix (2). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: unlinkat: don't follow symlinksGreg Kurz
The local_unlinkat() callback is vulnerable to symlink attacks because it calls remove() which follows symbolic links in all path elements but the rightmost one. This patch converts local_unlinkat() to rely on opendir_nofollow() and unlinkat() instead. Most of the code is moved to a separate local_unlinkat_common() helper which will be reused in a subsequent patch to fix the same issue in local_remove(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: lremovexattr: don't follow symlinksGreg Kurz
The local_lremovexattr() callback is vulnerable to symlink attacks because it calls lremovexattr() which follows symbolic links in all path elements but the rightmost one. This patch introduces a helper to emulate the non-existing fremovexattrat() function: it is implemented with /proc/self/fd which provides a trusted path that can be safely passed to lremovexattr(). local_lremovexattr() is converted to use this helper and opendir_nofollow(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: lsetxattr: don't follow symlinksGreg Kurz
The local_lsetxattr() callback is vulnerable to symlink attacks because it calls lsetxattr() which follows symbolic links in all path elements but the rightmost one. This patch introduces a helper to emulate the non-existing fsetxattrat() function: it is implemented with /proc/self/fd which provides a trusted path that can be safely passed to lsetxattr(). local_lsetxattr() is converted to use this helper and opendir_nofollow(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: llistxattr: don't follow symlinksGreg Kurz
The local_llistxattr() callback is vulnerable to symlink attacks because it calls llistxattr() which follows symbolic links in all path elements but the rightmost one. This patch introduces a helper to emulate the non-existing flistxattrat() function: it is implemented with /proc/self/fd which provides a trusted path that can be safely passed to llistxattr(). local_llistxattr() is converted to use this helper and opendir_nofollow(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: lgetxattr: don't follow symlinksGreg Kurz
The local_lgetxattr() callback is vulnerable to symlink attacks because it calls lgetxattr() which follows symbolic links in all path elements but the rightmost one. This patch introduces a helper to emulate the non-existing fgetxattrat() function: it is implemented with /proc/self/fd which provides a trusted path that can be safely passed to lgetxattr(). local_lgetxattr() is converted to use this helper and opendir_nofollow(). This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: open/opendir: don't follow symlinksGreg Kurz
The local_open() and local_opendir() callbacks are vulnerable to symlink attacks because they call: (1) open(O_NOFOLLOW) which follows symbolic links in all path elements but the rightmost one (2) opendir() which follows symbolic links in all path elements This patch converts both callbacks to use new helpers based on openat_nofollow() to only open files and directories if they are below the virtfs shared folder This partly fixes CVE-2016-9602. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: keep a file descriptor on the shared folderGreg Kurz
This patch opens the shared folder and caches the file descriptor, so that it can be used to do symlink-safe path walk. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: introduce relative_openat_nofollow() helperGreg Kurz
When using the passthrough security mode, symbolic links created by the guest are actual symbolic links on the host file system. Since the resolution of symbolic links during path walk is supposed to occur on the client side. The server should hence never receive any path pointing to an actual symbolic link. This isn't guaranteed by the protocol though, and malicious code in the guest can trick the server to issue various syscalls on paths whose one or more elements are symbolic links. In the case of the "local" backend using the "passthrough" or "none" security modes, the guest can directly create symbolic links to arbitrary locations on the host (as per spec). The "mapped-xattr" and "mapped-file" security modes are also affected to a lesser extent as they require some help from an external entity to create actual symbolic links on the host, i.e. another guest using "passthrough" mode for example. The current code hence relies on O_NOFOLLOW and "l*()" variants of system calls. Unfortunately, this only applies to the rightmost path component. A guest could maliciously replace any component in a trusted path with a symbolic link. This could allow any guest to escape a virtfs shared folder. This patch introduces a variant of the openat() syscall that successively opens each path element with O_NOFOLLOW. When passing a file descriptor pointing to a trusted directory, one is guaranteed to be returned a file descriptor pointing to a path which is beneath the trusted directory. This will be used by subsequent patches to implement symlink-safe path walk for any access to the backend. Symbolic links aren't the only threats actually: a malicious guest could change a path element to point to other types of file with undesirable effects: - a named pipe or any other thing that would cause openat() to block - a terminal device which would become QEMU's controlling terminal These issues can be addressed with O_NONBLOCK and O_NOCTTY. Two helpers are introduced: one to open intermediate path elements and one to open the rightmost path element. Suggested-by: Jann Horn <jannh@google.com> Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> (renamed openat_nofollow() to relative_openat_nofollow(), assert path is relative and doesn't contain '//', fixed side-effect in assert, Greg Kurz) Signed-off-by: Greg Kurz <groug@kaod.org>
2017-02-289pfs: remove side-effects in local_open() and local_opendir()Greg Kurz
If these functions fail, they should not change *fs. Let's use local variables to fix this. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: remove side-effects in local_init()Greg Kurz
If this function fails, it should not modify *ctx. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
2017-02-289pfs: local: move xattr security ops to 9p-xattr.cGreg Kurz
These functions are always called indirectly. It really doesn't make sense for them to sit in a header file. Signed-off-by: Greg Kurz <groug@kaod.org> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>