re: usb: gadget: nokia: convert to new interface of f_phonet

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Andrzej Pietrasiewicz,

The patch 83167f12da05: "usb: gadget: nokia: convert to new interface
of f_phonet" from May 23, 2013, leads to the following Smatch
warnings:

drivers/usb/gadget/nokia.c:209 nokia_bind_config() error: potential NULL dereference 'f_obex2'.
drivers/usb/gadget/nokia.c:211 nokia_bind_config() error: potential NULL dereference 'f_obex1'.
drivers/usb/gadget/nokia.c:213 nokia_bind_config() error: potential NULL dereference 'f_phonet'.

Let me walk you throug the code for the first warning.

drivers/usb/gadget/nokia.c
   115  static struct usb_function_instance *fi_acm;
   116  static struct usb_function_instance *fi_ecm;
   117  static struct usb_function_instance *fi_obex1;
   118  static struct usb_function_instance *fi_obex2;
   119  static struct usb_function_instance *fi_phonet;
   120  
   121  static int __init nokia_bind_config(struct usb_configuration *c)
   122  {
   123          struct usb_function *f_acm;
   124          struct usb_function *f_phonet = NULL;
   125          struct usb_function *f_obex1 = NULL;
   126          struct usb_function *f_ecm;
   127          struct usb_function *f_obex2 = NULL;
   128          int status = 0;
   129          int obex1_stat = 0;
   130          int obex2_stat = 0;
   131          int phonet_stat = 0;

We need to trace three variables to understand the first warning
message: fi_obex2, f_obex2, and obex2_stat.

Lets start with the assumption that "fi_obex2" is an error pointer at
the start of the function.
f_obex2 is NULL.
obex2_stat is zero.

   132  
   133          if (!IS_ERR(fi_phonet)) {
   134                  f_phonet = usb_get_function(fi_phonet);
   135                  if (IS_ERR(f_phonet))
   136                          pr_debug("could not get phonet function\n");
   137          }
   138  
   139          if (!IS_ERR(fi_obex1)) {
   140                  f_obex1 = usb_get_function(fi_obex1);
   141                  if (IS_ERR(f_obex1))
   142                          pr_debug("could not get obex function 0\n");

It's funny that the human readable messages start counting from zero as
in "obex function 0" and "obex function 1" but the computer code starts
counting from 1 as in "fi_obex1" and "fi_obex2".  Normally you would
expect it to be the other way around.  Also this is not consistent with
the rest of the driver.

   143          }
   144  
   145          if (!IS_ERR(fi_obex2)) {
   146                  f_obex2 = usb_get_function(fi_obex2);
   147                  if (IS_ERR(f_obex2))
   148                          pr_debug("could not get obex function 1\n");
   149          }

fi_obex2 is an error pointer.
f_obex2 is NULL.
obex2_stat is zero.

   150  
   151          f_acm = usb_get_function(fi_acm);
   152          if (IS_ERR(f_acm)) {
   153                  status = PTR_ERR(f_acm);
   154                  goto err_get_acm;
   155          }
   156  
   157          f_ecm = usb_get_function(fi_ecm);
   158          if (IS_ERR(f_ecm)) {
   159                  status = PTR_ERR(f_ecm);
   160                  goto err_get_ecm;
   161          }
   162  
   163          if (!IS_ERR_OR_NULL(f_phonet)) {
   164                  phonet_stat = usb_add_function(c, f_phonet);
   165                  if (phonet_stat)
   166                          pr_debug("could not add phonet function\n");
   167          }
   168  
   169          if (!IS_ERR_OR_NULL(f_obex1)) {
   170                  obex1_stat = usb_add_function(c, f_obex1);
   171                  if (obex1_stat)
   172                          pr_debug("could not add obex function 0\n");
   173          }
   174  
   175          if (!IS_ERR_OR_NULL(f_obex2)) {
   176                  obex2_stat = usb_add_function(c, f_obex2);
   177                  if (obex2_stat)
   178                          pr_debug("could not add obex function 1\n");
   179          }

f_obex2 is NULL so the condition is false.
obex2_stat is zero.

   180  
   181          status = usb_add_function(c, f_acm);
   182          if (status)
   183                  goto err_conf;

Let's assume we hit this goto.

   184  
   185          status = usb_add_function(c, f_ecm);
   186          if (status) {
   187                  pr_debug("could not bind ecm config %d\n", status);
   188                  goto err_ecm;
   189          }
   190          if (c == &nokia_config_500ma_driver) {
   191                  f_acm_cfg1 = f_acm;
   192                  f_ecm_cfg1 = f_ecm;
   193                  f_phonet_cfg1 = f_phonet;
   194                  f_obex1_cfg1 = f_obex1;
   195                  f_obex2_cfg1 = f_obex2;
   196          } else {
   197                  f_acm_cfg2 = f_acm;
   198                  f_ecm_cfg2 = f_ecm;
   199                  f_phonet_cfg2 = f_phonet;
   200                  f_obex1_cfg2 = f_obex1;
   201                  f_obex2_cfg2 = f_obex2;

Btw, we are assigning an ERR_PTR to the global here.  It means we need
to constantly check it, which the code does, but it's messy.  The driver
would be cleaner if we never did this.

   202          }
   203  
   204          return status;

Just "return 0" here to make it more obvious that we are returning zero.

   205  err_ecm:
   206          usb_remove_function(c, f_acm);
   207  err_conf:
   208          if (!obex2_stat)
   209                  usb_remove_function(c, f_obex2);

obex2_stat is zero.
f_obex2 is NULL.
This causes a NULL dereference.

We could initialize obex2_stat to -1 instead of 0 which would fix the
NULL deref but the real problem is that this code is quite messy.

We should be clearing the ERR_PTRs right away if we aren't going to use
the values.

		f_obex1 = usb_get_function(fi_obex1);
		if (IS_ERR(f_obex1)) {
			pr_debug("could not get obex function 0\n");
			f_obex1 = NULL;
		}

I'm not very familiar with this hardware, why is it not an error when
the usb_get_function() and usb_add_function() calls fail?

   210          if (!obex1_stat)
   211                  usb_remove_function(c, f_obex1);
   212          if (!phonet_stat)
   213                  usb_remove_function(c, f_phonet);
   214          usb_put_function(f_ecm);
   215  err_get_ecm:
   216          usb_put_function(f_acm);
   217  err_get_acm:
   218          if (!IS_ERR_OR_NULL(f_obex2))
   219                  usb_put_function(f_obex2);
   220          if (!IS_ERR_OR_NULL(f_obex1))
   221                  usb_put_function(f_obex1);
   222          if (!IS_ERR_OR_NULL(f_phonet))
   223                  usb_put_function(f_phonet);
   224          return status;
   225  }

regards,
dan carpenter

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux