On Tue, Apr 26, 2022 at 02:01:03PM +0800, Xie Yongji wrote:
The control device has no drvdata. So we will get a NULL NULL pointer dereference when accessing control device's msg_timeout via sysfs:
[ 132.841881][ T3644] BUG: kernel NULL pointer dereference, address: 00000000000000f8 [ 132.850619][ T3644] RIP: 0010:msg_timeout_show (drivers/vdpa/vdpa_user/vduse_dev.c:1271) [ 132.869447][ T3644] dev_attr_show (drivers/base/core.c:2094) [ 132.870215][ T3644] sysfs_kf_seq_show (fs/sysfs/file.c:59) [ 132.871164][ T3644] ? device_remove_bin_file (drivers/base/core.c:2088) [ 132.872082][ T3644] kernfs_seq_show (fs/kernfs/file.c:164) [ 132.872838][ T3644] seq_read_iter (fs/seq_file.c:230) [ 132.873578][ T3644] ? __vmalloc_area_node (mm/vmalloc.c:3041) [ 132.874532][ T3644] kernfs_fop_read_iter (fs/kernfs/file.c:238) [ 132.875513][ T3644] __kernel_read (fs/read_write.c:440 (discriminator 1)) [ 132.876319][ T3644] kernel_read (fs/read_write.c:459) [ 132.877129][ T3644] kernel_read_file (fs/kernel_read_file.c:94) [ 132.877978][ T3644] kernel_read_file_from_fd (include/linux/file.h:45 fs/kernel_read_file.c:186) [ 132.879019][ T3644] __do_sys_finit_module (kernel/module.c:4207) [ 132.879930][ T3644] __ia32_sys_finit_module (kernel/module.c:4189) [ 132.880930][ T3644] do_int80_syscall_32 (arch/x86/entry/common.c:112 arch/x86/entry/common.c:132) [ 132.881847][ T3644] entry_INT80_compat (arch/x86/entry/entry_64_compat.S:419)
To fix it, let's add a NULL check in msg_timeout_show() and msg_timeout_store().
Fixes: c8a6153b6c59 ("vduse: Introduce VDUSE - vDPA Device in Userspace") Reported-by: kernel test robot oliver.sang@intel.com Cc: stable@vger.kernel.org Signed-off-by: Xie Yongji xieyongji@bytedance.com
drivers/vdpa/vdpa_user/vduse_dev.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c index f85d1a08ed87..f1c42f4aabb4 100644 --- a/drivers/vdpa/vdpa_user/vduse_dev.c +++ b/drivers/vdpa/vdpa_user/vduse_dev.c @@ -1268,6 +1268,9 @@ static ssize_t msg_timeout_show(struct device *device, { struct vduse_dev *dev = dev_get_drvdata(device);
- if (!dev)
return -EPERM;
- return sysfs_emit(buf, "%u\n", dev->msg_timeout);
What prevents the pointer from going away right after you checked it if this is something that changes over time?
If this attribute is never going to be valid for this device, just do not create it.
thanks,
greg k-h