From 0f5cab99d22585d9a5958c07f5d7e3870bef93ef Mon Sep 17 00:00:00 2001 From: Parav Pandit Date: Thu, 21 Feb 2019 15:54:03 +0800 Subject: [PATCH] IB/umad: Avoid destroying device while it is accessed mainline inclusion from mainline-5.0-rc1 commit cf7ad3030271c55a7119a8c2162563e3f6e93879 category: bugfix bugzilla: 6512 CVE: NA -------------------------- Since Virtual Lanes BCT credits and MTU are set through separate MADs, we ib_umad_reg_agent2() and ib_umad_reg_agent() access the device name in dev_notice(), while concurrently, ib_umad_kill_port() can destroy the device using device_destroy(). cpu-0 cpu-1 ----- ----- ib_umad_ioctl() [...] ib_umad_kill_port() device_destroy(dev) ib_umad_reg_agent() dev_notice(dev) Therefore, first mark ib_dev as NULL, to block any further access in file ops, unregister the mad agent and destroy the device at the end after mutex is unlocked. This ensures that device doesn't get destroyed, while it may get accessed. Conflicts: drivers/infiniband/core/user_mad.c [jingxiangfeng: '900d07c IB/umad: Simplify and avoid dynamic allocation of class' has not been backported.so I have changed "&umad_class" to "umad_class".] Fixes: 0f29b46d49b0 ("IB/mad: add new ioctl to ABI to support new registration options") Signed-off-by: Parav Pandit Reviewed-by: Jack Morgenstein Reviewed-by: Ira Weiny Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe Signed-off-by: Jing Xiangfeng Reviewed-by: Hanjun Guo Signed-off-by: Yang Yingliang --- drivers/infiniband/core/user_mad.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index c34a6852d691..8289a4bb77dc 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -1237,19 +1237,13 @@ static void ib_umad_kill_port(struct ib_umad_port *port) struct ib_umad_file *file; int id; - dev_set_drvdata(port->dev, NULL); - dev_set_drvdata(port->sm_dev, NULL); - - device_destroy(umad_class, port->cdev.dev); - device_destroy(umad_class, port->sm_cdev.dev); - - cdev_del(&port->cdev); - cdev_del(&port->sm_cdev); - mutex_lock(&port->file_mutex); port->ib_dev = NULL; + /* Mark ib_dev NULL and block ioctl or other file ops to progress + * further. + */ list_for_each_entry(file, &port->file_list, port_list) { mutex_lock(&file->mutex); file->agents_dead = 1; @@ -1261,6 +1255,16 @@ static void ib_umad_kill_port(struct ib_umad_port *port) } mutex_unlock(&port->file_mutex); + + dev_set_drvdata(port->dev, NULL); + dev_set_drvdata(port->sm_dev, NULL); + + device_destroy(umad_class, port->cdev.dev); + device_destroy(umad_class, port->sm_cdev.dev); + + cdev_del(&port->cdev); + cdev_del(&port->sm_cdev); + clear_bit(port->dev_num, dev_map); } -- GitLab