Whamcloud - gitweb
LU-17606 ldiskfs: remove old el8.[123] patches/series
[fs/lustre-release.git] / ldiskfs / kernel_patches / patches / rhel8 / ext4-filename-encode.patch
diff --git a/ldiskfs/kernel_patches/patches/rhel8/ext4-filename-encode.patch b/ldiskfs/kernel_patches/patches/rhel8/ext4-filename-encode.patch
deleted file mode 100644 (file)
index 7a9f591..0000000
+++ /dev/null
@@ -1,385 +0,0 @@
-diff -wur /dev/null b/fs/ext4/critical_encode.h
---- /dev/null
-+++ b/fs/ext4/critical_encode.h
-@@ -0,0 +1,166 @@
-+/*
-+ *  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);
-+}
-+
-+static inline int ext4_prepare_lookup(struct inode *dir,
-+                                         struct dentry *dentry,
-+                                         unsigned int flags)
-+{
-+      if (unlikely(!IS_LUSTRE_MOUNT(dir->i_sb)))
-+              return 0;
-+        return fscrypt_prepare_lookup(dir, dentry, flags);
-+}
-+
-+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 -wur a/fs/ext4/dir.c b/fs/ext4/dir.c
---- a/fs/ext4/dir.c
-+++ b/fs/ext4/dir.c
-@@ -28,6 +28,7 @@
- #include <linux/iversion.h>
- #include "ext4.h"
- #include "xattr.h"
-+#include "critical_encode.h"
- static int ext4_dx_readdir(struct file *, struct dir_context *);
-@@ -144,7 +145,8 @@ static int ext4_readdir(struct file *
-                       return err;
-       }
--      if (IS_ENCRYPTED(inode)) {
-+      /* disable decryption of filename, present only escaped name */
-+      if (0 && IS_ENCRYPTED(inode)) {
-               err = fscrypt_fname_alloc_buffer(inode, EXT4_NAME_LEN, &fstr);
-               if (err < 0)
-                       return err;
-@@ -258,22 +259,33 @@ static int ext4_readdir(struct file *
-                                           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,
-                                               0, 0, &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 -wur a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
---- 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 -wur a/fs/ext4/namei.c b/fs/ext4/namei.c
---- a/fs/ext4/namei.c
-+++ b/fs/ext4/namei.c
-@@ -40,6 +40,7 @@
- #include "xattr.h"
- #include "acl.h"
-+#include "critical_encode.h"
- #include <trace/events/ext4.h>
- /*
-@@ -1368,22 +1369,31 @@ static int htree_dirblock_to_tree(struct
-                                  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;
-@@ -1614,7 +1614,7 @@ static void dx_insert_block(struct dx_fr
-  * Return: %true if the directory entry matches, otherwise %false.
-  */
- static inline bool ext4_match(const struct ext4_filename *fname,
--                            const struct ext4_dir_entry_2 *de)
-+                            const struct ext4_dir_entry_2 *de, int denamelen)
- {
-       struct fscrypt_name f;
-@@ -1626,7 +1626,7 @@ static inline bool ext4_match(const s
- #ifdef CONFIG_EXT4_FS_ENCRYPTION
-       f.crypto_buf = fname->crypto_buf;
- #endif
--      return fscrypt_match_name(&f, de->name, de->name_len);
-+      return fscrypt_match_name(&f, de->name, denamelen);
- }
- /*
-@@ -1637,16 +1637,30 @@ int ext4_search_dir(struct buffer_hea
-                   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) {
-               /* 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 ((char *) de + de->name_len <= dlimit &&
--                  ext4_match(fname, de)) {
-+                  ext4_match(fname, de, denamelen)) {
-                       /* found a match - just to be sure, do
-                        * a full check */
-                       if (ext4_check_dir_entry(dir, NULL, de, bh, bh->b_data,
-@@ -1707,7 +1717,7 @@ struct buffer_head *__ext4_find_entry
-       if (namelen > EXT4_NAME_LEN)
-               return NULL;
--      retval = ext4_fname_setup_filename(dir, d_name, 1, &fname);
-+      retval = ext4_setup_filename(dir, d_name, 1, &fname);
-       if (retval == -ENOENT)
-               return NULL;
-       if (retval)
-@@ -1834,7 +1844,8 @@ cleanup_and_exit:
-       /* Clean up the read-ahead blocks */
-       for (; ra_ptr < ra_max; ra_ptr++)
-               brelse(bh_use[ra_ptr]);
--      ext4_fname_free_filename(&fname);
-+      if (fname.disk_name.name != d_name->name)
-+              kfree(fname.disk_name.name);
-       return ret;
- }
- EXPORT_SYMBOL(__ext4_find_entry);
-@@ -1900,7 +1911,7 @@ static struct dentry *ext4_lookup(str
-       struct buffer_head *bh;
-       int err;
--      err = fscrypt_prepare_lookup(dir, dentry, flags);
-+      err = ext4_prepare_lookup(dir, dentry, flags);
-       if (err)
-               return ERR_PTR(err);
-@@ -1957,7 +1957,7 @@ static struct dentry *ext4_lookup(struct
-               }
-               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);
-@@ -2206,7 +2221,7 @@ int ext4_find_dest_de(struct inode *d
-               if (ext4_check_dir_entry(dir, NULL, de, bh,
-                                        buf, buf_size, offset))
-                       return -EFSCORRUPTED;
--              if (ext4_match(fname, de))
-+              if (ext4_match(fname, de, de->name_len))
-                       return -EEXIST;
-               nlen = EXT4_DIR_ENTRY_LEN(de);
-               rlen = ext4_rec_len_from_disk(de->rec_len, buf_size);