* [PATCH 0/3] debugfs: fixes to "file removal race" series
@ 2016-05-24 11:08 Nicolai Stange
2016-05-24 11:08 ` [PATCH 1/3] debugfs: remove extra debugfs_create_file_unsafe() declaration Nicolai Stange
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Nicolai Stange @ 2016-05-24 11:08 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Nicolai Stange
Hi Greg,
the recent report by Sasha Levin made me review my debugfs
"file removal race" series again.
For your reference, the original series in question was posted here:
http://lkml.kernel.org/g/1458652280-19785-1-git-send-email-nicstange@gmail.com
It has been merged through your driver-core tree into mainline.
Unfortunately, I found three issues:
The first one is a minor code style issue.
The second one is more serious: on ->open() failure, references to modules
as well as memory are leaked.
The third one is a potential leak of module references with future debugfs
users.
The patches don't depend on each other and are unrelated except that they
all address issues introduced by the same series.
I tested them with linux-next 20160523.
Apologies and thanks,
Nicolai
Nicolai Stange (3):
debugfs: remove extra debugfs_create_file_unsafe() declaration
debugfs: full_proxy_open(): free proxy on ->open() failure
debugfs: open_proxy_open(): avoid double fops release
fs/debugfs/file.c | 7 ++++---
fs/debugfs/internal.h | 4 ----
2 files changed, 4 insertions(+), 7 deletions(-)
--
2.8.2
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/3] debugfs: remove extra debugfs_create_file_unsafe() declaration
2016-05-24 11:08 [PATCH 0/3] debugfs: fixes to "file removal race" series Nicolai Stange
@ 2016-05-24 11:08 ` Nicolai Stange
2016-05-24 11:08 ` [PATCH 2/3] debugfs: full_proxy_open(): free proxy on ->open() failure Nicolai Stange
2016-05-24 11:08 ` [PATCH 3/3] debugfs: open_proxy_open(): avoid double fops release Nicolai Stange
2 siblings, 0 replies; 4+ messages in thread
From: Nicolai Stange @ 2016-05-24 11:08 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Nicolai Stange
debugfs_create_file_unsafe() is declared twice in exactly the same
manner each: once in fs/debugfs/internal.h and once in
include/linux/debugfs.h
All files that include the former also include the latter and thus,
the declaration in fs/debugfs/internal.h is superfluous.
Remove it.
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
---
fs/debugfs/internal.h | 4 ----
1 file changed, 4 deletions(-)
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index bba5263..b3e8443 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -19,8 +19,4 @@ extern const struct file_operations debugfs_noop_file_operations;
extern const struct file_operations debugfs_open_proxy_file_operations;
extern const struct file_operations debugfs_full_proxy_file_operations;
-struct dentry *debugfs_create_file_unsafe(const char *name, umode_t mode,
- struct dentry *parent, void *data,
- const struct file_operations *fops);
-
#endif /* _DEBUGFS_INTERNAL_H_ */
--
2.8.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/3] debugfs: full_proxy_open(): free proxy on ->open() failure
2016-05-24 11:08 [PATCH 0/3] debugfs: fixes to "file removal race" series Nicolai Stange
2016-05-24 11:08 ` [PATCH 1/3] debugfs: remove extra debugfs_create_file_unsafe() declaration Nicolai Stange
@ 2016-05-24 11:08 ` Nicolai Stange
2016-05-24 11:08 ` [PATCH 3/3] debugfs: open_proxy_open(): avoid double fops release Nicolai Stange
2 siblings, 0 replies; 4+ messages in thread
From: Nicolai Stange @ 2016-05-24 11:08 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Nicolai Stange
Debugfs' full_proxy_open(), the ->open() installed at all inodes created
through debugfs_create_file(),
- grabs a reference to the original struct file_operations instance passed
to debugfs_create_file(),
- dynamically allocates a proxy struct file_operations instance wrapping
the original
- and installs this at the file's ->f_op.
Afterwards, it calls the original ->open() and passes its return value back
to the VFS layer.
Now, if that return value indicates failure, the VFS layer won't ever call
->release() and thus, neither the reference to the original file_operations
nor the memory for the proxy file_operations will get released, i.e. both
are leaked.
Upon failure of the original fops' ->open(), undo the proxy installation.
That is:
- Set the struct file ->f_op to what it had been when full_proxy_open()
was entered.
- Drop the reference to the original file_operations.
- Free the memory holding the proxy file_operations.
Fixes: 49d200deaa68 ("debugfs: prevent access to removed files' private
data")
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
---
fs/debugfs/file.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 9c1c9a0..d1ec803 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -262,8 +262,10 @@ static int full_proxy_open(struct inode *inode, struct file *filp)
if (real_fops->open) {
r = real_fops->open(inode, filp);
-
- if (filp->f_op != proxy_fops) {
+ if (r) {
+ replace_fops(filp, d_inode(dentry)->i_fop);
+ goto free_proxy;
+ } else if (filp->f_op != proxy_fops) {
/* No protection against file removal anymore. */
WARN(1, "debugfs file owner replaced proxy fops: %pd",
dentry);
--
2.8.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 3/3] debugfs: open_proxy_open(): avoid double fops release
2016-05-24 11:08 [PATCH 0/3] debugfs: fixes to "file removal race" series Nicolai Stange
2016-05-24 11:08 ` [PATCH 1/3] debugfs: remove extra debugfs_create_file_unsafe() declaration Nicolai Stange
2016-05-24 11:08 ` [PATCH 2/3] debugfs: full_proxy_open(): free proxy on ->open() failure Nicolai Stange
@ 2016-05-24 11:08 ` Nicolai Stange
2 siblings, 0 replies; 4+ messages in thread
From: Nicolai Stange @ 2016-05-24 11:08 UTC (permalink / raw)
To: Greg Kroah-Hartman; +Cc: linux-kernel, Nicolai Stange
Debugfs' open_proxy_open(), the ->open() installed at all inodes created
through debugfs_create_file_unsafe(),
- grabs a reference to the original file_operations instance passed to
debugfs_create_file_unsafe() via fops_get(),
- installs it at the file's ->f_op by means of replace_fops()
- and calls fops_put() on it.
Since the semantics of replace_fops() are such that the reference's
ownership is transferred, the subsequent fops_put() will result in a double
release when the file is eventually closed.
Currently, this is not an issue since fops_put() basically does a
module_put() on the file_operations' ->owner only and there don't exist any
modules calling debugfs_create_file_unsafe() yet. This is expected to
change in the future though, c.f. commit c64688081490 ("debugfs: add
support for self-protecting attribute file fops").
Remove the call to fops_put() from open_proxy_open().
Fixes: 9fd4dcece43a ("debugfs: prevent access to possibly dead
file_operations at file open")
Signed-off-by: Nicolai Stange <nicstange@gmail.com>
---
fs/debugfs/file.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index d1ec803..592059f 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -127,7 +127,6 @@ static int open_proxy_open(struct inode *inode, struct file *filp)
r = real_fops->open(inode, filp);
out:
- fops_put(real_fops);
debugfs_use_file_finish(srcu_idx);
return r;
}
--
2.8.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2016-05-24 11:09 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-24 11:08 [PATCH 0/3] debugfs: fixes to "file removal race" series Nicolai Stange
2016-05-24 11:08 ` [PATCH 1/3] debugfs: remove extra debugfs_create_file_unsafe() declaration Nicolai Stange
2016-05-24 11:08 ` [PATCH 2/3] debugfs: full_proxy_open(): free proxy on ->open() failure Nicolai Stange
2016-05-24 11:08 ` [PATCH 3/3] debugfs: open_proxy_open(): avoid double fops release Nicolai Stange
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox