public inbox for kernel-janitors@vger.kernel.org
 help / color / mirror / Atom feed
* [bug report] drivers/net: support hdlc function for QE-UCC
@ 2016-07-12 23:49 Dan Carpenter
  2016-07-13  2:22 ` Qiang Zhao
  2016-08-03 14:13 ` Dan Carpenter
  0 siblings, 2 replies; 3+ messages in thread
From: Dan Carpenter @ 2016-07-12 23:49 UTC (permalink / raw)
  To: kernel-janitors

Hello Zhao Qiang,

The patch c19b6d246a35: "drivers/net: support hdlc function for
QE-UCC" from Jun 6, 2016, leads to the following static checker
warning:

	drivers/net/wan/fsl_ucc_hdlc.c:1131 ucc_hdlc_probe()
	error: dereferencing freed memory 'uhdlc_priv'

The error handling has quite a few problems.  There is an easy way to
write error handling.  Let me demonstrate.

drivers/net/wan/fsl_ucc_hdlc.c
  1062          ret = of_address_to_resource(np, 0, &res);
  1063          if (ret)
  1064                  return -EINVAL;
  1065  
  1066          ut_info->uf_info.regs = res.start;
  1067          ut_info->uf_info.irq = irq_of_parse_and_map(np, 0);
  1068  
  1069          uhdlc_priv = kzalloc(sizeof(*uhdlc_priv), GFP_KERNEL);
  1070          if (!uhdlc_priv) {
  1071                  ret = -ENOMEM;
  1072                  dev_err(&pdev->dev, "No mem to alloc hdlc private data\n");

No need for this printk().  kzalloc() already prints a warning.

  1073                  goto err_alloc_priv;

This is a do-nothing goto.  Change it to "return -ENOMEM;".

		uhdlc_priv = kzalloc(sizeof(*uhdlc_priv), GFP_KERNEL);
		if (!uhdlc_priv)
			return -ENOMEM;


  1074          }
  1075  
  1076          dev_set_drvdata(&pdev->dev, uhdlc_priv);
  1077          uhdlc_priv->dev = &pdev->dev;
  1078          uhdlc_priv->ut_info = ut_info;
  1079  
  1080          if (of_get_property(np, "fsl,tdm-interface", NULL))
  1081                  uhdlc_priv->tsa = 1;
  1082  
  1083          if (of_get_property(np, "fsl,ucc-internal-loopback", NULL))
  1084                  uhdlc_priv->loopback = 1;
  1085  
  1086          if (uhdlc_priv->tsa = 1) {
  1087                  utdm = kzalloc(sizeof(*utdm), GFP_KERNEL);
  1088                  if (!utdm) {
  1089                          ret = -ENOMEM;
  1090                          dev_err(&pdev->dev, "No mem to alloc ucc tdm data\n");

No need again.

  1091                          goto err_alloc_utdm;

The goto name should say what the goto does.  We need to free uhdlc_priv
so "goto free_uhdlc;" is a good name.

  1092                  }
  1093                  uhdlc_priv->utdm = utdm;
  1094                  ret = ucc_of_parse_tdm(np, utdm, ut_info);
  1095                  if (ret)
  1096                          goto err_miss_tsa_property;

Here we need to free utdm so "goto free_utdm;".

  1097          }
  1098  
  1099          ret = uhdlc_init(uhdlc_priv);
  1100          if (ret) {
  1101                  dev_err(&pdev->dev, "Failed to init uhdlc\n");
  1102                  goto err_hdlc_init;

We're still freeing utdm;   So goto free_utdm;

  1103          }
  1104  
  1105          dev = alloc_hdlcdev(uhdlc_priv);
  1106          if (!dev) {
  1107                  ret = -ENOMEM;
  1108                  pr_err("ucc_hdlc: unable to allocate memory\n");
  1109                  goto err_hdlc_init;

Hm...  Here we need to undo what uhdlc_init() did.  I'm not sure the
function to do that.  Currently we leak resources.

			goto undo_uhdlc_init;

  1110          }
  1111  
  1112          uhdlc_priv->ndev = dev;
  1113          hdlc = dev_to_hdlc(dev);
  1114          dev->tx_queue_len = 16;
  1115          dev->netdev_ops = &uhdlc_ops;
  1116          hdlc->attach = ucc_hdlc_attach;
  1117          hdlc->xmit = ucc_hdlc_tx;
  1118          netif_napi_add(dev, &uhdlc_priv->napi, ucc_hdlc_poll, 32);
  1119          if (register_hdlc_device(dev)) {
  1120                  ret = -ENOBUFS;

Why are we not preserving the error code?

		ret = register_hdlc_device(dev);
		if (ret) {

  1121                  pr_err("ucc_hdlc: unable to register hdlc device\n");

No need for this printk.

  1122                  free_netdev(dev);
  1123                  goto err_hdlc_init;

Instead of freeing and then a goto just do "goto free_dev;".

  1124          }
  1125  
  1126          return 0;
  1127  
  1128  err_hdlc_init:
  1129  err_miss_tsa_property:
  1130          kfree(uhdlc_priv);
  1131          if (uhdlc_priv->tsa)
  1132                  kfree(utdm);
  1133  err_alloc_utdm:
  1134          kfree(uhdlc_priv);
  1135  err_alloc_priv:
  1136          return ret;
  1137  }

