All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev
@ 2020-09-22  7:25 Jing Xiangfeng
  2020-09-22  8:04 ` Dan Carpenter
  0 siblings, 1 reply; 4+ messages in thread
From: Jing Xiangfeng @ 2020-09-22  7:25 UTC (permalink / raw)
  To: mporter, alex.bou9, akpm, gustavoars, jhubbard, keescook,
	madhuparnabhowmik10, dan.carpenter
  Cc: linux-kernel, jingxiangfeng

rio_mport_add_riodev() misses to call put_device() when the device
already exists. Add the missed function call to fix it.

Fixes: e8de370188d0 ("rapidio: add mport char device driver")
Signed-off-by: Jing Xiangfeng <jingxiangfeng@huawei.com>
---
 drivers/rapidio/devices/rio_mport_cdev.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c
index a30342942e26..829fe2b7c437 100644
--- a/drivers/rapidio/devices/rio_mport_cdev.c
+++ b/drivers/rapidio/devices/rio_mport_cdev.c
@@ -1679,6 +1679,7 @@ static int rio_mport_add_riodev(struct mport_cdev_priv *priv,
 	struct rio_dev *rdev;
 	struct rio_switch *rswitch = NULL;
 	struct rio_mport *mport;
+	struct device *dev;
 	size_t size;
 	u32 rval;
 	u32 swpinfo = 0;
@@ -1693,8 +1694,10 @@ static int rio_mport_add_riodev(struct mport_cdev_priv *priv,
 	rmcd_debug(RDEV, "name:%s ct:0x%x did:0x%x hc:0x%x", dev_info.name,
 		   dev_info.comptag, dev_info.destid, dev_info.hopcount);
 
-	if (bus_find_device_by_name(&rio_bus_type, NULL, dev_info.name)) {
+	dev = bus_find_device_by_name(&rio_bus_type, NULL, dev_info.name);
+	if (dev) {
 		rmcd_debug(RDEV, "device %s already exists", dev_info.name);
+		put_device(dev);
 		return -EEXIST;
 	}
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev
  2020-09-22  7:25 [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev Jing Xiangfeng
@ 2020-09-22  8:04 ` Dan Carpenter
  2020-09-22  9:19   ` Jing Xiangfeng
  0 siblings, 1 reply; 4+ messages in thread
From: Dan Carpenter @ 2020-09-22  8:04 UTC (permalink / raw)
  To: Jing Xiangfeng
  Cc: mporter, alex.bou9, akpm, gustavoars, jhubbard, keescook,
	madhuparnabhowmik10, linux-kernel

On Tue, Sep 22, 2020 at 03:25:25PM +0800, Jing Xiangfeng wrote:
> rio_mport_add_riodev() misses to call put_device() when the device
> already exists. Add the missed function call to fix it.
> 

Looks good.

Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>

I notice that rio_mport_del_riodev() has a related bug.

  1802          err = rio_add_device(rdev);
  1803          if (err)
  1804                  goto cleanup;
  1805          rio_dev_get(rdev);
                ^^^^^^^^^^^^^^^^^
This calls get_device(&rdev->dev);

  1806  
  1807          return 0;
  1808  cleanup:
  1809          kfree(rdev);
  1810          return err;
  1811  }
  1812  
  1813  static int rio_mport_del_riodev(struct mport_cdev_priv *priv, void __user *arg)
  1814  {
  1815          struct rio_rdev_info dev_info;
  1816          struct rio_dev *rdev = NULL;
  1817          struct device  *dev;
  1818          struct rio_mport *mport;
  1819          struct rio_net *net;
  1820  
  1821          if (copy_from_user(&dev_info, arg, sizeof(dev_info)))
  1822                  return -EFAULT;
  1823          dev_info.name[sizeof(dev_info.name) - 1] = '\0';
  1824  
  1825          mport = priv->md->mport;
  1826  
  1827          /* If device name is specified, removal by name has priority */
  1828          if (strlen(dev_info.name)) {
  1829                  dev = bus_find_device_by_name(&rio_bus_type, NULL,
  1830                                                dev_info.name);
  1831                  if (dev)
  1832                          rdev = to_rio_dev(dev);

This path takes a second get_device(&rdev->dev);

  1833          } else {
  1834                  do {
  1835                          rdev = rio_get_comptag(dev_info.comptag, rdev);
  1836                          if (rdev && rdev->dev.parent == &mport->net->dev &&
  1837                              rdev->destid == dev_info.destid &&
  1838                              rdev->hopcount == dev_info.hopcount)
  1839                                  break;

This path does not call get_device().

  1840                  } while (rdev);
  1841          }
  1842  
  1843          if (!rdev) {
  1844                  rmcd_debug(RDEV,
  1845                          "device name:%s ct:0x%x did:0x%x hc:0x%x not found",
  1846                          dev_info.name, dev_info.comptag, dev_info.destid,
  1847                          dev_info.hopcount);
  1848                  return -ENODEV;
  1849          }
  1850  
  1851          net = rdev->net;
  1852          rio_dev_put(rdev);

This drops a reference.

  1853          rio_del_device(rdev, RIO_DEVICE_SHUTDOWN);

This drops a second reference.  So presumably deleting by component tag
will lead to a use after free.

  1854  
  1855          if (list_empty(&net->devices)) {
  1856                  rio_free_net(net);
  1857                  mport->net = NULL;
  1858          }
  1859  
  1860          return 0;
  1861  }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev
  2020-09-22  8:04 ` Dan Carpenter
