1. 25 5月, 2017 1 次提交
    • G
      9pfs: local: simplify file opening · 3dbcf273
      Greg Kurz 提交于
      The logic to open a path currently sits between local_open_nofollow() and
      the relative_openat_nofollow() helper, which has no other user.
      
      For the sake of clarity, this patch moves all the code of the helper into
      its unique caller. While here we also:
      - drop the code to skip leading "/" because the backend isn't supposed to
        pass anything but relative paths without consecutive slashes. The assert()
        is kept because we really don't want a buggy backend to pass an absolute
        path to openat().
      - use strchrnul() to get a simpler code. This is ok since virtfs is for
        linux+glibc hosts only.
      - don't dup() the initial directory and add an assert() to ensure we don't
        return the global mountfd to the caller. BTW, this would mean that the
        caller passed an empty path, which isn't supposed to happen either.
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NEric Blake <eblake@redhat.com>
      [groug: fixed typos in changelog]
      3dbcf273
  2. 28 2月, 2017 2 次提交
    • G
      9pfs: local: lgetxattr: don't follow symlinks · 56ad3e54
      Greg 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: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NStefan Hajnoczi <stefanha@redhat.com>
      56ad3e54
    • G
      9pfs: introduce relative_openat_nofollow() helper · 6482a961
      Greg 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: NJann Horn <jannh@google.com>
      Signed-off-by: NGreg Kurz <groug@kaod.org>
      Reviewed-by: NStefan 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: NGreg Kurz <groug@kaod.org>
      6482a961