summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit Pundir <amit.pundir@linaro.org>2015-08-01 03:26:51 +0530
committerBadhri Jagan Sridharan <badhri@google.com>2015-11-18 22:31:16 +0000
commit2c51a3f603e38439130cba62c6c503e594979f3d (patch)
treedbdcc340d15d1a820a11ba92952a18ad049a0f6f
parentb669974001120b2199e250bf5f3a2efeb6d242ac (diff)
downloadmediatek-2c51a3f603e38439130cba62c6c503e594979f3d.tar.gz
usb: gadget: fix NULL ptr derefer while symlinking PTP func
Fix NULL pointer dereference while trying to link PTP function to a gadget configuration without creating MTP function. PTP piggyback on MTP function so make sure we have MTP function created beforehand. Otherwise we run into following kernel panic: ----------------------- [ 70.329957] Unable to handle kernel NULL pointer dereference at virtual address 00000000 [ 70.330738] pgd = dd8ec000 [ 70.330916] [00000000] *pgd=00000000 [ 70.331663] Internal error: Oops: 805 [#1] SMP THUMB2 [ 70.332155] CPU: 0 PID: 2067 Comm: ln Not tainted 3.18.0-00587-gdfa582e #1 [ 70.332511] task: dd9c92c0 ti: dd822000 task.ti: dd822000 [ 70.333094] PC is at function_alloc_mtp_ptp+0xe/0x68 [ 70.333311] LR is at usb_get_function+0x11/0x1c [ 70.333489] pc : [<c034ec12>] lr : [<c033cce9>] psr: 60070033 <..snip..> [ 70.384111] 3fc0: bec14ae4 00000004 bec14c0a 00000053 00000004 b6f0422d 00000000 bec14adc [ 70.384369] 3fe0: bec14af8 bec14a98 b6f071f3 b6e8977c 20070010 bec14c0d 00000000 00000000 [ 70.384832] [<c034ec12>] (function_alloc_mtp_ptp) from [<c033cce9>] (usb_get_function+0x11/0x1c) [ 70.385146] [<c033cce9>] (usb_get_function) from [<c033da9b>] (config_usb_cfg_link+0x87/0xa8) [ 70.385421] [<c033da9b>] (config_usb_cfg_link) from [<c011f417>] (configfs_symlink+0xb7/0x1c8) [ 70.385696] [<c011f417>] (configfs_symlink) from [<c00dcd8d>] (vfs_symlink+0x85/0xc0) [ 70.386010] [<c00dcd8d>] (vfs_symlink) from [<c00dce0b>] (SyS_symlinkat+0x43/0x70) [ 70.386261] [<c00dce0b>] (SyS_symlinkat) from [<c000ce41>] (ret_fast_syscall+0x1/0x5c) [ 70.386610] Code: eb04 4a0f 6e03 480f (e883) 0005 [ 70.387346] ---[ end trace 8dba7c552e02f8fa ]--- [ 70.387647] Kernel panic - not syncing: Fatal exception [ 70.387980] ---[ end Kernel panic - not syncing: Fatal exception ----------------------- Steps to reproduce the kernel panic: mount -t configfs none /config mkdir /config/usb_gadget/g1 cd /config/usb_gadget/g1 echo 0x18d1 > idVendor echo 0x4e26 > idProduct mkdir strings/0x409 echo 0123459876 > strings/0x409/serialnumber echo Asus > strings/0x409/manufacturer echo Nexus7 > strings/0x409/product mkdir configs/c.1 mkdir configs/c.1/strings/0x409 echo "Conf 1" > configs/c.1/strings/0x409/configuration echo 120 > configs/c.1/MaxPower mkdir functions/ptp.ptp ln -s functions/ptp.ptp configs/c.1/ptp.ptp Also MTP and PTP are mutually exclusive functions so make sure we have only one of it linked to a configuration at a time. Otherwise it opens up another set of bug(s?). Signed-off-by: Amit Pundir <amit.pundir@linaro.org> (cherry picked from commit c44a699d96df2e13467fc081bff88b97dcc5afb2) Change-Id: I265c8531a2f58cb421e6212879481eb6a360dd2a
-rw-r--r--drivers/usb/gadget/configfs.c5
-rw-r--r--drivers/usb/gadget/function/f_mtp.c18
-rw-r--r--drivers/usb/gadget/functions.c2
3 files changed, 23 insertions, 2 deletions
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index cb53930bd24e..d201f5609bb0 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -436,6 +436,11 @@ static int config_usb_cfg_link(
}
f = usb_get_function(fi);
+ if (f == NULL) {
+ /* Are we trying to symlink PTP without MTP function? */
+ ret = -EINVAL; /* Invalid Configuration */
+ goto out;
+ }
if (IS_ERR(f)) {
ret = PTR_ERR(f);
goto out;
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 82f6b2ebaebb..03a61f8b9d48 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -1426,8 +1426,24 @@ struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi,
bool mtp_config)
{
struct mtp_instance *fi_mtp = to_fi_mtp(fi);
- struct mtp_dev *dev = fi_mtp->dev;
+ struct mtp_dev *dev;
+
+ /*
+ * PTP piggybacks on MTP function so make sure we have
+ * created MTP function before we associate this PTP
+ * function with a gadget configuration.
+ */
+ if (fi_mtp->dev == NULL) {
+ pr_err("Error: Create MTP function before linking"
+ " PTP function with a gadget configuration\n");
+ pr_err("\t1: Delete existing PTP function if any\n");
+ pr_err("\t2: Create MTP function\n");
+ pr_err("\t3: Create and symlink PTP function"
+ " with a gadget configuration\n");
+ return NULL;
+ }
+ dev = fi_mtp->dev;
dev->function.name = DRIVER_NAME;
dev->function.strings = mtp_strings;
if (mtp_config) {
diff --git a/drivers/usb/gadget/functions.c b/drivers/usb/gadget/functions.c
index b13f839e7368..389c1f3d0fee 100644
--- a/drivers/usb/gadget/functions.c
+++ b/drivers/usb/gadget/functions.c
@@ -58,7 +58,7 @@ struct usb_function *usb_get_function(struct usb_function_instance *fi)
struct usb_function *f;
f = fi->fd->alloc_func(fi);
- if (IS_ERR(f))
+ if ((f == NULL) || IS_ERR(f))
return f;
f->fi = fi;
return f;