[PATCH v6 0/9] ovl: Enable support for casefold layers

André Almeida posted 9 patches 1 month, 1 week ago
fs/overlayfs/copy_up.c   |   2 +-
fs/overlayfs/dir.c       |   7 +++
fs/overlayfs/inode.c     |   1 +
fs/overlayfs/namei.c     |  17 +++----
fs/overlayfs/overlayfs.h |   8 ++--
fs/overlayfs/ovl_entry.h |   1 +
fs/overlayfs/params.c    |  15 +++++--
fs/overlayfs/params.h    |   1 +
fs/overlayfs/readdir.c   | 113 +++++++++++++++++++++++++++++++++++++++--------
fs/overlayfs/super.c     |  51 +++++++++++++++++++++
fs/overlayfs/util.c      |  10 +++--
include/linux/fs.h       |  27 ++++++++++-
12 files changed, 213 insertions(+), 40 deletions(-)
[PATCH v6 0/9] ovl: Enable support for casefold layers
Posted by André Almeida 1 month, 1 week ago
Hi all,

We would like to support the usage of casefold layers with overlayfs to
be used with container tools. This use case requires a simple setup,
where every layer will have the same encoding setting (i.e. Unicode
version and flags), using one upper and one lower layer.

* Implementation

When merge layers, ovl uses a red-black tree to check if a given dentry
name from a lower layers already exists in the upper layer. For merging
case-insensitive names, we need to store then in tree casefolded.
However, when displaying to the user the dentry name, we need to respect
the name chosen when the file was created (e.g. Picture.PNG, instead of
picture.png). To achieve this, I create a new field for cache entries
that stores the casefolded names and a function ovl_strcmp() that uses
this name for searching the rb_tree. For composing the layer, ovl uses
the original name, keeping it consistency with whatever name the user
created.

The rest of the patches are mostly for checking if casefold is being
consistently used across the layers and dropping the mount restrictions
that prevented case-insensitive filesystems to be mounted.

Thanks for the feedback!

---
Changes in v6:
- Change pr_warn_ratelimited() message for ovl_create_real()
- Fixed kernel bot warning: "unused variable 'ofs'"
- Last version was using `strncmp(... tmp->len)` which was causing
  xfstests regressions. It should be `strncmp(... len)`.
- Use c_len for tree operation: (cmp < 0 || len < tmp->c_len)
- Remove needless kfree(cf_name)
- Fix mounting layers without casefold enabled in ovl_dentry_weird()
v5: https://lore.kernel.org/r/20250814-tonyk-overlayfs-v5-0-c5b80a909cbd@igalia.com

Changes in v5:
- Reordered commits. libfs commits come earlier in the series
- First ovl commit just prepare and create ofs->casefold. The proper
  enablement is done in the last commit
- Rework ovl_casefold() consumer/free buffer logic out to the caller
- Replace `const char *aux` with `const char *c_name`
- Add pr_warn_ratelimited() for ovl_create_real() error
- Replace "filesystems" with "layers" in the commit messages
- Add "Testing" section to cover letter
v4: https://lore.kernel.org/r/20250813-tonyk-overlayfs-v4-0-357ccf2e12ad@igalia.com

Changes in v4:
- Split patch "ovl: Support case-insensitive lookup" and move patch that
  creates ofs->casefold to the begging of the series
- Merge patch "Store casefold name..." and "Create ovl_casefold()..."
- Make encoding restrictions apply just when casefold is enabled
- Rework set_d_op() with new helper
- Set encoding and encoding flags inside of ovl_get_layers()
- Rework how inode flags are set and checked
v3: https://lore.kernel.org/r/20250808-tonyk-overlayfs-v3-0-30f9be426ba8@igalia.com

Changes in v3:
- Rebased on top of vfs-6.18.misc branch
- Added more guards for casefolding things inside of IS_ENABLED(UNICODE)
- Refactor the strncmp() patch to do a single kmalloc() per rb_tree operation
- Instead of casefolding the cache entry name everytime per strncmp(),
  casefold it once and reuse it for every strncmp().
- Created ovl_dentry_ci_operations to not override dentry ops set by
  ovl_dentry_operations
- Instead of setting encoding just when there's a upper layer, set it
  for any first layer (ofs->fs[0].sb), regardless of it being upper or
  not.
- Rewrote the patch that set inode flags
- Check if every dentry is consistent with the root dentry regarding
  casefold
v2: https://lore.kernel.org/r/20250805-tonyk-overlayfs-v2-0-0e54281da318@igalia.com

Changes in v2:
- Almost a full rewritten from the v1.
v1: https://lore.kernel.org/lkml/20250409-tonyk-overlayfs-v1-0-3991616fe9a3@igalia.com/

---
André Almeida (9):
      fs: Create sb_encoding() helper
      fs: Create sb_same_encoding() helper
      ovl: Prepare for mounting case-insensitive enabled layers
      ovl: Create ovl_casefold() to support casefolded strncmp()
      ovl: Ensure that all layers have the same encoding
      ovl: Set case-insensitive dentry operations for ovl sb
      ovl: Add S_CASEFOLD as part of the inode flag to be copied
      ovl: Check for casefold consistency when creating new dentries
      ovl: Support mounting case-insensitive enabled layers

 fs/overlayfs/copy_up.c   |   2 +-
 fs/overlayfs/dir.c       |   7 +++
 fs/overlayfs/inode.c     |   1 +
 fs/overlayfs/namei.c     |  17 +++----
 fs/overlayfs/overlayfs.h |   8 ++--
 fs/overlayfs/ovl_entry.h |   1 +
 fs/overlayfs/params.c    |  15 +++++--
 fs/overlayfs/params.h    |   1 +
 fs/overlayfs/readdir.c   | 113 +++++++++++++++++++++++++++++++++++++++--------
 fs/overlayfs/super.c     |  51 +++++++++++++++++++++
 fs/overlayfs/util.c      |  10 +++--
 include/linux/fs.h       |  27 ++++++++++-
 12 files changed, 213 insertions(+), 40 deletions(-)