You can see the problems.  We free uhdlc_priv then we dereference it,
then we free it a second time.  There is stuff that is missing.  The
labels are bad.  Here is the new version:

free_dev:
	free_netdev(dev);
undo_uhdlc_init:
	/* FIXME: impliment this code */
free_utdm:
	if (uhdlc_priv->tsa)
		kfree(utdm);
free_uhdlc:
	kfree(uhdlc);

	return ret;

Just follow the steps and then error handling is easy to understand.

regards,
dan carpenter

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

* RE: [bug report] drivers/net: support hdlc function for QE-UCC
  2016-07-12 23:49 [bug report] drivers/net: support hdlc function for QE-UCC Dan Carpenter
@ 2016-07-13  2:22 ` Qiang Zhao
  2016-08-03 14:13 ` Dan Carpenter
  1 sibling, 0 replies; 3+ messages in thread
From: Qiang Zhao @ 2016-07-13  2:22 UTC (permalink / raw)
  To: kernel-janitors

Hello Dan Carpenter,

Thank you for your comments, I will send a patch to fix it.

Best Regards
Zhao Qiang

> -----Original Message-----
> From: Dan Carpenter [mailto:dan.carpenter@oracle.com]
> Sent: Wednesday, July 13, 2016 7:49 AM
> To: Qiang Zhao <qiang.zhao@nxp.com>
> Cc: kernel-janitors@vger.kernel.org
> Subject: [bug report] drivers/net: support hdlc function for QE-UCC
> 
> Hello Zhao Qiang,
> 
> The patch c19b6d246a35: "drivers/net: support hdlc function for QE-UCC" from
> Jun 6, 2016, leads to the following static checker
> warning:
> 
> 	drivers/net/wan/fsl_ucc_hdlc.c:1131 ucc_hdlc_probe()
> 	error: dereferencing freed memory 'uhdlc_priv'
> 
> The error handling has quite a few problems.  There is an easy way to write
> error handling.  Let me demonstrate.
> 
> drivers/net/wan/fsl_ucc_hdlc.c
>   1062          ret = of_address_to_resource(np, 0, &res);
>   1063          if (ret)
>   1064                  return -EINVAL;
>   1065
>   1066          ut_info->uf_info.regs = res.start;
>   1067          ut_info->uf_info.irq = irq_of_parse_and_map(np, 0);
>   1068
>   1069          uhdlc_priv = kzalloc(sizeof(*uhdlc_priv), GFP_KERNEL);
>   1070          if (!uhdlc_priv) {
>   1071                  ret = -ENOMEM;
>   1072                  dev_err(&pdev->dev, "No mem to alloc hdlc private data\n");
> 
> No need for this printk().  kzalloc() already prints a warning.
> 
>   1073                  goto err_alloc_priv;
> 
> This is a do-nothing goto.  Change it to "return -ENOMEM;".
> 
> 		uhdlc_priv = kzalloc(sizeof(*uhdlc_priv), GFP_KERNEL);
> 		if (!uhdlc_priv)
> 			return -ENOMEM;
> 
> 
>   1074          }
>   1075
>   1076          dev_set_drvdata(&pdev->dev, uhdlc_priv);
>   1077          uhdlc_priv->dev = &pdev->dev;
>   1078          uhdlc_priv->ut_info = ut_info;
>   1079
>   1080          if (of_get_property(np, "fsl,tdm-interface", NULL))
>   1081                  uhdlc_priv->tsa = 1;
>   1082
>   1083          if (of_get_property(np, "fsl,ucc-internal-loopback", NULL))
>   1084                  uhdlc_priv->loopback = 1;
>   1085
>   1086          if (uhdlc_priv->tsa = 1) {
>   1087                  utdm = kzalloc(sizeof(*utdm), GFP_KERNEL);
>   1088                  if (!utdm) {
>   1089                          ret = -ENOMEM;
>   1090                          dev_err(&pdev->dev, "No mem to alloc ucc tdm data\n");
> 
> No need again.
> 
>   1091                          goto err_alloc_utdm;
> 
> The goto name should say what the goto does.  We need to free uhdlc_priv so
> "goto free_uhdlc;" is a good name.
> 
>   1092                  }
>   1093                  uhdlc_priv->utdm = utdm;
>   1094                  ret = ucc_of_parse_tdm(np, utdm, ut_info);
>   1095                  if (ret)
>   1096                          goto err_miss_tsa_property;
> 
> Here we need to free utdm so "goto free_utdm;".
> 
>   1097          }
>   1098
>   1099          ret = uhdlc_init(uhdlc_priv);
>   1100          if (ret) {
>   1101                  dev_err(&pdev->dev, "Failed to init uhdlc\n");
>   1102                  goto err_hdlc_init;
> 
> We're still freeing utdm;   So goto free_utdm;
> 
>   1103          }
>   1104
>   1105          dev = alloc_hdlcdev(uhdlc_priv);
>   1106          if (!dev) {
>   1107                  ret = -ENOMEM;
>   1108                  pr_err("ucc_hdlc: unable to allocate memory\n");
>   1109                  goto err_hdlc_init;
> 
> Hm...  Here we need to undo what uhdlc_init() did.  I'm not sure the function to
> do that.  Currently we leak resources.
> 
> 			goto undo_uhdlc_init;
> 
>   1110          }
>   1111
>   1112          uhdlc_priv->ndev = dev;
>   1113          hdlc = dev_to_hdlc(dev);
>   1114          dev->tx_queue_len = 16;
>   1115          dev->netdev_ops = &uhdlc_ops;
>   1116          hdlc->attach = ucc_hdlc_attach;
>   1117          hdlc->xmit = ucc_hdlc_tx;
>   1118          netif_napi_add(dev, &uhdlc_priv->napi, ucc_hdlc_poll, 32);
>   1119          if (register_hdlc_device(dev)) {
>   1120                  ret = -ENOBUFS;
> 
> Why are we not preserving the error code?
> 
> 		ret = register_hdlc_device(dev);
> 		if (ret) {
> 
>   1121                  pr_err("ucc_hdlc: unable to register hdlc device\n");
> 
> No need for this printk.
> 
>   1122                  free_netdev(dev);
>   1123                  goto err_hdlc_init;
> 
> Instead of freeing and then a goto just do "goto free_dev;".
> 
>   1124          }
>   1125
>   1126          return 0;
>   1127
>   1128  err_hdlc_init:
>   1129  err_miss_tsa_property:
>   1130          kfree(uhdlc_priv);
>   1131          if (uhdlc_priv->tsa)
>   1132                  kfree(utdm);
>   1133  err_alloc_utdm:
>   1134          kfree(uhdlc_priv);
>   1135  err_alloc_priv:
>   1136          return ret;
>   1137  }
> 
> You can see the problems.  We free uhdlc_priv then we dereference it, then
> we free it a second time.  There is stuff that is missing.  The labels are bad.
> Here is the new version:
> 
> free_dev:
> 	free_netdev(dev);
> undo_uhdlc_init:
> 	/* FIXME: impliment this code */
> free_utdm:
> 	if (uhdlc_priv->tsa)
> 		kfree(utdm);
> free_uhdlc:
> 	kfree(uhdlc);
> 
> 	return ret;
> 
> Just follow the steps and then error handling is easy to understand.
> 
> regards,
> dan carpenter

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