@ 2020-09-22  9:19   ` Jing Xiangfeng
  2020-09-22  9:52     ` Dan Carpenter
  0 siblings, 1 reply; 4+ messages in thread
From: Jing Xiangfeng @ 2020-09-22  9:19 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: mporter, alex.bou9, akpm, gustavoars, jhubbard, keescook,
	madhuparnabhowmik10, linux-kernel



On 2020/9/22 16:04, Dan Carpenter wrote:
> On Tue, Sep 22, 2020 at 03:25:25PM +0800, Jing Xiangfeng wrote:
>> rio_mport_add_riodev() misses to call put_device() when the device
>> already exists. Add the missed function call to fix it.
>>
> Looks good.
>
> Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
>
> I notice that rio_mport_del_riodev() has a related bug.
>
>    1802          err = rio_add_device(rdev);
>    1803          if (err)
>    1804                  goto cleanup;
>    1805          rio_dev_get(rdev);
>                  ^^^^^^^^^^^^^^^^^
> This calls get_device(&rdev->dev);
>
>    1806
>    1807          return 0;
>    1808  cleanup:
>    1809          kfree(rdev);
>    1810          return err;
>    1811  }
>    1812
>    1813  static int rio_mport_del_riodev(struct mport_cdev_priv *priv, void __user *arg)
>    1814  {
>    1815          struct rio_rdev_info dev_info;
>    1816          struct rio_dev *rdev = NULL;
>    1817          struct device  *dev;
>    1818          struct rio_mport *mport;
>    1819          struct rio_net *net;
>    1820
>    1821          if (copy_from_user(&dev_info, arg, sizeof(dev_info)))
>    1822                  return -EFAULT;
>    1823          dev_info.name[sizeof(dev_info.name) - 1] = '\0';
>    1824
>    1825          mport = priv->md->mport;
>    1826
>    1827          /* If device name is specified, removal by name has priority */
>    1828          if (strlen(dev_info.name)) {
>    1829                  dev = bus_find_device_by_name(&rio_bus_type, NULL,
>    1830                                                dev_info.name);
>    1831                  if (dev)
>    1832                          rdev = to_rio_dev(dev);
>
> This path takes a second get_device(&rdev->dev);
>
>    1833          } else {
>    1834                  do {
>    1835                          rdev = rio_get_comptag(dev_info.comptag, rdev);
>    1836                          if (rdev && rdev->dev.parent == &mport->net->dev &&
>    1837                              rdev->destid == dev_info.destid &&
>    1838                              rdev->hopcount == dev_info.hopcount)
>    1839                                  break;
>
> This path does not call get_device().
  Add  calling rio_dev_get()  in this path? like the following changes:

  static int rio_mport_del_riodev(struct mport_cdev_priv *priv, void 
__user *arg)
                         rdev = rio_get_comptag(dev_info.comptag, rdev);
                         if (rdev && rdev->dev.parent == &mport->net->dev &&
                             rdev->destid == dev_info.destid &&
-                           rdev->hopcount == dev_info.hopcount)
+                           rdev->hopcount == dev_info.hopcount) {
+                               rio_dev_get(rdev);
                                 break;
+                       }
                 } while (rdev);
         }

