]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.19-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Dec 2020 15:42:03 +0000 (16:42 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Dec 2020 15:42:03 +0000 (16:42 +0100)
added patches:
ext4-prevent-creating-duplicate-encrypted-filenames.patch
f2fs-prevent-creating-duplicate-encrypted-filenames.patch
fscrypt-add-fscrypt_is_nokey_name.patch
ubifs-prevent-creating-duplicate-encrypted-filenames.patch

queue-4.19/ext4-prevent-creating-duplicate-encrypted-filenames.patch [new file with mode: 0644]
queue-4.19/f2fs-prevent-creating-duplicate-encrypted-filenames.patch [new file with mode: 0644]
queue-4.19/fscrypt-add-fscrypt_is_nokey_name.patch [new file with mode: 0644]
queue-4.19/md-raid10-initialize-r10_bio-read_slot-before-use.patch
queue-4.19/series
queue-4.19/ubifs-prevent-creating-duplicate-encrypted-filenames.patch [new file with mode: 0644]

diff --git a/queue-4.19/ext4-prevent-creating-duplicate-encrypted-filenames.patch b/queue-4.19/ext4-prevent-creating-duplicate-encrypted-filenames.patch
new file mode 100644 (file)
index 0000000..660ac44
--- /dev/null
@@ -0,0 +1,43 @@
+From foo@baz Wed Dec 30 04:40:58 PM CET 2020
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Mon, 28 Dec 2020 11:12:09 -0800
+Subject: ext4: prevent creating duplicate encrypted filenames
+To: stable@vger.kernel.org
+Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org
+Message-ID: <20201228191211.138300-3-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 75d18cd1868c2aee43553723872c35d7908f240f upstream.
+
+As described in "fscrypt: add fscrypt_is_nokey_name()", it's possible to
+create a duplicate filename in an encrypted directory by creating a file
+concurrently with adding the directory's encryption key.
+
+Fix this bug on ext4 by rejecting no-key dentries in ext4_add_entry().
+
+Note that the duplicate check in ext4_find_dest_de() sometimes prevented
+this bug.  However in many cases it didn't, since ext4_find_dest_de()
+doesn't examine every dentry.
+
+Fixes: 4461471107b7 ("ext4 crypto: enable filename encryption")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20201118075609.120337-3-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/namei.c |    3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -2106,6 +2106,9 @@ static int ext4_add_entry(handle_t *hand
+       if (!dentry->d_name.len)
+               return -EINVAL;
++      if (fscrypt_is_nokey_name(dentry))
++              return -ENOKEY;
++
+       retval = ext4_fname_setup_filename(dir, &dentry->d_name, 0, &fname);
+       if (retval)
+               return retval;
diff --git a/queue-4.19/f2fs-prevent-creating-duplicate-encrypted-filenames.patch b/queue-4.19/f2fs-prevent-creating-duplicate-encrypted-filenames.patch
new file mode 100644 (file)
index 0000000..70736fd
--- /dev/null
@@ -0,0 +1,41 @@
+From foo@baz Wed Dec 30 04:40:58 PM CET 2020
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Mon, 28 Dec 2020 11:12:10 -0800
+Subject: f2fs: prevent creating duplicate encrypted filenames
+To: stable@vger.kernel.org
+Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org
+Message-ID: <20201228191211.138300-4-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit bfc2b7e8518999003a61f91c1deb5e88ed77b07d upstream.
+
+As described in "fscrypt: add fscrypt_is_nokey_name()", it's possible to
+create a duplicate filename in an encrypted directory by creating a file
+concurrently with adding the directory's encryption key.
+
+Fix this bug on f2fs by rejecting no-key dentries in f2fs_add_link().
+
+Note that the weird check for the current task in f2fs_do_add_link()
+seems to make this bug difficult to reproduce on f2fs.
+
+Fixes: 9ea97163c6da ("f2fs crypto: add filename encryption for f2fs_add_link")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20201118075609.120337-4-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/f2fs/f2fs.h |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/f2fs/f2fs.h
++++ b/fs/f2fs/f2fs.h
+@@ -2857,6 +2857,8 @@ bool f2fs_empty_dir(struct inode *dir);
+ static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
+ {
++      if (fscrypt_is_nokey_name(dentry))
++              return -ENOKEY;
+       return f2fs_do_add_link(d_inode(dentry->d_parent), &dentry->d_name,
+                               inode, inode->i_ino, inode->i_mode);
+ }
diff --git a/queue-4.19/fscrypt-add-fscrypt_is_nokey_name.patch b/queue-4.19/fscrypt-add-fscrypt_is_nokey_name.patch
new file mode 100644 (file)
index 0000000..5486fe3
--- /dev/null
@@ -0,0 +1,124 @@
+From foo@baz Wed Dec 30 04:40:58 PM CET 2020
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Mon, 28 Dec 2020 11:12:08 -0800
+Subject: fscrypt: add fscrypt_is_nokey_name()
+To: stable@vger.kernel.org
+Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org
+Message-ID: <20201228191211.138300-2-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 159e1de201b6fca10bfec50405a3b53a561096a8 upstream.
+
+It's possible to create a duplicate filename in an encrypted directory
+by creating a file concurrently with adding the encryption key.
+
+Specifically, sys_open(O_CREAT) (or sys_mkdir(), sys_mknod(), or
+sys_symlink()) can lookup the target filename while the directory's
+encryption key hasn't been added yet, resulting in a negative no-key
+dentry.  The VFS then calls ->create() (or ->mkdir(), ->mknod(), or
+->symlink()) because the dentry is negative.  Normally, ->create() would
+return -ENOKEY due to the directory's key being unavailable.  However,
+if the key was added between the dentry lookup and ->create(), then the
+filesystem will go ahead and try to create the file.
+
+If the target filename happens to already exist as a normal name (not a
+no-key name), a duplicate filename may be added to the directory.
+
+In order to fix this, we need to fix the filesystems to prevent
+->create(), ->mkdir(), ->mknod(), and ->symlink() on no-key names.
+(->rename() and ->link() need it too, but those are already handled
+correctly by fscrypt_prepare_rename() and fscrypt_prepare_link().)
+
+In preparation for this, add a helper function fscrypt_is_nokey_name()
+that filesystems can use to do this check.  Use this helper function for
+the existing checks that fs/crypto/ does for rename and link.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20201118075609.120337-2-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/crypto/hooks.c               |   10 +++++-----
+ include/linux/fscrypt_notsupp.h |    5 +++++
+ include/linux/fscrypt_supp.h    |   29 +++++++++++++++++++++++++++++
+ 3 files changed, 39 insertions(+), 5 deletions(-)
+
+--- a/fs/crypto/hooks.c
++++ b/fs/crypto/hooks.c
+@@ -58,8 +58,8 @@ int __fscrypt_prepare_link(struct inode
+       if (err)
+               return err;
+-      /* ... in case we looked up ciphertext name before key was added */
+-      if (dentry->d_flags & DCACHE_ENCRYPTED_NAME)
++      /* ... in case we looked up no-key name before key was added */
++      if (fscrypt_is_nokey_name(dentry))
+               return -ENOKEY;
+       if (!fscrypt_has_permitted_context(dir, inode))
+@@ -83,9 +83,9 @@ int __fscrypt_prepare_rename(struct inod
+       if (err)
+               return err;
+-      /* ... in case we looked up ciphertext name(s) before key was added */
+-      if ((old_dentry->d_flags | new_dentry->d_flags) &
+-          DCACHE_ENCRYPTED_NAME)
++      /* ... in case we looked up no-key name(s) before key was added */
++      if (fscrypt_is_nokey_name(old_dentry) ||
++          fscrypt_is_nokey_name(new_dentry))
+               return -ENOKEY;
+       if (old_dir != new_dir) {
+--- a/include/linux/fscrypt_notsupp.h
++++ b/include/linux/fscrypt_notsupp.h
+@@ -24,6 +24,11 @@ static inline bool fscrypt_dummy_context
+       return false;
+ }
++static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
++{
++      return false;
++}
++
+ /* crypto.c */
+ static inline void fscrypt_enqueue_decrypt_work(struct work_struct *work)
+ {
+--- a/include/linux/fscrypt_supp.h
++++ b/include/linux/fscrypt_supp.h
+@@ -58,6 +58,35 @@ static inline bool fscrypt_dummy_context
+               inode->i_sb->s_cop->dummy_context(inode);
+ }
++/**
++ * fscrypt_is_nokey_name() - test whether a dentry is a no-key name
++ * @dentry: the dentry to check
++ *
++ * This returns true if the dentry is a no-key dentry.  A no-key dentry is a
++ * dentry that was created in an encrypted directory that hasn't had its
++ * encryption key added yet.  Such dentries may be either positive or negative.
++ *
++ * When a filesystem is asked to create a new filename in an encrypted directory
++ * and the new filename's dentry is a no-key dentry, it must fail the operation
++ * with ENOKEY.  This includes ->create(), ->mkdir(), ->mknod(), ->symlink(),
++ * ->rename(), and ->link().  (However, ->rename() and ->link() are already
++ * handled by fscrypt_prepare_rename() and fscrypt_prepare_link().)
++ *
++ * This is necessary because creating a filename requires the directory's
++ * encryption key, but just checking for the key on the directory inode during
++ * the final filesystem operation doesn't guarantee that the key was available
++ * during the preceding dentry lookup.  And the key must have already been
++ * available during the dentry lookup in order for it to have been checked
++ * whether the filename already exists in the directory and for the new file's
++ * dentry not to be invalidated due to it incorrectly having the no-key flag.
++ *
++ * Return: %true if the dentry is a no-key name
++ */
++static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
++{
++      return dentry->d_flags & DCACHE_ENCRYPTED_NAME;
++}
++
+ /* crypto.c */
+ extern void fscrypt_enqueue_decrypt_work(struct work_struct *);
+ extern struct fscrypt_ctx *fscrypt_get_ctx(const struct inode *, gfp_t);
index 358f4b8cf34c4ae0a4e2b73ba3334eda86bc8235..ffc06ac824243faccd59594c859c5f58783c3a81 100644 (file)
@@ -19,8 +19,6 @@ Cc: stable@vger.kernel.org
 Signed-off-by: Kevin Vigor <kvigor@gmail.com>
 Signed-off-by: Song Liu <songliubraving@fb.com>
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-
 ---
  drivers/md/raid10.c |    3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)
index 5f9505299d0a2def0ed015fff944151a6a407d7c..c871fa6aac0edc7fa05b74c60f760959aa438b5a 100644 (file)
@@ -1 +1,5 @@
 md-raid10-initialize-r10_bio-read_slot-before-use.patch
+fscrypt-add-fscrypt_is_nokey_name.patch
+ext4-prevent-creating-duplicate-encrypted-filenames.patch
+f2fs-prevent-creating-duplicate-encrypted-filenames.patch
+ubifs-prevent-creating-duplicate-encrypted-filenames.patch
diff --git a/queue-4.19/ubifs-prevent-creating-duplicate-encrypted-filenames.patch b/queue-4.19/ubifs-prevent-creating-duplicate-encrypted-filenames.patch
new file mode 100644 (file)
index 0000000..30a6e8a
--- /dev/null
@@ -0,0 +1,89 @@
+From foo@baz Wed Dec 30 04:40:58 PM CET 2020
+From: Eric Biggers <ebiggers@kernel.org>
+Date: Mon, 28 Dec 2020 11:12:11 -0800
+Subject: ubifs: prevent creating duplicate encrypted filenames
+To: stable@vger.kernel.org
+Cc: linux-fscrypt@vger.kernel.org, linux-ext4@vger.kernel.org, linux-f2fs-devel@lists.sourceforge.net, linux-mtd@lists.infradead.org
+Message-ID: <20201228191211.138300-5-ebiggers@kernel.org>
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 76786a0f083473de31678bdb259a3d4167cf756d upstream.
+
+As described in "fscrypt: add fscrypt_is_nokey_name()", it's possible to
+create a duplicate filename in an encrypted directory by creating a file
+concurrently with adding the directory's encryption key.
+
+Fix this bug on ubifs by rejecting no-key dentries in ubifs_create(),
+ubifs_mkdir(), ubifs_mknod(), and ubifs_symlink().
+
+Note that ubifs doesn't actually report the duplicate filenames from
+readdir, but rather it seems to replace the original dentry with a new
+one (which is still wrong, just a different effect from ext4).
+
+On ubifs, this fixes xfstest generic/595 as well as the new xfstest I
+wrote specifically for this bug.
+
+Fixes: f4f61d2cc6d8 ("ubifs: Implement encrypted filenames")
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20201118075609.120337-5-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ubifs/dir.c |   17 +++++++++++++----
+ 1 file changed, 13 insertions(+), 4 deletions(-)
+
+--- a/fs/ubifs/dir.c
++++ b/fs/ubifs/dir.c
+@@ -290,6 +290,15 @@ done:
+       return d_splice_alias(inode, dentry);
+ }
++static int ubifs_prepare_create(struct inode *dir, struct dentry *dentry,
++                              struct fscrypt_name *nm)
++{
++      if (fscrypt_is_nokey_name(dentry))
++              return -ENOKEY;
++
++      return fscrypt_setup_filename(dir, &dentry->d_name, 0, nm);
++}
++
+ static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
+                       bool excl)
+ {
+@@ -313,7 +322,7 @@ static int ubifs_create(struct inode *di
+       if (err)
+               return err;
+-      err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
++      err = ubifs_prepare_create(dir, dentry, &nm);
+       if (err)
+               goto out_budg;
+@@ -977,7 +986,7 @@ static int ubifs_mkdir(struct inode *dir
+       if (err)
+               return err;
+-      err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
++      err = ubifs_prepare_create(dir, dentry, &nm);
+       if (err)
+               goto out_budg;
+@@ -1062,7 +1071,7 @@ static int ubifs_mknod(struct inode *dir
+               return err;
+       }
+-      err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
++      err = ubifs_prepare_create(dir, dentry, &nm);
+       if (err) {
+               kfree(dev);
+               goto out_budg;
+@@ -1146,7 +1155,7 @@ static int ubifs_symlink(struct inode *d
+       if (err)
+               return err;
+-      err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
++      err = ubifs_prepare_create(dir, dentry, &nm);
+       if (err)
+               goto out_budg;