--- /dev/null
+From 77f30bfcfcf484da7208affd6a9e63406420bf91 Mon Sep 17 00:00:00 2001
+From: Eric Biggers <ebiggers@google.com>
+Date: Thu, 27 May 2021 16:52:36 -0700
+Subject: fscrypt: don't ignore minor_hash when hash is 0
+
+From: Eric Biggers <ebiggers@google.com>
+
+commit 77f30bfcfcf484da7208affd6a9e63406420bf91 upstream.
+
+When initializing a no-key name, fscrypt_fname_disk_to_usr() sets the
+minor_hash to 0 if the (major) hash is 0.
+
+This doesn't make sense because 0 is a valid hash code, so we shouldn't
+ignore the filesystem-provided minor_hash in that case. Fix this by
+removing the special case for 'hash == 0'.
+
+This is an old bug that appears to have originated when the encryption
+code in ext4 and f2fs was moved into fs/crypto/. The original ext4 and
+f2fs code passed the hash by pointer instead of by value. So
+'if (hash)' actually made sense then, as it was checking whether a
+pointer was NULL. But now the hashes are passed by value, and
+filesystems just pass 0 for any hashes they don't have. There is no
+need to handle this any differently from the hashes actually being 0.
+
+It is difficult to reproduce this bug, as it only made a difference in
+the case where a filename's 32-bit major hash happened to be 0.
+However, it probably had the largest chance of causing problems on
+ubifs, since ubifs uses minor_hash to do lookups of no-key names, in
+addition to using it as a readdir cookie. ext4 only uses minor_hash as
+a readdir cookie, and f2fs doesn't use minor_hash at all.
+
+Fixes: 0b81d0779072 ("fs crypto: move per-file encryption from f2fs tree to fs/crypto")
+Cc: <stable@vger.kernel.org> # v4.6+
+Link: https://lore.kernel.org/r/20210527235236.2376556-1-ebiggers@kernel.org
+Signed-off-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/crypto/fname.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/fs/crypto/fname.c
++++ b/fs/crypto/fname.c
+@@ -294,12 +294,8 @@ int fscrypt_fname_disk_to_usr(struct ino
+ oname->name);
+ return 0;
+ }
+- if (hash) {
+- memcpy(buf, &hash, 4);
+- memcpy(buf + 4, &minor_hash, 4);
+- } else {
+- memset(buf, 0, 8);
+- }
++ memcpy(buf, &hash, 4);
++ memcpy(buf + 4, &minor_hash, 4);
+ memcpy(buf + 8, iname->name + ((iname->len - 17) & ~15), 16);
+ oname->name[0] = '_';
+ oname->len = 1 + digest_encode(buf, 24, oname->name + 1);