All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: kernel-janitors@vger.kernel.org
Subject: [bug report] drivers/net: support hdlc function for QE-UCC
Date: Tue, 12 Jul 2016 23:49:19 +0000	[thread overview]
Message-ID: <20160712234919.GA23061@mwanda> (raw)

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

             reply	other threads:[~2016-07-12 23:49 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-07-12 23:49 Dan Carpenter [this message]
2016-07-13  2:22 ` [bug report] drivers/net: support hdlc function for QE-UCC Qiang Zhao
2016-08-03 14:13 ` Dan Carpenter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160712234919.GA23061@mwanda \
    --to=dan.carpenter@oracle.com \
    --cc=kernel-janitors@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.