>
>    1840                  } while (rdev);
>    1841          }
>    1842
>    1843          if (!rdev) {
>    1844                  rmcd_debug(RDEV,
>    1845                          "device name:%s ct:0x%x did:0x%x hc:0x%x not found",
>    1846                          dev_info.name, dev_info.comptag, dev_info.destid,
>    1847                          dev_info.hopcount);
>    1848                  return -ENODEV;
>    1849          }
>    1850
>    1851          net = rdev->net;
>    1852          rio_dev_put(rdev);
>
> This drops a reference.
>
>    1853          rio_del_device(rdev, RIO_DEVICE_SHUTDOWN);
>
> This drops a second reference.  So presumably deleting by component tag
> will lead to a use after free.
Indeed,  it  is a mismatched reference.
>
>    1854
>    1855          if (list_empty(&net->devices)) {
>    1856                  rio_free_net(net);
>    1857                  mport->net = NULL;
>    1858          }
>    1859
>    1860          return 0;
>    1861  }
>
> regards,
> dan carpenter
> .
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev
  2020-09-22  9:19   ` Jing Xiangfeng
@ 2020-09-22  9:52     ` Dan Carpenter
  0 siblings, 0 replies; 4+ messages in thread
From: Dan Carpenter @ 2020-09-22  9:52 UTC (permalink / raw)
  To: Jing Xiangfeng
  Cc: mporter, alex.bou9, akpm, gustavoars, jhubbard, keescook,
	madhuparnabhowmik10, linux-kernel

On Tue, Sep 22, 2020 at 05:19:06PM +0800, Jing Xiangfeng wrote:
> 
> 
> On 2020/9/22 16:04, Dan Carpenter wrote:
> > On Tue, Sep 22, 2020 at 03:25:25PM +0800, Jing Xiangfeng wrote:
> > > rio_mport_add_riodev() misses to call put_device() when the device
> > > already exists. Add the missed function call to fix it.
> > > 
> > Looks good.
> > 
> > Reviewed-by: Dan Carpenter <dan.carpenter@oracle.com>
> > 
> > I notice that rio_mport_del_riodev() has a related bug.
> > 
> >    1802          err = rio_add_device(rdev);
> >    1803          if (err)
> >    1804                  goto cleanup;
> >    1805          rio_dev_get(rdev);
> >                  ^^^^^^^^^^^^^^^^^
> > This calls get_device(&rdev->dev);
> > 
> >    1806
> >    1807          return 0;
> >    1808  cleanup:
> >    1809          kfree(rdev);
> >    1810          return err;
> >    1811  }
> >    1812
> >    1813  static int rio_mport_del_riodev(struct mport_cdev_priv *priv, void __user *arg)
> >    1814  {
> >    1815          struct rio_rdev_info dev_info;
> >    1816          struct rio_dev *rdev = NULL;
> >    1817          struct device  *dev;
> >    1818          struct rio_mport *mport;
> >    1819          struct rio_net *net;
> >    1820
> >    1821          if (copy_from_user(&dev_info, arg, sizeof(dev_info)))
> >    1822                  return -EFAULT;
> >    1823          dev_info.name[sizeof(dev_info.name) - 1] = '\0';
> >    1824
> >    1825          mport = priv->md->mport;
> >    1826
> >    1827          /* If device name is specified, removal by name has priority */
> >    1828          if (strlen(dev_info.name)) {
> >    1829                  dev = bus_find_device_by_name(&rio_bus_type, NULL,
> >    1830                                                dev_info.name);
> >    1831                  if (dev)
> >    1832                          rdev = to_rio_dev(dev);
> > 
> > This path takes a second get_device(&rdev->dev);
> > 
> >    1833          } else {
> >    1834                  do {
> >    1835                          rdev = rio_get_comptag(dev_info.comptag, rdev);
> >    1836                          if (rdev && rdev->dev.parent == &mport->net->dev &&
> >    1837                              rdev->destid == dev_info.destid &&
> >    1838                              rdev->hopcount == dev_info.hopcount)
> >    1839                                  break;
> > 
> > This path does not call get_device().
>  Add  calling rio_dev_get()  in this path? like the following changes:
> 
>  static int rio_mport_del_riodev(struct mport_cdev_priv *priv, void __user
> *arg)
>                         rdev = rio_get_comptag(dev_info.comptag, rdev);
>                         if (rdev && rdev->dev.parent == &mport->net->dev &&
>                             rdev->destid == dev_info.destid &&
> -                           rdev->hopcount == dev_info.hopcount)
> +                           rdev->hopcount == dev_info.hopcount) {
> +                               rio_dev_get(rdev);
>                                 break;
> +                       }

To be honest, I'm not sure how the rio_get_comptag() stuff is supposed
to work...  It probably requires some thought and testing.

Anyway, your patch is straight forward enough so let's just merge that
and hope someone with the hardware can take a look at this.

regards,
dan carpenter


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2020-09-22  9:53 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-22  7:25 [PATCH] rapidio: fix the missed put_device() for rio_mport_add_riodev Jing Xiangfeng
2020-09-22  8:04 ` Dan Carpenter
2020-09-22  9:19   ` Jing Xiangfeng
2020-09-22  9:52     ` Dan Carpenter

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.