---
base-commit: 3b7f28e441a100531fa9eff20e011a42376ca7d5
change-id: 20250409-tonyk-overlayfs-591f5e4d407a

Best regards,
-- 
André Almeida <andrealmeid@igalia.com>

[syzbot ci] Re: ovl: Enable support for casefold layers
Posted by syzbot ci 1 month, 1 week ago
syzbot ci has tested the following series

[v6] ovl: Enable support for casefold layers
https://lore.kernel.org/all/20250822-tonyk-overlayfs-v6-0-8b6e9e604fa2@igalia.com
* [PATCH v6 1/9] fs: Create sb_encoding() helper
* [PATCH v6 2/9] fs: Create sb_same_encoding() helper
* [PATCH v6 3/9] ovl: Prepare for mounting case-insensitive enabled layers
* [PATCH v6 4/9] ovl: Create ovl_casefold() to support casefolded strncmp()
* [PATCH v6 5/9] ovl: Ensure that all layers have the same encoding
* [PATCH v6 6/9] ovl: Set case-insensitive dentry operations for ovl sb
* [PATCH v6 7/9] ovl: Add S_CASEFOLD as part of the inode flag to be copied
* [PATCH v6 8/9] ovl: Check for casefold consistency when creating new dentries
* [PATCH v6 9/9] ovl: Support mounting case-insensitive enabled layers

and found the following issue:
WARNING in ovl_dentry_weird

Full report is available here:
https://ci.syzbot.org/series/efd002b5-e585-4cf8-86e7-4f24ba2247c7

***

WARNING in ovl_dentry_weird

tree:      torvalds
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/torvalds/linux
base:      068a56e56fa81e42fc5f08dff34fab149bb60a09
arch:      amd64
compiler:  Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7
config:    https://ci.syzbot.org/builds/039eb31b-2b45-4207-b63e-71a25ed89f00/config
C repro:   https://ci.syzbot.org/findings/726ae90b-83b6-49e2-a496-9bfe444dc24f/c_repro
syz repro: https://ci.syzbot.org/findings/726ae90b-83b6-49e2-a496-9bfe444dc24f/syz_repro

EXT4-fs (loop0): 1 orphan inode deleted
EXT4-fs (loop0): mounted filesystem 00000000-0000-0000-0000-000000000000 r/w without journal. Quota mode: none.
------------[ cut here ]------------
WARNING: CPU: 0 PID: 6001 at fs/overlayfs/ovl_entry.h:118 OVL_FS fs/overlayfs/ovl_entry.h:118 [inline]
WARNING: CPU: 0 PID: 6001 at fs/overlayfs/ovl_entry.h:118 ovl_dentry_weird+0x15a/0x1a0 fs/overlayfs/util.c:206
Modules linked in:
CPU: 0 UID: 0 PID: 6001 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:OVL_FS fs/overlayfs/ovl_entry.h:118 [inline]
RIP: 0010:ovl_dentry_weird+0x15a/0x1a0 fs/overlayfs/util.c:206
Code: e8 6b f9 8f fe 83 e5 03 0f 95 c3 31 ff 89 ee e8 9c fd 8f fe 89 d8 5b 41 5c 41 5e 41 5f 5d e9 3d b9 4c 08 cc e8 47 f9 8f fe 90 <0f> 0b 90 e9 08 ff ff ff 44 89 f1 80 e1 07 80 c1 03 38 c1 0f 8c 0b
RSP: 0018:ffffc90002caf9c8 EFLAGS: 00010293
RAX: ffffffff832fb1e9 RBX: ffff888109730000 RCX: ffff888023295640
RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88802b624a48
RBP: dffffc0000000000 R08: 0000000030656c69 R09: 1ffff110048d0ce0
R10: dffffc0000000000 R11: ffffed10048d0ce1 R12: dffffc0000000000
R13: 0000000000000003 R14: ffff88802b624a48 R15: ffff888109730028
FS:  0000555581e17500(0000) GS:ffff8880b861b000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000001000 CR3: 00000000242f4000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 ovl_mount_dir_check fs/overlayfs/params.c:300 [inline]
 ovl_do_parse_layer+0x307/0xbb0 fs/overlayfs/params.c:422
 ovl_parse_layer fs/overlayfs/params.c:448 [inline]
 ovl_parse_param+0xb62/0xee0 fs/overlayfs/params.c:633
 vfs_parse_fs_param+0x1a9/0x420 fs/fs_context.c:146
 vfs_parse_fs_string fs/fs_context.c:188 [inline]
 vfs_parse_monolithic_sep+0x24d/0x310 fs/fs_context.c:230
 do_new_mount+0x273/0x9e0 fs/namespace.c:3804
 do_mount fs/namespace.c:4136 [inline]
 __do_sys_mount fs/namespace.c:4347 [inline]
 __se_sys_mount+0x317/0x410 fs/namespace.c:4324
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0c2558ebe9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd67150878 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5
RAX: ffffffffffffffda RBX: 00007f0c257b5fa0 RCX: 00007f0c2558ebe9
RDX: 0000200000000b80 RSI: 0000200000000100 RDI: 0000000000000000
RBP: 00007f0c25611e19 R08: 0000200000000180 R09: 0000000000000000
R10: 0000000000000008 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f0c257b5fa0 R14: 00007f0c257b5fa0 R15: 0000000000000005
 </TASK>


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.