Omitting the owner field in file_operations declared in modules is an easy mistake to make, and can result in crashes when the module is unloaded while userspace is poking the file. This patch modifies fops_get() to WARN when it encounters a NULL owner, since in this case it cannot take a reference on the containing module. Signed-off-by: Calvin Owens <calvinowens@xxxxxx> --- include/linux/fs.h | 13 ++++++++++++- kernel/module.c | 1 + 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 901e25d..fafda9e 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2081,10 +2081,21 @@ extern struct dentry *mount_pseudo(struct file_system_type *, char *, unsigned long); /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ -#define fops_get(fops) \ +#define __fops_get(fops) \ (((fops) && try_module_get((fops)->owner) ? (fops) : NULL)) #define fops_put(fops) \ do { if (fops) module_put((fops)->owner); } while(0) + +#define unowned_fmt "No fops owner at %p in [%s]\n" +#define fops_unowned(fops) \ + (is_module_address((unsigned long)(fops)) && !(fops)->owner) +#define fops_modname(fops) \ + __module_address((unsigned long)(fops))->name +#define fops_warn_unowned(fops) \ + WARN(fops_unowned(fops), unowned_fmt, (fops), fops_modname(fops)) +#define fops_get(fops) \ + ({ fops_warn_unowned(fops); __fops_get(fops); }) + /* * This one is to be used *ONLY* from ->open() instances. * fops must be non-NULL, pinned down *and* module dependencies diff --git a/kernel/module.c b/kernel/module.c index 529efae..4443727 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -4181,6 +4181,7 @@ bool is_module_address(unsigned long addr) return ret; } +EXPORT_SYMBOL_GPL(is_module_address); /* * __module_address - get the module which contains an address. -- 2.9.3 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html