From: Felipe Balbi <balbi@kernel.org>
To: Yu Chen <chenyu56@huawei.com>,
gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: wangbinghui@hisilicon.com
Subject: usb:dwc3:fix access poisoned list_head in dwc3_gadget_giveback
Date: Mon, 08 Jan 2018 13:46:11 +0200 [thread overview]
Message-ID: <87fu7glgjg.fsf@linux.intel.com> (raw)
Hi,
Yu Chen <chenyu56@huawei.com> writes:
> From: Yu Chen <chenyu56@huawei.com>
>
> Unable to handle kernel paging request at virtual address dead000000000108
> pgd = fffffff7a3179000
> [dead000000000108] *pgd=00000000230e0003, *pud=00000000230e0003,
> *pmd=0000000000000000
> Internal error: Oops: 96000044 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 2 PID: 1 Comm: init Tainted: G W 4.4.23+ #1
try mainline
> TGID: 1 Comm: init
> Hardware name: kirin970 (DT)
> task: fffffff99f190000 ti: fffffff99f1740e0 task.ti: fffffff99f1740e0
> PC is at dwc3_gadget_giveback+0xa8/0x228
> LR is at dwc3_remove_requests+0x44/0x88
>
> The crash occurred when usb work as rndis device and
> __dwc3_gadget_kick_transfer return error in __dwc3_gadget_ep_queue.
> The request submited in __dwc3_gadget_ep_queue is moved to started_list
> but not kicked. It is stil on started_list although
> __dwc3_gadget_kick_transfer failed. When dwc3_gadget_ep_queue return
why did kick_transfer fail? Where are the tracepoints showing the
failure?
> error to u_ether driver, the request will be resubmit to dwc3 driver.
> At last, the same request is both on started_list and pending_list,
> it will be list_del twice in dwc3_remove_requests and cause crash.
>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
> drivers/usb/dwc3/gadget.c | 28 +++++++++++++++++++++++++++-
> 1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 639dd1b163a0..a913e64ca4e0 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1278,9 +1278,28 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
> __dwc3_gadget_start_isoc(dwc, dep, cur_uf);
> }
>
> +static int dwc3_gadget_is_req_pengding_or_started(struct dwc3_ep *dep,
> + struct dwc3_request *req)
> +{
> + struct dwc3_request *iterate_req;
> +
> + list_for_each_entry(iterate_req, &dep->pending_list, list) {
> + if (iterate_req == req)
> + return 1;
> + }
> +
> + list_for_each_entry(iterate_req, &dep->started_list, list) {
> + if (iterate_req == req)
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
> {
> struct dwc3 *dwc = dep->dwc;
> + int ret;
>
> if (!dep->endpoint.desc) {
> dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
> @@ -1334,7 +1353,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
> }
>
> out:
> - return __dwc3_gadget_kick_transfer(dep);
> + ret = __dwc3_gadget_kick_transfer(dep);
> + if (ret && dwc3_gadget_is_req_pengding_or_started(dep, req)) {
first we need to figure out why kick_transfer failed. It shouldn't fail,
so why did it? Then I need you to try with a more recent kernel v4.4 is
rather old and a lot has changed WRT transfer handling:
$ git rev-list --count --no-merges v4.4..linus/master -- drivers/usb/dwc3/gadget.c
184
WARNING: multiple messages have this Message-ID (diff)
From: Felipe Balbi <balbi@kernel.org>
To: Yu Chen <chenyu56@huawei.com>,
gregkh@linuxfoundation.org, linux-usb@vger.kernel.org,
linux-kernel@vger.kernel.org
Cc: wangbinghui@hisilicon.com
Subject: Re: [PATCH] usb:dwc3:fix access poisoned list_head in dwc3_gadget_giveback
Date: Mon, 08 Jan 2018 13:46:11 +0200 [thread overview]
Message-ID: <87fu7glgjg.fsf@linux.intel.com> (raw)
In-Reply-To: <20171223092505.23620-1-chenyu56@huawei.com>
[-- Attachment #1: Type: text/plain, Size: 3059 bytes --]
Hi,
Yu Chen <chenyu56@huawei.com> writes:
> From: Yu Chen <chenyu56@huawei.com>
>
> Unable to handle kernel paging request at virtual address dead000000000108
> pgd = fffffff7a3179000
> [dead000000000108] *pgd=00000000230e0003, *pud=00000000230e0003,
> *pmd=0000000000000000
> Internal error: Oops: 96000044 [#1] PREEMPT SMP
> Modules linked in:
> CPU: 2 PID: 1 Comm: init Tainted: G W 4.4.23+ #1
try mainline
> TGID: 1 Comm: init
> Hardware name: kirin970 (DT)
> task: fffffff99f190000 ti: fffffff99f1740e0 task.ti: fffffff99f1740e0
> PC is at dwc3_gadget_giveback+0xa8/0x228
> LR is at dwc3_remove_requests+0x44/0x88
>
> The crash occurred when usb work as rndis device and
> __dwc3_gadget_kick_transfer return error in __dwc3_gadget_ep_queue.
> The request submited in __dwc3_gadget_ep_queue is moved to started_list
> but not kicked. It is stil on started_list although
> __dwc3_gadget_kick_transfer failed. When dwc3_gadget_ep_queue return
why did kick_transfer fail? Where are the tracepoints showing the
failure?
> error to u_ether driver, the request will be resubmit to dwc3 driver.
> At last, the same request is both on started_list and pending_list,
> it will be list_del twice in dwc3_remove_requests and cause crash.
>
> Signed-off-by: Yu Chen <chenyu56@huawei.com>
> ---
> drivers/usb/dwc3/gadget.c | 28 +++++++++++++++++++++++++++-
> 1 file changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
> index 639dd1b163a0..a913e64ca4e0 100644
> --- a/drivers/usb/dwc3/gadget.c
> +++ b/drivers/usb/dwc3/gadget.c
> @@ -1278,9 +1278,28 @@ static void dwc3_gadget_start_isoc(struct dwc3 *dwc,
> __dwc3_gadget_start_isoc(dwc, dep, cur_uf);
> }
>
> +static int dwc3_gadget_is_req_pengding_or_started(struct dwc3_ep *dep,
> + struct dwc3_request *req)
> +{
> + struct dwc3_request *iterate_req;
> +
> + list_for_each_entry(iterate_req, &dep->pending_list, list) {
> + if (iterate_req == req)
> + return 1;
> + }
> +
> + list_for_each_entry(iterate_req, &dep->started_list, list) {
> + if (iterate_req == req)
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
> {
> struct dwc3 *dwc = dep->dwc;
> + int ret;
>
> if (!dep->endpoint.desc) {
> dev_err(dwc->dev, "%s: can't queue to disabled endpoint\n",
> @@ -1334,7 +1353,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
> }
>
> out:
> - return __dwc3_gadget_kick_transfer(dep);
> + ret = __dwc3_gadget_kick_transfer(dep);
> + if (ret && dwc3_gadget_is_req_pengding_or_started(dep, req)) {
first we need to figure out why kick_transfer failed. It shouldn't fail,
so why did it? Then I need you to try with a more recent kernel v4.4 is
rather old and a lot has changed WRT transfer handling:
$ git rev-list --count --no-merges v4.4..linus/master -- drivers/usb/dwc3/gadget.c
184
--
balbi
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
next reply other threads:[~2018-01-08 11:46 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-01-08 11:46 Felipe Balbi [this message]
2018-01-08 11:46 ` [PATCH] usb:dwc3:fix access poisoned list_head in dwc3_gadget_giveback Felipe Balbi
-- strict thread matches above, loose matches on Subject: below --
2017-12-23 9:25 Yu Chen
2017-12-23 9:25 ` [PATCH] " Yu Chen
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=87fu7glgjg.fsf@linux.intel.com \
--to=balbi@kernel.org \
--cc=chenyu56@huawei.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=wangbinghui@hisilicon.com \
/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.