1. 10 May, 2024 1 commit
  2. 09 May, 2024 1 commit
  3. 04 May, 2024 1 commit
  4. 02 May, 2024 3 commits
  5. 26 Apr, 2024 1 commit
  6. 24 Apr, 2024 3 commits
  7. 17 Apr, 2024 5 commits
  8. 15 Apr, 2024 1 commit
  9. 13 Apr, 2024 1 commit
    • Linus Torvalds's avatar
      vfs: relax linkat() AT_EMPTY_PATH - aka flink() - requirements · 42bd2af5
      Linus Torvalds authored
         "The definition of insanity is doing the same thing over and over
          again and expecting different results”
      
      We've tried to do this before, most recently with commit bb2314b4
      ("fs: Allow unprivileged linkat(..., AT_EMPTY_PATH) aka flink") about a
      decade ago.
      
      But the effort goes back even further than that, eg this thread back
      from 1998 that is so old that we don't even have it archived in lore:
      
          https://lkml.org/lkml/1998/3/10/108
      
      which also points out some of the reasons why it's dangerous.
      
      Or, how about then in 2003:
      
          https://lkml.org/lkml/2003/4/6/112
      
      where we went through some of the same arguments, just wirh different
      people involved.
      
      In particular, having access to a file descriptor does not necessarily
      mean that you have access to the path that was used for lookup, and
      there may be very good reasons why you absolutely must not have access
      to a path to said file.
      
      For example, if we were passed a file descriptor from the outside into
      some limited environment (think chroot, but also user namespaces etc) a
      'flink()' system call could now make that file visible inside a context
      where it's not supposed to be visible.
      
      In the process the user may also be able to re-open it with permissions
      that the original file descriptor did not have (eg a read-only file
      descriptor may be associated with an underlying file that is writable).
      
      Another variation on this is if somebody else (typically root) opens a
      file in a directory that is not accessible to others, and passes the
      file descriptor on as a read-only file.  Again, the access to the file
      descriptor does not imply that you should have access to a path to the
      file in the filesystem.
      
      So while we have tried this several times in the past, it never works.
      
      The last time we did this, that commit bb2314b4 quickly got reverted
      again in commit f0cc6ffb (Revert "fs: Allow unprivileged linkat(...,
      AT_EMPTY_PATH) aka flink"), with a note saying "We may re-do this once
      the whole discussion about the interface is done".
      
      Well, the discussion is long done, and didn't come to any resolution.
      There's no question that 'flink()' would be a useful operation, but it's
      a dangerous one.
      
      However, it does turn out that since 2008 (commit d76b0d9b: "CRED:
      Use creds in file structs") we have had a fairly straightforward way to
      check whether the file descriptor was opened by the same credentials as
      the credentials of the flink().
      
      That allows the most common patterns that people want to use, which tend
      to be to either open the source carefully (ie using the openat2()
      RESOLVE_xyz flags, and/or checking ownership with fstat() before
      linking), or to use O_TMPFILE and fill in the file contents before it's
      exposed to the world with linkat().
      
      But it also means that if the file descriptor was opened by somebody
      else, or we've gone through a credentials change since, the operation no
      longer works (unless we have CAP_DAC_READ_SEARCH capabilities in the
      opener's user namespace, as before).
      
      Note that the credential equality check is done by using pointer
      equality, which means that it's not enough that you have effectively the
      same user - they have to be literally identical, since our credentials
      are using copy-on-write semantics.
      
      So you can't change your credentials to something else and try to change
      it back to the same ones between the open() and the linkat().  This is
      not meant to be some kind of generic permission check, this is literally
      meant as a "the open and link calls are 'atomic' wrt user credentials"
      check.
      
      It also means that you can't just move things between namespaces,
      because the credentials aren't just a list of uid's and gid's: they
      includes the pointer to the user_ns that the capabilities are relative
      to.
      
      So let's try this one more time and see if maybe this approach ends up
      being workable after all.
      
      Cc: Andrew Lutomirski <luto@kernel.org>
      Cc: Al Viro <viro@zeniv.linux.org.uk>
      Cc: Christian Brauner <brauner@kernel.org>
      Cc: Peter Anvin <hpa@zytor.com>
      Cc: Jan Kara <jack@suse.cz>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      Link: https://lore.kernel.org/r/20240411001012.12513-1-torvalds@linux-foundation.org
      [brauner: relax capability check to opener of the file]
      Link: https://lore.kernel.org/all/20231113-undenkbar-gediegen-efde5f1c34bc@braunerSigned-off-by: default avatarChristian Brauner <brauner@kernel.org>
      42bd2af5
  10. 11 Apr, 2024 1 commit
  11. 09 Apr, 2024 4 commits
  12. 07 Apr, 2024 2 commits
  13. 05 Apr, 2024 12 commits
  14. 26 Mar, 2024 4 commits