summaryrefslogtreecommitdiff
path: root/fs/debugfs/file.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2023-11-24 19:25:24 +0300
committerJohannes Berg <johannes.berg@intel.com>2023-11-27 13:24:45 +0300
commit0ed04a1847a10297595ac24dc7d46b35fb35f90a (patch)
tree4aecc9d5e6d1aafa25a04cdeac454adb080459b5 /fs/debugfs/file.c
parent00f7d153f3358a7c7e35aef66fcd9ceb95d90430 (diff)
downloadlinux-0ed04a1847a10297595ac24dc7d46b35fb35f90a.tar.xz
debugfs: fix automount d_fsdata usage
debugfs_create_automount() stores a function pointer in d_fsdata, but since commit 7c8d469877b1 ("debugfs: add support for more elaborate ->d_fsdata") debugfs_release_dentry() will free it, now conditionally on DEBUGFS_FSDATA_IS_REAL_FOPS_BIT, but that's not set for the function pointer in automount. As a result, removing an automount dentry would attempt to free the function pointer. Luckily, the only user of this (tracing) never removes it. Nevertheless, it's safer if we just handle the fsdata in one way, namely either DEBUGFS_FSDATA_IS_REAL_FOPS_BIT or allocated. Thus, change the automount to allocate it, and use the real_fops in the data to indicate whether or not automount is filled, rather than adding a type tag. At least for now this isn't actually needed, but the next changes will require it. Also check in debugfs_file_get() that it gets only called on regular files, just to make things clearer. Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'fs/debugfs/file.c')
-rw-r--r--fs/debugfs/file.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 87b3753aa4b1..e00189aebbf4 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -84,6 +84,14 @@ int debugfs_file_get(struct dentry *dentry)
struct debugfs_fsdata *fsd;
void *d_fsd;
+ /*
+ * This could only happen if some debugfs user erroneously calls
+ * debugfs_file_get() on a dentry that isn't even a file, let
+ * them know about it.
+ */
+ if (WARN_ON(!d_is_reg(dentry)))
+ return -EINVAL;
+
d_fsd = READ_ONCE(dentry->d_fsdata);
if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
fsd = d_fsd;