Whamcloud - gitweb
Revert "LU-17131 ldiskfs: el9.2 encdata and filename-encode" 69/53069/3
authorAndreas Dilger <adilger@whamcloud.com>
Fri, 10 Nov 2023 04:54:35 +0000 (04:54 +0000)
committerOleg Drokin <green@whamcloud.com>
Sat, 18 Nov 2023 21:47:23 +0000 (21:47 +0000)
This reverts commit b0cc96a1ff516f79f26be32945a237ef8373e408
as it is likely causing ldiskfs to crash immediately at mount:

 LDISKFS-fs (dm-0): mounted filesystem with ordered data mode. Quota mode: journalled.
 BUG: kernel NULL pointer dereference, address: 0000000000000000
 #PF: error_code(0x0000) - not-present page
 Oops: 0000 [#1] PREEMPT SMP PTI
 CPU: 0 PID: 7148 Comm: mkfs.lustre  5.14.0-284.30.1_lustre.el9.x86_64 #1
 Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011
 RIP: 0010:__ldiskfs_find_entry+0xab/0x440 [ldiskfs]
 Call Trace:
  ldiskfs_lookup.part.0+0x6c/0x2c0 [ldiskfs]
  __lookup_hash+0x70/0xa0
  __filename_create+0x87/0x150
  do_mkdirat+0x4b/0x160
  __x64_sys_mkdir+0x48/0x70

Change-Id: Idc8448c9e6d2300bc5eccb6ea190252eaaca9f75
Test-Parameters: trivial
Test-Parameters: serverdistro=el9.2 testlist=sanity
Test-Parameters: serverdistro=el9.2 testlist=conf-sanity
Signed-off-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/53069
Reviewed-by: Alex Zhuravlev <bzzz@whamcloud.com>
Reviewed-by: Shaun Tancheff <shaun.tancheff@hpe.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
ldiskfs/kernel_patches/patches/rhel9.2/ext4-encdata.patch [deleted file]
ldiskfs/kernel_patches/patches/rhel9.2/ext4-filename-encode.patch [deleted file]
ldiskfs/kernel_patches/series/ldiskfs-5.14-rhel9.2.series

diff --git a/ldiskfs/kernel_patches/patches/rhel9.2/ext4-encdata.patch b/ldiskfs/kernel_patches/patches/rhel9.2/ext4-encdata.patch
deleted file mode 100644 (file)
index a7a71c8..0000000
+++ /dev/null
@@ -1,441 +0,0 @@
-diff --git a/fs/ext4/encdata.h b/fs/ext4/encdata.h
-new file mode 100644
-index 00000000..aa83832f
---- /dev/null
-+++ b/fs/ext4/encdata.h
-@@ -0,0 +1,128 @@
-+/*
-+ *  encdata.h
-+ *
-+ *  Copyright (c) 2022 Whamcloud
-+ */
-+
-+#ifndef _ENCDATA_H
-+#define _ENCDATA_H
-+
-+/* Define a fixed 4096-byte encryption unit size */
-+/* Must be identical to LUSTRE_ENCRYPTION_UNIT_SIZE */
-+#define EXT4_ENCRYPTION_BLOCKBITS 12
-+#define EXT4_ENCRYPTION_UNIT_SIZE ((size_t)1 << EXT4_ENCRYPTION_BLOCKBITS)
-+#define EXT4_ENCRYPTION_MASK      (~(EXT4_ENCRYPTION_UNIT_SIZE - 1))
-+#define LLCRYPT_SET_CONTEXT_MAX_SIZE  40
-+#define ENCDATA_XATTR_FMT_1 "{ encoding: "
-+#define ENCDATA_XATTR_FMT_2 ", size: "
-+#define ENCDATA_XATTR_FMT_3 ", enc_ctx: "
-+#define ENCDATA_XATTR_FMT_4 ", enc_name: "
-+#define ENCDATA_XATTR_FMT_END " }"
-+#define ENCDATA_XATTR_FMT_COMP  ENCDATA_XATTR_FMT_1 ENCDATA_XATTR_FMT_2 \
-+                              ENCDATA_XATTR_FMT_3 ENCDATA_XATTR_FMT_4 \
-+                              ENCDATA_XATTR_FMT_END
-+
-+extern char encdata_xattr_fmt[NAME_MAX];
-+
-+/*
-+ * base64url encoding, lifted from fs/crypto/fname.c.
-+ */
-+
-+static const char base64url_table[] =
-+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-+
-+#define BASE64URL_CHARS(nbytes)       DIV_ROUND_UP((nbytes) * 4, 3)
-+
-+/**
-+ * base64url_encode() - base64url-encode some binary data
-+ * @src: the binary data to encode
-+ * @srclen: the length of @src in bytes
-+ * @dst: (output) the base64url-encoded string.  Not NUL-terminated.
-+ *
-+ * Encodes data using base64url encoding, i.e. the "Base 64 Encoding with URL
-+ * and Filename Safe Alphabet" specified by RFC 4648.  '='-padding isn't used,
-+ * as it's unneeded and not required by the RFC.  base64url is used instead of
-+ * base64 to avoid the '/' character, which isn't allowed in filenames.
-+ *
-+ * Return: the length of the resulting base64url-encoded string in bytes.
-+ *       This will be equal to LLCRYPT_BASE64URL_CHARS(srclen).
-+ */
-+static inline int base64url_encode(const u8 *src, int srclen, char *dst)
-+{
-+      u32 ac = 0;
-+      int bits = 0;
-+      int i;
-+      char *cp = dst;
-+
-+      for (i = 0; i < srclen; i++) {
-+              ac = (ac << 8) | src[i];
-+              bits += 8;
-+              do {
-+                      bits -= 6;
-+                      *cp++ = base64url_table[(ac >> bits) & 0x3f];
-+              } while (bits >= 6);
-+      }
-+      if (bits)
-+              *cp++ = base64url_table[(ac << (6 - bits)) & 0x3f];
-+      return cp - dst;
-+}
-+
-+/**
-+ * base64url_decode() - base64url-decode a string
-+ * @src: the string to decode.  Doesn't need to be NUL-terminated.
-+ * @srclen: the length of @src in bytes
-+ * @dst: (output) the decoded binary data
-+ *
-+ * Decodes a string using base64url encoding, i.e. the "Base 64 Encoding with
-+ * URL and Filename Safe Alphabet" specified by RFC 4648.  '='-padding isn't
-+ * accepted, nor are non-encoding characters such as whitespace.
-+ *
-+ * This implementation hasn't been optimized for performance.
-+ *
-+ * Return: the length of the resulting decoded binary data in bytes,
-+ *       or -1 if the string isn't a valid base64url string.
-+ */
-+static inline int base64url_decode(const char *src, int srclen, u8 *dst)
-+{
-+      u32 ac = 0;
-+      int bits = 0;
-+      int i;
-+      u8 *bp = dst;
-+
-+      for (i = 0; i < srclen; i++) {
-+              const char *p = strchr(base64url_table, src[i]);
-+
-+              if (p == NULL || src[i] == 0)
-+                      return -1;
-+              ac = (ac << 6) | (p - base64url_table);
-+              bits += 6;
-+              if (bits >= 8) {
-+                      bits -= 8;
-+                      *bp++ = (u8)(ac >> bits);
-+              }
-+      }
-+      if (ac & ((1 << bits) - 1))
-+              return -1;
-+      return bp - dst;
-+}
-+
-+/* This version of the code uses base64url encoding for binary data. */
-+#define ENCDATA_ENCODING      "base64url"
-+
-+/* Wrappers to support various encodings. Add new methods in there.
-+ */
-+static inline int encode(const u8 *src, int srclen, char *dst, char *encoding)
-+{
-+      if (!strcmp(encoding, "base64url"))
-+              return base64url_encode(src, srclen, dst);
-+      return -EINVAL;
-+}
-+
-+static inline int decode(const char *src, int srclen, u8 *dst, char *encoding)
-+{
-+      if (!strcmp(encoding, "base64url"))
-+              return base64url_decode(src, srclen, dst);
-+      return -EINVAL;
-+}
-+
-+#endif /* _ENCDATA_H */
-diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
-index fb500d12..769eabce 100644
---- a/fs/ext4/inode.c
-+++ b/fs/ext4/inode.c
-@@ -46,6 +46,7 @@
- #include "xattr.h"
- #include "acl.h"
- #include "truncate.h"
-+#include "encdata.h"
- #include <trace/events/ext4.h>
-@@ -5620,6 +5621,12 @@ int ext4_getattr(struct user_namespace *mnt_userns, const struct path *path,
-                                 STATX_ATTR_VERITY);
-       generic_fillattr(mnt_userns, inode, stat);
-+
-+      if (flags & EXT4_ENCRYPT_FL &&
-+          unlikely(!IS_LUSTRE_MOUNT(inode->i_sb)))
-+              stat->size = round_up(stat->size,
-+                                    EXT4_ENCRYPTION_UNIT_SIZE);
-+
-       return 0;
- }
-diff --git a/fs/ext4/super.c b/fs/ext4/super.c
-index 89d609c9..fd066751 100644
---- a/fs/ext4/super.c
-+++ b/fs/ext4/super.c
-@@ -55,6 +55,7 @@
- #include "acl.h"
- #include "mballoc.h"
- #include "fsmap.h"
-+#include "encdata.h"
- #define CREATE_TRACE_POINTS
- #include <trace/events/ext4.h>
-@@ -7260,6 +7261,7 @@ MODULE_ALIAS_FS("ext4");
- /* Shared across all ext4 file systems */
- wait_queue_head_t ext4__ioend_wq[EXT4_WQ_HASH_SZ];
-+char encdata_xattr_fmt[NAME_MAX];
- static int __init ext4_init_fs(void)
- {
-@@ -7313,6 +7315,12 @@ static int __init ext4_init_fs(void)
-       if (err)
-               goto out;
-+      snprintf(encdata_xattr_fmt, sizeof(encdata_xattr_fmt),
-+               ENCDATA_XATTR_FMT_1"%%%u[^,]"ENCDATA_XATTR_FMT_2"%%llu"
-+               ENCDATA_XATTR_FMT_3"%%%us"ENCDATA_XATTR_FMT_4"%%%us",
-+               NAME_MAX, BASE64URL_CHARS(LLCRYPT_SET_CONTEXT_MAX_SIZE),
-+               BASE64URL_CHARS(NAME_MAX));
-+
-       return 0;
- out:
-       ext4_fc_destroy_dentry_cache();
-diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h
-index 824faf0b..1e8aa6f2 100644
---- a/fs/ext4/xattr.h
-+++ b/fs/ext4/xattr.h
-@@ -140,6 +140,8 @@ extern const struct xattr_handler ext4_xattr_security_handler;
- extern const struct xattr_handler ext4_xattr_hurd_handler;
- #define EXT4_XATTR_NAME_ENCRYPTION_CONTEXT "c"
-+#define EXT4_XATTR_NAME_ENCDATA             "encdata"
-+#define EXT4_XATTR_NAME_RAWENCNAME          "rawencname"
- /*
-  * The EXT4_STATE_NO_EXPAND is overloaded and used for two purposes.
-diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
-index 8213f66f..6fb465a8 100644
---- a/fs/ext4/xattr_security.c
-+++ b/fs/ext4/xattr_security.c
-@@ -10,13 +10,217 @@
- #include <linux/slab.h>
- #include "ext4_jbd2.h"
- #include "ext4.h"
-+#include "critical_encode.h"
-+#include "encdata.h"
- #include "xattr.h"
-+/* security.encdata is a virtual xattr containing information related
-+ * to encrypted files. It is expressed as ASCII text with a "key: value"
-+ * format, and space as field separator. For instance:
-+ *
-+ *    { encoding: base64url, size: 3012, enc_ctx: YWJjZGVmZ2hpamtsbW
-+ *    5vcHFyc3R1dnd4eXphYmNkZWZnaGlqa2xtbg, enc_name: ZmlsZXdpdGh2ZX
-+ *    J5bG9uZ25hbWVmaWxld2l0aHZlcnlsb25nbmFtZWZpbGV3aXRodmVyeWxvbmdu
-+ *    YW1lZmlsZXdpdGg }
-+ *
-+ * 'encoding' is the encoding method used for binary data, assume name
-+ * can be up to 255 chars.
-+ * 'size' is the clear text file data length in bytes.
-+ * 'enc_ctx' is encoded encryption context, 40 bytes for v2.
-+ * 'enc_name' is encoded encrypted name, 256 bytes max.
-+ * So on overall, this xattr is at most 727 chars plus terminating '\0'.
-+ */
-+static int ext4_build_xattr_encdata(struct dentry *dentry,
-+                                   struct inode *inode,
-+                                   void *buffer, size_t size)
-+{
-+      char encoded_enc_ctx[BASE64URL_CHARS(LLCRYPT_SET_CONTEXT_MAX_SIZE) + 1];
-+      unsigned char enc_ctx[LLCRYPT_SET_CONTEXT_MAX_SIZE];
-+      char encoded_name[BASE64URL_CHARS(NAME_MAX) + 1];
-+      struct ext4_filename fname = { 0 };
-+      struct inode *parent = NULL;
-+      int encoded_enc_ctx_len = 0;
-+      int encoded_name_len = 0;
-+      char size_str[32];
-+      int retval;
-+
-+      if (!IS_ENCRYPTED(inode)) {
-+              retval = -ENODATA;
-+              goto out;
-+      }
-+
-+      /* get size */
-+      retval = snprintf(size_str, sizeof(size_str), "%llu",
-+                        S_ISDIR(inode->i_mode) ? 0 : inode->i_size);
-+      if (retval >= sizeof(size_str)) {
-+              retval = -ERANGE;
-+              goto out;
-+      }
-+
-+      /* get raw name */
-+      if (dentry && dentry->d_parent)
-+              parent = dentry->d_parent->d_inode;
-+
-+      retval = ext4_setup_filename(parent, &dentry->d_name, 1, &fname);
-+      if (retval)
-+              goto out;
-+
-+      /* base64url-encode raw name */
-+      encoded_name_len = encode(fname.disk_name.name, fname.disk_name.len,
-+                                encoded_name, ENCDATA_ENCODING);
-+      if (encoded_name_len == -EINVAL) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+      encoded_name[encoded_name_len] = '\0';
-+
-+      if (!buffer) {
-+              /* Return exact xattr length we would return if called with
-+               * non-NULL buffer.
-+               */
-+              retval = sizeof(ENCDATA_XATTR_FMT_COMP) - 1 +
-+                      sizeof(ENCDATA_ENCODING) - 1 + strlen(size_str) +
-+                      BASE64URL_CHARS(LLCRYPT_SET_CONTEXT_MAX_SIZE) +
-+                      encoded_name_len;
-+              goto out;
-+      }
-+
-+      /* get encryption context */
-+      retval = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
-+                              EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
-+                              enc_ctx, sizeof(enc_ctx));
-+
-+      if (retval < 0)
-+              goto out;
-+
-+      /* base64url-encode encryption context */
-+      encoded_enc_ctx_len = encode(enc_ctx, retval, encoded_enc_ctx,
-+                                   ENCDATA_ENCODING);
-+      if (encoded_enc_ctx_len == -EINVAL) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+      encoded_enc_ctx[encoded_enc_ctx_len] = '\0';
-+
-+      /* write EXT4_XATTR_ENCDATA info into buffer */
-+      retval = snprintf(buffer, size,
-+                        ENCDATA_XATTR_FMT_1 ENCDATA_ENCODING
-+                        ENCDATA_XATTR_FMT_2"%s"ENCDATA_XATTR_FMT_3"%s"
-+                        ENCDATA_XATTR_FMT_4"%s"ENCDATA_XATTR_FMT_END,
-+                        size_str, encoded_enc_ctx,
-+                        encoded_name_len ? encoded_name : "");
-+      if (retval >= size)
-+              retval = -ERANGE;
-+
-+out:
-+      if (fname.disk_name.name != dentry->d_name.name)
-+              kfree(fname.disk_name.name);
-+
-+      return retval;
-+}
-+
-+static int ext4_process_xattr_encdata(struct inode *inode,
-+                                     const void *value, size_t size,
-+                                     int flags)
-+{
-+      char encoded_enc_ctx[BASE64URL_CHARS(LLCRYPT_SET_CONTEXT_MAX_SIZE) + 1];
-+      unsigned char enc_ctx[LLCRYPT_SET_CONTEXT_MAX_SIZE];
-+      char encoded_name[BASE64URL_CHARS(NAME_MAX) + 1];
-+      char encoding[NAME_MAX + 1];
-+      char name[NAME_MAX + 1];
-+      loff_t disk_size = 0;
-+      char *buffer = NULL;
-+      int enc_ctx_len = 0;
-+      int name_len = 0;
-+      int retval = 0;
-+
-+      if (IS_ENCRYPTED(inode) || !value || flags & XATTR_REPLACE) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      buffer = kmalloc(size + 1, GFP_NOFS);
-+      if (!buffer) {
-+              retval = -ENOMEM;
-+              goto out;
-+      }
-+      memcpy(buffer, value, size);
-+      buffer[size] = '\0';
-+
-+      retval = sscanf(buffer, encdata_xattr_fmt,
-+                      encoding, &disk_size, encoded_enc_ctx, encoded_name);
-+      if (retval < 4) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* get former encryption context: should not exist */
-+      retval = ext4_xattr_get(inode, EXT4_XATTR_INDEX_ENCRYPTION,
-+                              EXT4_XATTR_NAME_ENCRYPTION_CONTEXT, NULL, 0);
-+      if (retval != -ENODATA) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      if (strlen(encoded_enc_ctx) >
-+          BASE64URL_CHARS(LLCRYPT_SET_CONTEXT_MAX_SIZE)) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+
-+      /* base64url-decode encryption context */
-+      retval = decode(encoded_enc_ctx, strlen(encoded_enc_ctx),
-+                      enc_ctx, encoding);
-+      if (retval < 0) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+      enc_ctx_len = retval;
-+
-+      /* set encryption context, this will set encryption flag */
-+      retval = ext4_xattr_set(inode, EXT4_XATTR_INDEX_ENCRYPTION,
-+                              EXT4_XATTR_NAME_ENCRYPTION_CONTEXT,
-+                              enc_ctx, enc_ctx_len, XATTR_CREATE);
-+      if (retval < 0)
-+              goto out;
-+
-+      if (disk_size) {
-+              /* set size on inode */
-+              spin_lock(&inode->i_lock);
-+              i_size_write(inode, disk_size);
-+              EXT4_I(inode)->i_disksize = disk_size;
-+              spin_unlock(&inode->i_lock);
-+              mark_inode_dirty(inode);
-+      }
-+
-+      /* put raw encrypted name in EXT4_XATTR_NAME_RAWENCNAME xattr,
-+       * for later use, but base64url-decode first
-+       */
-+      retval = decode(encoded_name, strlen(encoded_name), name, encoding);
-+      if (retval < 0) {
-+              retval = -EINVAL;
-+              goto out;
-+      }
-+      name_len = retval;
-+
-+      retval = ext4_xattr_set(inode, EXT4_XATTR_INDEX_LUSTRE,
-+                              EXT4_XATTR_NAME_RAWENCNAME,
-+                              name, name_len, XATTR_CREATE);
-+
-+out:
-+      kfree(buffer);
-+
-+      return retval;
-+}
-+
- static int
- ext4_xattr_security_get(const struct xattr_handler *handler,
--                      struct dentry *unused, struct inode *inode,
-+                         struct dentry *dentry, struct inode *inode,
-                       const char *name, void *buffer, size_t size)
- {
-+      if (!strncmp(name, EXT4_XATTR_NAME_ENCDATA, strlen(name)))
-+              return ext4_build_xattr_encdata(dentry, inode, buffer, size);
-+
-       return ext4_xattr_get(inode, EXT4_XATTR_INDEX_SECURITY,
-                             name, buffer, size);
- }
-@@ -28,6 +232,9 @@ ext4_xattr_security_set(const struct xattr_handler *handler,
-                       const char *name, const void *value,
-                       size_t size, int flags)
- {
-+      if (!strncmp(name, EXT4_XATTR_NAME_ENCDATA, strlen(name)))
-+              return ext4_process_xattr_encdata(inode, value, size, flags);
-+
-       return ext4_xattr_set(inode, EXT4_XATTR_INDEX_SECURITY,
-                             name, value, size, flags);
- }
--- 
-2.25.1
-
diff --git a/ldiskfs/kernel_patches/patches/rhel9.2/ext4-filename-encode.patch b/ldiskfs/kernel_patches/patches/rhel9.2/ext4-filename-encode.patch
deleted file mode 100644 (file)
index e40ac38..0000000
+++ /dev/null
@@ -1,398 +0,0 @@
-diff --git a/fs/ext4/critical_encode.h b/fs/ext4/critical_encode.h
-new file mode 100644
-index 00000000..a624594d
---- /dev/null
-+++ b/fs/ext4/critical_encode.h
-@@ -0,0 +1,168 @@
-+/*
-+ *  critical_encode.h
-+ *
-+ *  Copyright (c) 2022 Whamcloud
-+ */
-+
-+#ifndef _CRITICAL_ENCODE_H
-+#define _CRITICAL_ENCODE_H
-+
-+#include <linux/ctype.h>
-+
-+/* Encoding/decoding routines inspired from yEnc principles.
-+ * We just take care of a few critical characters:
-+ * NULL, LF, CR, /, DEL and =.
-+ * If such a char is found, it is replaced with '=' followed by
-+ * the char value + 64.
-+ * All other chars are left untouched.
-+ * Efficiency of this encoding depends on the occurences of the
-+ * critical chars, but statistically on binary data it can be much higher
-+ * than base64 for instance.
-+ */
-+static inline int critical_encode(const u8 *src, int len, char *dst)
-+{
-+      u8 *p = (u8 *)src, *q = dst;
-+
-+      while (p - src < len) {
-+              /* escape NULL, LF, CR, /, DEL and = */
-+              if (unlikely(*p == 0x0 || *p == 0xA || *p == 0xD ||
-+                           *p == '/' || *p == 0x7F || *p == '=')) {
-+                      *(q++) = '=';
-+                      *(q++) = *(p++) + 64;
-+              } else {
-+                      *(q++) = *(p++);
-+              }
-+      }
-+
-+      return (char *)q - dst;
-+}
-+
-+/* returns the number of chars encoding would produce */
-+static inline int critical_chars(const u8 *src, int len)
-+{
-+      u8 *p = (u8 *)src;
-+      int newlen = len;
-+
-+      while (p - src < len) {
-+              /* NULL, LF, CR, /, DEL and = cost an additional '=' */
-+              if (unlikely(*p == 0x0 || *p == 0xA || *p == 0xD ||
-+                           *p == '/' || *p == 0x7F || *p == '='))
-+                      newlen++;
-+              p++;
-+      }
-+
-+      return newlen;
-+}
-+
-+/* decoding routine - returns the number of chars in output */
-+static inline int critical_decode(const u8 *src, int len, char *dst)
-+{
-+      u8 *p = (u8 *)src, *q = dst;
-+
-+      while (p - src < len) {
-+              if (unlikely(*p == '=')) {
-+                      *(q++) = *(++p) - 64;
-+                      p++;
-+              } else {
-+                      *(q++) = *(p++);
-+              }
-+      }
-+
-+      return (char *)q - dst;
-+}
-+
-+#define fscrypt_get_encryption_info(inode) \
-+      (unlikely(!IS_LUSTRE_MOUNT(inode->i_sb)) ? 0 : -EOPNOTSUPP)
-+
-+static inline int ext4_has_permitted_context(struct inode *parent,
-+                                      struct inode *child)
-+{
-+      if (unlikely(!IS_LUSTRE_MOUNT(parent->i_sb)))
-+              return 1;
-+      return fscrypt_has_permitted_context(parent, child);
-+}
-+
-+struct ext4_filename;
-+
-+static inline int ext4_prepare_lookup(struct inode *dir,
-+                                         struct dentry *dentry,
-+                                         struct ext4_filename *fname)
-+{
-+      if (unlikely(!IS_LUSTRE_MOUNT(dir->i_sb)))
-+              return 0;
-+        return ext4_fname_prepare_lookup(dir, dentry, fname);
-+}
-+
-+static inline int ext4_fname_alloc_buffer(const struct inode *inode,
-+                                           u32 max_encrypted_len,
-+                                           struct fscrypt_str *crypto_str)
-+{
-+      crypto_str->name = kmalloc(max_encrypted_len + 1, GFP_NOFS);
-+      if (!crypto_str->name)
-+              return -ENOMEM;
-+      crypto_str->len = max_encrypted_len;
-+      return 0;
-+}
-+
-+static inline void ext4_fname_free_buffer(struct fscrypt_str *crypto_str)
-+{
-+      if (!crypto_str)
-+              return;
-+      kfree(crypto_str->name);
-+      crypto_str->name = NULL;
-+}
-+
-+static inline int ext4_fname_disk_to_usr(struct inode *inode,
-+                                          u32 hash, u32 minor_hash,
-+                                          const struct fscrypt_str *iname,
-+                                          struct fscrypt_str *oname)
-+{
-+      int presented_len;
-+
-+      presented_len = critical_encode(iname->name, iname->len, oname->name);
-+      if (presented_len > NAME_MAX) {
-+              /* truncate at NAME_MAX,
-+               * or NAME_MAX-1 if name ends with '=' to avoid decoding issue
-+               */
-+              presented_len = NAME_MAX;
-+              if (oname->name[presented_len - 1] == '=')
-+                      presented_len--;
-+              oname->len = presented_len;
-+      }
-+      oname->name[presented_len] = '\0';
-+
-+      return 0;
-+}
-+
-+static inline int ext4_setup_filename(struct inode *dir,
-+                                       const struct qstr *iname,
-+                                       int lookup,
-+                                       struct ext4_filename *fname)
-+{
-+      fname->usr_fname = iname;
-+
-+      if (lookup && IS_ENCRYPTED(dir) &&
-+          unlikely(!IS_LUSTRE_MOUNT(dir->i_sb) &&
-+                   strnchr(iname->name, iname->len, '='))) {
-+              /* Only proceed to critical decode if
-+               * iname contains escape char '='.
-+               */
-+              int len = iname->len;
-+              char *buf;
-+
-+              buf = kmalloc(len, GFP_NOFS);
-+              if (!buf)
-+                      return -ENOMEM;
-+
-+              len = critical_decode(iname->name, len, buf);
-+              fname->disk_name.name = (unsigned char *)buf;
-+              fname->disk_name.len = len;
-+              return 0;
-+      }
-+
-+      fname->disk_name.name = (unsigned char *) iname->name;
-+      fname->disk_name.len = iname->len;
-+      return 0;
-+}
-+
-+#endif /* _CRITICAL_ENCODE_H */
-diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c
-index b8e4df14..a3e4904e 100644
---- a/fs/ext4/dir.c
-+++ b/fs/ext4/dir.c
-@@ -29,6 +29,7 @@
- #include <linux/unicode.h>
- #include "ext4.h"
- #include "xattr.h"
-+#include "critical_encode.h"
- static int ext4_dx_readdir(struct file *, struct dir_context *);
-@@ -161,7 +162,8 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
-                       return err;
-       }
--      if (IS_ENCRYPTED(inode)) {
-+      /* disable decryption of filename, present only escaped name */
-+      if (0 && IS_ENCRYPTED(inode)) {
-               err = fscrypt_fname_alloc_buffer(EXT4_NAME_LEN, &fstr);
-               if (err < 0)
-                       return err;
-@@ -275,24 +277,35 @@ static int ext4_readdir(struct file *file, struct dir_context *ctx)
-                                           get_dtype(sb, de->file_type)))
-                                               goto done;
-                               } else {
--                                      int save_len = fstr.len;
-                                       struct fscrypt_str de_name =
-                                                       FSTR_INIT(de->name,
-                                                               de->name_len);
-+                                      int presented_len;
-                                       /* Directory is encrypted */
--                                      err = fscrypt_fname_disk_to_usr(inode,
-+                                      presented_len = critical_chars(de->name,
-+                                                                de->name_len);
-+                                      err = ext4_fname_alloc_buffer(inode,
-+                                                                presented_len,
-+                                                                &fstr);
-+                                      if (err)
-+                                              goto errout;
-+
-+                                      err = ext4_fname_disk_to_usr(inode,
-                                               EXT4_DIRENT_HASH(de),
-                                               EXT4_DIRENT_MINOR_HASH(de),
-                                               &de_name, &fstr);
-                                       de_name = fstr;
--                                      fstr.len = save_len;
--                                      if (err)
-+                                      if (err) {
-+                                              ext4_fname_free_buffer(&fstr);
-                                               goto errout;
--                                      if (!dir_emit(ctx,
-+                                      }
-+                                      err = dir_emit(ctx,
-                                           de_name.name, de_name.len,
-                                           le32_to_cpu(de->inode),
--                                          get_dtype(sb, de->file_type)))
-+                                          get_dtype(sb, de->file_type));
-+                                      ext4_fname_free_buffer(&fstr);
-+                                      if (!err)
-                                               goto done;
-                               }
-                       }
-diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
-index 5d5641b6..8dee069a 100644
---- a/fs/ext4/ialloc.c
-+++ b/fs/ext4/ialloc.c
-@@ -30,6 +30,7 @@
- #include "ext4_jbd2.h"
- #include "xattr.h"
- #include "acl.h"
-+#include "critical_encode.h"
- #include <trace/events/ext4.h>
-diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
-index 4934a46a..8f35bd62 100644
---- a/fs/ext4/namei.c
-+++ b/fs/ext4/namei.c
-@@ -42,6 +42,7 @@
- #include "xattr.h"
- #include "acl.h"
-+#include "critical_encode.h"
- #include <trace/events/ext4.h>
- /*
-@@ -1478,22 +1479,31 @@ static int htree_dirblock_to_tree(struct file *dir_file,
-                                  hinfo->hash, hinfo->minor_hash, de,
-                                  &tmp_str);
-               } else {
--                      int save_len = fname_crypto_str.len;
-                       struct fscrypt_str de_name = FSTR_INIT(de->name,
-                                                               de->name_len);
-+                      int presented_len;
-                       /* Directory is encrypted */
--                      err = fscrypt_fname_disk_to_usr(dir, hinfo->hash,
-+                      presented_len = critical_chars(de->name, de->name_len);
-+                      err = ext4_fname_alloc_buffer(dir, presented_len,
-+                                                       &fname_crypto_str);
-+                      if (err) {
-+                              count = err;
-+                              goto errout;
-+                      }
-+
-+                      err = ext4_fname_disk_to_usr(dir, hinfo->hash,
-                                       hinfo->minor_hash, &de_name,
-                                       &fname_crypto_str);
-                       if (err) {
-+                              ext4_fname_free_buffer(&fname_crypto_str);
-                               count = err;
-                               goto errout;
-                       }
-                       err = ext4_htree_store_dirent(dir_file,
-                                  hinfo->hash, hinfo->minor_hash, de,
-                                       &fname_crypto_str);
--                      fname_crypto_str.len = save_len;
-+                      ext4_fname_free_buffer(&fname_crypto_str);
-               }
-               if (err != 0) {
-                       count = err;
-@@ -1818,7 +1828,7 @@ int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
-  */
- static bool ext4_match(struct inode *parent,
-                             const struct ext4_filename *fname,
--                            struct ext4_dir_entry_2 *de)
-+                            struct ext4_dir_entry_2 *de, int denamelen)
- {
-       struct fscrypt_name f;
-@@ -1853,7 +1863,7 @@ static bool ext4_match(struct inode *parent,
-       }
- #endif
--      return fscrypt_match_name(&f, de->name, de->name_len);
-+      return fscrypt_match_name(&f, de->name, denamelen);
- }
- /*
-@@ -1864,16 +1874,30 @@ int ext4_search_dir(struct buffer_head *bh, char *search_buf, int buf_size,
-                   unsigned int offset, struct ext4_dir_entry_2 **res_dir)
- {
-       struct ext4_dir_entry_2 * de;
-+      bool probablytrunc;
-       char * dlimit;
--      int de_len;
-+      int de_len, denamelen;
-       de = (struct ext4_dir_entry_2 *)search_buf;
-       dlimit = search_buf + buf_size;
-+      /* fname is probably truncated if it is the decoded representation of
-+       * an encrypted filename not aligned on a 32-byte boundary
-+       */
-+      probablytrunc = !IS_LUSTRE_MOUNT(dir->i_sb) && IS_ENCRYPTED(dir) &&
-+              fname->disk_name.len & 31;
-       while ((char *) de < dlimit - EXT4_BASE_DIR_LEN) {
-               /* this code is executed quadratically often */
-               /* do minimal checking `by hand' */
-+              denamelen = de->name_len;
-+              if (unlikely(probablytrunc) &&
-+                  de->name_len > fname->disk_name.len)
-+                      /* Adjust name len to look for a partial match.
-+                       * Since it is binary encrypted names, there
-+                       * should not be any collision between names.
-+                       */
-+                      denamelen = fname->disk_name.len;
-               if (de->name + de->name_len <= dlimit &&
--                  ext4_match(dir, fname, de)) {
-+                  ext4_match(dir, fname, de, denamelen)) {
-                       /* found a match - just to be sure, do
-                        * a full check */
-                       if (ext4_check_dir_entry(dir, NULL, de, bh, search_buf,
-@@ -2075,7 +2099,7 @@ struct buffer_head *ext4_find_entry_locked(struct inode *dir,
-       struct ext4_filename fname;
-       struct buffer_head *bh;
--      err = ext4_fname_setup_filename(dir, d_name, 1, &fname);
-+      err = ext4_setup_filename(dir, d_name, 1, &fname);
-       if (err == -ENOENT)
-               return NULL;
-       if (err)
-@@ -2083,7 +2107,9 @@ struct buffer_head *ext4_find_entry_locked(struct inode *dir,
-       bh = __ext4_find_entry(dir, &fname, res_dir, inlined, lck);
--      ext4_fname_free_filename(&fname);
-+      if (fname.disk_name.name != d_name->name)
-+              kfree(fname.disk_name.name);
-+
-       return bh;
- }
-@@ -2097,7 +2123,7 @@ static struct buffer_head *ext4_lookup_entry(struct inode *dir,
-       struct ext4_filename fname;
-       struct buffer_head *bh;
--      err = ext4_fname_prepare_lookup(dir, dentry, &fname);
-+      err = ext4_prepare_lookup(dir, dentry, &fname);
-       generic_set_encrypted_ci_d_ops(dentry);
-       if (err == -ENOENT)
-               return NULL;
-@@ -2198,7 +2224,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
-               }
-               if (!IS_ERR(inode) && IS_ENCRYPTED(dir) &&
-                   (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) &&
--                  !fscrypt_has_permitted_context(dir, inode)) {
-+                  !ext4_has_permitted_context(dir, inode)) {
-                       ext4_warning(inode->i_sb,
-                                    "Inconsistent encryption contexts: %lu/%lu",
-                                    dir->i_ino, inode->i_ino);
-@@ -2498,7 +2524,7 @@ int ext4_find_dest_de(struct inode *dir, struct inode *inode,
-               if (ext4_check_dir_entry(dir, NULL, de, bh,
-                                        buf, buf_size, offset))
-                       return -EFSCORRUPTED;
--              if (ext4_match(dir, fname, de))
-+              if (ext4_match(dir, fname, de, de->name_len))
-                       return -EEXIST;
-               nlen = EXT4_DIR_ENTRY_LEN(de, dir);
-               rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);
--- 
-2.25.1
-
index 078007e..243409e 100644 (file)
@@ -32,7 +32,5 @@ rhel8/ext4-ext-merge.patch
 linux-5.14/ext4-xattr-disable-credits-check.patch
 rhel9.2/ext4-fiemap-kernel-data.patch
 rhel8/ext4-old_ea_inodes_handling_fix.patch
-rhel9.2/ext4-filename-encode.patch
 rhel9.1/ext4-enc-flag.patch
-rhel9.2/ext4-encdata.patch
 rhel9/ext4-add-periodic-superblock-update.patch