* [bug report] drivers/net: support hdlc function for QE-UCC
  2016-07-12 23:49 [bug report] drivers/net: support hdlc function for QE-UCC Dan Carpenter
  2016-07-13  2:22 ` Qiang Zhao
@ 2016-08-03 14:13 ` Dan Carpenter
  1 sibling, 0 replies; 3+ messages in thread
From: Dan Carpenter @ 2016-08-03 14:13 UTC (permalink / raw)
  To: kernel-janitors

Hello Zhao Qiang,

The patch c19b6d246a35: "drivers/net: support hdlc function for
QE-UCC" from Jun 6, 2016, leads to the following static checker
warning:

	drivers/net/wan/fsl_ucc_hdlc.c:164 uhdlc_init()
	warn: unsigned 'priv->ucc_pram_offset' is never less than zero.

drivers/net/wan/fsl_ucc_hdlc.c
   159  
   160          /* Alloc parameter ram for ucc hdlc */
   161          priv->ucc_pram_offset = qe_muram_alloc(sizeof(priv->ucc_pram),
   162                                  ALIGNMENT_OF_UCC_HDLC_PRAM);
   163  
   164          if (priv->ucc_pram_offset < 0) {

This is slightly complicated what's happening here.  qe_muram_alloc()
returns negatives but casted to an unsigned long, then we assign it to
priv->ucc_pram_offset which is a u32.

   165                  dev_err(priv->dev, "Can not allocate MURAM for hdlc prameter.\n");
   166                  ret = -ENOMEM;
   167                  goto free_tx_bd;
   168          }
   169  

regards,
dan carpenter

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

end of thread, other threads:[~2016-08-03 14:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-12 23:49 [bug report] drivers/net: support hdlc function for QE-UCC Dan Carpenter
2016-07-13  2:22 ` Qiang Zhao
2016-08-03 14:13 ` Dan Carpenter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox