Skip to content

smb: client: fix (remove) drop_dir_cache module parameter#178

Open
smfrench wants to merge 1 commit into
code-reviewfrom
enzo-proc-opendirs
Open

smb: client: fix (remove) drop_dir_cache module parameter#178
smfrench wants to merge 1 commit into
code-reviewfrom
enzo-proc-opendirs

Conversation

@smfrench

Copy link
Copy Markdown
Owner

Being a module parameter, it's possible to do:

modprobe cifs drop_dir_cache=1

Which will lead to a crash, because cifs_tcp_ses_list hasn't been initialized yet:

[ 168.242624] BUG: kernel NULL pointer dereference, address: 0000000000000010
[ 168.242952] #PF: supervisor read access in kernel mode
[ 168.243175] #PF: error_code(0x0000) - not-present page
[ 168.243394] PGD 0 P4D 0
[ 168.243524] Oops: Oops: 0000 [#1] SMP NOPTI
[ 168.243703] CPU: 2 UID: 0 PID: 1105 Comm: modprobe Not tainted 7.0.0-lku #5 PREEMPT(lazy)
[ 168.244054] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-2-g4f253b9b-prebuilt.qemu.org 04/01/2014
[ 168.244557] RIP: 0010:cifs_param_set_drop_dir_cache+0x7c/0x100 [cifs]
...
[ 168.248785] Call Trace:
[ 168.248915]
[ 168.249023] parse_args+0x285/0x3a0
[ 168.249204] ? __pfx_unknown_module_param_cb+0x10/0x10
[ 168.249448] load_module+0x192b/0x1bb0
[ 168.249637] ? __pfx_unknown_module_param_cb+0x10/0x10
[ 168.249882] ? kernel_read_file+0x27d/0x2b0
[ 168.250088] init_module_from_file+0xce/0xf0
[ 168.250291] idempotent_init_module+0xfb/0x2f0
[ 168.250496] __x64_sys_finit_module+0x5a/0xa0
[ 168.250694] do_syscall_64+0xe0/0x5a0
[ 168.250863] ? exc_page_fault+0x65/0x160
[ 168.251050] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 168.251284] RIP: 0033:0x7fcaa12b774d

Instead of fixing this with some kind of "is module initialized" approach, this patch instead moves that functionality to procfs, setting a write op for the existing open_dirs entry, where writing a 0 to it will drop the cached directory entries.

Also make it available only when CONFIG_CIFS_DEBUG=y.

A small change needed now is to not call flush_delayed_work() on invalidate_all_cached_dirs() when called from procfs (can't sleep in that context).
So add a @sync arg to invalidate_all_cached_dirs() to control when to flush the delayed works.

Fixes: dde6667 ("smb: client: add drop_dir_cache module parameter to invalidate cached dirents")

Being a module parameter, it's possible to do:

  # modprobe cifs drop_dir_cache=1

Which will lead to a crash, because cifs_tcp_ses_list hasn't been
initialized yet:

  [  168.242624] BUG: kernel NULL pointer dereference, address: 0000000000000010
  [  168.242952] #PF: supervisor read access in kernel mode
  [  168.243175] #PF: error_code(0x0000) - not-present page
  [  168.243394] PGD 0 P4D 0
  [  168.243524] Oops: Oops: 0000 [#1] SMP NOPTI
  [  168.243703] CPU: 2 UID: 0 PID: 1105 Comm: modprobe Not tainted 7.0.0-lku #5 PREEMPT(lazy)
  [  168.244054] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-2-g4f253b9b-prebuilt.qemu.org 04/01/2014
  [  168.244557] RIP: 0010:cifs_param_set_drop_dir_cache+0x7c/0x100 [cifs]
  ...
  [  168.248785] Call Trace:
  [  168.248915]  <TASK>
  [  168.249023]  parse_args+0x285/0x3a0
  [  168.249204]  ? __pfx_unknown_module_param_cb+0x10/0x10
  [  168.249448]  load_module+0x192b/0x1bb0
  [  168.249637]  ? __pfx_unknown_module_param_cb+0x10/0x10
  [  168.249882]  ? kernel_read_file+0x27d/0x2b0
  [  168.250088]  init_module_from_file+0xce/0xf0
  [  168.250291]  idempotent_init_module+0xfb/0x2f0
  [  168.250496]  __x64_sys_finit_module+0x5a/0xa0
  [  168.250694]  do_syscall_64+0xe0/0x5a0
  [  168.250863]  ? exc_page_fault+0x65/0x160
  [  168.251050]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
  [  168.251284] RIP: 0033:0x7fcaa12b774d

Instead of fixing this with some kind of "is module initialized"
approach, this patch instead moves that functionality to procfs,
setting a write op for the existing open_dirs entry, where
writing a 0 to it will drop the cached directory entries.

Also make it available only when CONFIG_CIFS_DEBUG=y.

A small change needed now is to not call flush_delayed_work()
on invalidate_all_cached_dirs() when called from procfs (can't sleep in
that context).
So add a @sync arg to invalidate_all_cached_dirs() to control when to
flush the delayed works.

Fixes: dde6667 ("smb: client: add drop_dir_cache module parameter to invalidate cached dirents")
Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes the drop_dir_cache CIFS module parameter (which can be invoked during modprobe before global CIFS lists are initialized, causing a crash) and replaces the functionality with a procfs-triggered cache drop via /proc/fs/cifs/open_dirs (debug-only), plus a small API tweak to avoid sleeping in that path.

Changes:

  • Remove the drop_dir_cache module parameter and its traversal of cifs_tcp_ses_list.
  • Add an optional write handler for /proc/fs/cifs/open_dirs to trigger dropping cached directory entries (debug builds).
  • Extend invalidate_all_cached_dirs() with a sync flag to avoid flush_delayed_work() in the procfs-triggered path, and update call sites accordingly.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
fs/smb/client/smb2pdu.c Updates invalidate_all_cached_dirs() call to pass sync=true.
fs/smb/client/file.c Updates invalidate_all_cached_dirs() call to pass sync=true.
fs/smb/client/cifsfs.c Removes the drop_dir_cache module parameter implementation.
fs/smb/client/cifs_debug.c Adds procfs write support for open_dirs to drop cached dir entries (debug-only), and updates proc creation.
fs/smb/client/cached_dir.h Updates invalidate_all_cached_dirs() prototype to include bool sync.
fs/smb/client/cached_dir.c Adds sync parameter and conditionally flushes delayed work.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +309 to +311
#ifdef CONFIG_CIFS_DEBUG
seq_puts(m, "# Write 0 to this file to drop all cached directory entries\n");
#endif /* CONFIG_CIFS_DEBUG */

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cifs_debug_dirs_proc_show() prints "Write 0 to this file to drop..." under CONFIG_CIFS_DEBUG, but in the current diff the proc entry is only made writable under CONFIG_CIFS_DEBUG2 (and otherwise is created read-only). This makes the header misleading in the common CIFS_DEBUG=y, CIFS_DEBUG2=n configuration. Please gate this line on the same condition that actually enables .proc_write (or make the proc entry writable under CONFIG_CIFS_DEBUG as intended).

Suggested change
#ifdef CONFIG_CIFS_DEBUG
seq_puts(m, "# Write 0 to this file to drop all cached directory entries\n");
#endif /* CONFIG_CIFS_DEBUG */
#ifdef CONFIG_CIFS_DEBUG2
seq_puts(m, "# Write 0 to this file to drop all cached directory entries\n");
#endif /* CONFIG_CIFS_DEBUG2 */

Copilot uses AI. Check for mistakes.
Comment on lines +936 to +940
#ifdef CONFIG_CIFS_DEBUG2
proc_create("open_dirs", 0644, proc_fs_cifs, &cifs_debug_dirs_proc_ops);
#else /* CONFIG_CIFS_DEBUG2 */
proc_create_single("open_dirs", 0400, proc_fs_cifs, cifs_debug_dirs_proc_show);
#endif /* !CONFIG_CIFS_DEBUG2 */

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cifs_proc_init() creates /proc/fs/cifs/open_dirs with the writable proc_ops only under CONFIG_CIFS_DEBUG2, but the new write/drop-cache functionality is described as being available when CONFIG_CIFS_DEBUG=y. With CIFS_DEBUG=y and CIFS_DEBUG2=n, the file remains proc_create_single(..., 0400, ...) (read-only) even though cifs_debug_dirs_proc_show() advertises that writing 0 will drop caches. Please align the Kconfig guard(s) so the writable version is created whenever the feature is compiled in (likely CONFIG_CIFS_DEBUG).

Suggested change
#ifdef CONFIG_CIFS_DEBUG2
proc_create("open_dirs", 0644, proc_fs_cifs, &cifs_debug_dirs_proc_ops);
#else /* CONFIG_CIFS_DEBUG2 */
proc_create_single("open_dirs", 0400, proc_fs_cifs, cifs_debug_dirs_proc_show);
#endif /* !CONFIG_CIFS_DEBUG2 */
#ifdef CONFIG_CIFS_DEBUG
proc_create("open_dirs", 0644, proc_fs_cifs, &cifs_debug_dirs_proc_ops);
#else /* CONFIG_CIFS_DEBUG */
proc_create_single("open_dirs", 0400, proc_fs_cifs, cifs_debug_dirs_proc_show);
#endif /* !CONFIG_CIFS_DEBUG */

Copilot uses AI. Check for mistakes.
cifs_debug_dirs_proc_show);

#ifdef CONFIG_CIFS_DEBUG2
proc_create("open_dirs", 0644, proc_fs_cifs, &cifs_debug_dirs_proc_ops);

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/proc/fs/cifs/open_dirs switches from 0400 to 0644 in the CONFIG_CIFS_DEBUG2 branch. This makes the cached directory paths and related identifiers world-readable, which is a behavior change compared to open_files (still 0400) and the prior open_dirs permissions. If the intent is to allow cache dropping via writes, consider using a root-only mode (e.g. 0600) so adding a write capability doesn't also broaden read access.

Suggested change
proc_create("open_dirs", 0644, proc_fs_cifs, &cifs_debug_dirs_proc_ops);
proc_create("open_dirs", 0600, proc_fs_cifs, &cifs_debug_dirs_proc_ops);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants