[Xenomai] Analogy: subdev list not intitialized if driver private data is NULL

Philippe Gerum rpm at xenomai.org
Fri Apr 11 15:15:08 CEST 2014


On 04/10/2014 10:58 AM, Andreas Glatz wrote:
> Currently my analogy driver for a new DAQ board doesn't need the private
> data struct of the driver, so I set the size to 0:
>
> /* Analogy driver structure */
> static a4l_drv_t a4l_drv_pandadaq = {
>      .owner = THIS_MODULE,
>      .board_name = "analogy_pandadaq",
>      .attach = dev_pandadaq_attach,
>      .detach = dev_pandadaq_detach,
>      .privdata_size = 0,
> };
>
> However, due to a potential bug the kernel crashes with a NULL ptr
> exception after linking analogy0 to my driver.
>
> If I apply this patch to the git head of xenomai-2.6 everything works
> for me:
>
> diff --git a/ksrc/drivers/analogy/device.c b/ksrc/drivers/analogy/device.c
> index b93ae72..c4095a2 100644
> --- a/ksrc/drivers/analogy/device.c
> +++ b/ksrc/drivers/analogy/device.c
> @@ -278,15 +278,14 @@ int a4l_assign_driver(a4l_cxt_t * cxt,
>          a4l_dev_t *dev = a4l_get_dev(cxt);
>
>          dev->driver = drv;
> +
> +       INIT_LIST_HEAD(&dev->subdvsq);
>
>          if (drv->privdata_size == 0)
>                  __a4l_dbg(1, core_dbg,
>                            "a4l_assign_driver: warning! "
>                            "the field priv will not be usable\n");
>          else {
> -
> -               INIT_LIST_HEAD(&dev->subdvsq);
> -
>                  dev->priv = rtdm_malloc(drv->privdata_size);
>                  if (dev->priv == NULL && drv->privdata_size != 0) {
>                          __a4l_err("a4l_assign_driver: "
>
>

Makes sense. This release routine may also attempt to free a NULL 
pointer, which is fortunately caught by the underlying allocator, but is 
definitely invalid. Finally, the open-coded iterator for subdevices 
reinvents a wheel. Could you try this patch adding a few fixups to 
yours? TIA,

diff --git a/ksrc/drivers/analogy/device.c b/ksrc/drivers/analogy/device.c
index b93ae72..60b2977 100644
--- a/ksrc/drivers/analogy/device.c
+++ b/ksrc/drivers/analogy/device.c
@@ -278,17 +278,15 @@ int a4l_assign_driver(a4l_cxt_t * cxt,
  	a4l_dev_t *dev = a4l_get_dev(cxt);

  	dev->driver = drv;
+	INIT_LIST_HEAD(&dev->subdvsq);

  	if (drv->privdata_size == 0)
  		__a4l_dbg(1, core_dbg,
  			  "a4l_assign_driver: warning! "
  			  "the field priv will not be usable\n");
  	else {
-
-		INIT_LIST_HEAD(&dev->subdvsq);
-
  		dev->priv = rtdm_malloc(drv->privdata_size);
-		if (dev->priv == NULL && drv->privdata_size != 0) {
+		if (dev->priv == NULL) {
  			__a4l_err("a4l_assign_driver: "
  				  "call(alloc) failed\n");
  			ret = -ENOMEM;
@@ -325,27 +323,26 @@ out_assign_driver:

  int a4l_release_driver(a4l_cxt_t * cxt)
  {
-	int ret = 0;
  	a4l_dev_t *dev = a4l_get_dev(cxt);
+	a4l_subd_t *subd, *tmp;
+	int ret = 0;

  	if ((ret = dev->driver->detach(dev)) != 0)
  		goto out_release_driver;

-	/* Decrease module's count
-	   so as to allow module unloading */
  	module_put(dev->driver->owner);

  	/* In case, the driver developer did not free the subdevices */
-	while (&dev->subdvsq != dev->subdvsq.next) {
-		struct list_head *this = dev->subdvsq.next;
-		a4l_subd_t *tmp = list_entry(this, a4l_subd_t, list);
-
-		list_del(this);
-		rtdm_free(tmp);
-	}
+	if (!list_empty(&dev->subdvsq))
+		list_for_each_entry_safe(subd, tmp, &dev->subdvsq, list) {
+			list_del(&subd->list);
+			rtdm_free(subd);
+		}

  	/* Free the private field */
-	rtdm_free(dev->priv);
+	if (dev->priv)
+		rtdm_free(dev->priv);
+
  	dev->driver = NULL;

  out_release_driver:

-- 
Philippe.




More information about the Xenomai mailing list