aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLeon Winter <winter-cyanongenmod@bfw-online.de>2014-10-30 11:05:03 +0100
committerLeon Winter <winter-cyanongenmod@bfw-online.de>2014-11-03 06:57:14 +0000
commit22cbf2cfb211cef2e493c5984d237d0509bf98ce (patch)
tree83f17743e4f74656416797ba1911b4cf049d1e94
parent4ca83ffe8bbf82acb088bb7af50a952c95d1d09e (diff)
downloadkernel_samsung_smdk4412-22cbf2cfb211cef2e493c5984d237d0509bf98ce.zip
kernel_samsung_smdk4412-22cbf2cfb211cef2e493c5984d237d0509bf98ce.tar.gz
kernel_samsung_smdk4412-22cbf2cfb211cef2e493c5984d237d0509bf98ce.tar.bz2
otg: when removing ED from readyQ also set flag
The driver keeps track of the "is this endpoint in the list" state with the redundant flag ".is_in_transfer_ready_q". It should therefore always be sync with the .next and .prev of the readyq_list list: struct ed *ed; otg_list_head *qlist = (typeof qlist) ed->readyq_list; (qlist->prev == LIST_POISON2 || qlist->next == LIST_POISON1) == !ed->ed_status.is_in_transfer_ready_q; Should both properties be not in sync, bad things can happen. All code paths in driver rely on the flag and then call list operations. If the flag suggests the entry is in the list, otg_list_pop () will be called. When the entry however is not in the list, the members .prev and .next are poisoned and an attempt to do list operations on them results into a NULL (or rather an invalid address which is the poison) pointer dereference. Such a fault would then trigger a kernel panic and the device rebooting. In real life this happens when disconnecting USB devices frequently, especially when in operation (transfering data while detaching). While in most positions in the code, it was taken care to keep both properties, the flag and the list entry state, consistent, one position was left out, which is addressed with this patch. Extensive testing shows that the device would crash easily and in a reproducable manner without the patch but does not show any faults with the patch applied. Change-Id: I80f3a8e7d866c699ddcd1c61b04d956e39d2197c
-rw-r--r--drivers/usb/host/shost/shost_readyq.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/usb/host/shost/shost_readyq.c b/drivers/usb/host/shost/shost_readyq.c
index 9e41da5..b2ccea0 100644
--- a/drivers/usb/host/shost/shost_readyq.c
+++ b/drivers/usb/host/shost/shost_readyq.c
@@ -202,6 +202,7 @@ static int get_ed_from_ready_q(struct ed **get_ed, bool is_periodic)
} else {
otg_list_pop(qlist);
periodic_trans_ready_q.entity_num--;
+ get_ed[0]->ed_status.is_in_transfer_ready_q = false;
}
return USB_ERR_SUCCESS;
@@ -230,6 +231,7 @@ static int get_ed_from_ready_q(struct ed **get_ed, bool is_periodic)
} else {
otg_list_pop(qlist);
nonperiodic_trans_ready_q.entity_num--;
+ get_ed[0]->ed_status.is_in_transfer_ready_q = false;
}
return USB_ERR_SUCCESS;
} else