From patchwork Fri Oct 27 20:19:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avichal Rakesh X-Patchwork-Id: 159145 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp862139vqb; Fri, 27 Oct 2023 13:20:28 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFpLaU+DTDIAq+sMfVNCvNT5le+0IqKViq7y6z3avVqqOQn4M5LwnUgnjEanngFXJpwmvXB X-Received: by 2002:a81:99c3:0:b0:5a8:1aa0:6253 with SMTP id q186-20020a8199c3000000b005a81aa06253mr3290685ywg.7.1698438028246; Fri, 27 Oct 2023 13:20:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698438028; cv=none; d=google.com; s=arc-20160816; b=Bl6789pwaKTHX6dJs+MH8ty9s1gBEmtaEVdYPXs8IpiO2VoKCZ6diChPL/YhcgSzNS FXvLtAiv0HD9E0qcA+qQgG5fvV+b2kfrEV9GjC8HVxtMilMbY9kbBgZDMwq9lzEEcfzu gGsyMp4ga5gM7mpAQXjzR1OjQLjomj4uB2/78H2KM5lDv2GOcG1wKJMWxyEB5pqJD3Af OvobDgSauqX5INJ9U/BvSUrNy3cgdajId1aL3s0o353qrWYJqGFT0N2H5mYYF4gmo1n5 yOSEI3RliRmWxBumyfhCFpPpKqb90epqaBYuyfI4mICL2k6Izt+MmoCKpr6eXCLRv+1N aL/Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=Ep/ELVWkKr4CeruSxLnrkZQE2W1VuCadmVO/eYOPMRk=; fh=p+LYTnSpNzrqEe7IwOmRmqfbsNd6xnlNPhpiE7PelQI=; b=tPAdnwOyzRdVmw4nWktCpu1laWjdVj7geHtcoUUHRSDseHkkTTdizspERI+XPVg8HT DjBfuwCPyqf6izZ6HKoyw+pCkuIWwBuu32sITnWvBJZk810mYk9vzJslQ0eK33fJrtEJ Yt43WoZD+KkxziMKGfvETYfI7CXq5P2XMqBURyR2AYhF9YfUfvM45CGmjh3ChS+GSlcO 4+57fTB5dkN9ta7SZuZX/u3mQiepP4fa+oLJRUdL8Noy62qGB3E5AeR8rsxthsGUfJuH kGBjd5W/5gPhky2IfuyxIYh5hIDGYLZ1CWEXv6sz4fFEQPdlyQkldpqMNB8rxG+MYOut AWgg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=Oy5ULI1x; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:3 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from lipwig.vger.email (lipwig.vger.email. [2620:137:e000::3:3]) by mx.google.com with ESMTPS id p63-20020a0dcd42000000b005a7e46262e7si3597295ywd.375.2023.10.27.13.20.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 13:20:28 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:3 as permitted sender) client-ip=2620:137:e000::3:3; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=Oy5ULI1x; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:3 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id 27265829A545; Fri, 27 Oct 2023 13:20:24 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346384AbjJ0UUJ (ORCPT + 27 others); Fri, 27 Oct 2023 16:20:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230451AbjJ0UUI (ORCPT ); Fri, 27 Oct 2023 16:20:08 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CD5031AA for ; Fri, 27 Oct 2023 13:20:05 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-da1176f3d96so1003835276.2 for ; Fri, 27 Oct 2023 13:20:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698438005; x=1699042805; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Ep/ELVWkKr4CeruSxLnrkZQE2W1VuCadmVO/eYOPMRk=; b=Oy5ULI1xCGvq5/en2OQihjQfOfkMVL/ir4JroB3PvAbiXYSRxKBdvYwrL6iFL0u1wf XJe+1MuOP0DmfK+XCpRNuhfTwjjpDP2lmFEcvVnb+plCbDIr3O5pCpZbrAx3Xf10wVkU mo/durMepm5yw1gTYpkxov2+HhW5bc1nFSxkbExN5xT6s5UbtElRXtybrrgKpjCJ7AGJ hi6+4kJpIvK4GW8rkIws9joNEv8K4fIXHCCcofB9pTvICi16s5GrMVU6kOwVROqUp+J3 ZNdDMtM1+aDjcOIOMi1L/i9I4avSlilZ3M/rof0Hei0YkR7PeTpsmKEPqifivzydF+b9 Qo2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698438005; x=1699042805; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Ep/ELVWkKr4CeruSxLnrkZQE2W1VuCadmVO/eYOPMRk=; b=YYdPu8FJLL70tlEYicg3RvKJbofs1eKyyONtOsqv4PUvQgKr1fLcvku+yfSVQAXHqn KuYl5Lyq2NomBRRn3oVzIl5v9vqfc58jDYrfNn/5zIiiQtYvQcVn77vnXu4wEdDviIYU UE+6AH5+sZgJEs/fIXrUJUbhMRXWAvQjYymhoyU8oVgXNQ9lNSyxTlkCu/o49gET0WaR Ju4tz5aBR5W6ztHXhiItH1+LHfS/eN9TGgpiPy/jmQW+drv7CRYTwtv+lmVATUfS6RbE Ja6l5ayNH0X53N/RlLywkxkW1otCexEUZ667QGt2jwMaPN4AwE6ie0MBdbJKPyOrKNpU O4hw== X-Gm-Message-State: AOJu0YxEfsVFUtfdlt+K3a6XFWaOWhoyWMR7a7crVwO+qYkRWjYjLs14 gSAMlp/TGF1fSyLI9OzpaMtSn6hOFEzt X-Received: from hi-h2o-specialist.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:3cef]) (user=arakesh job=sendgmr) by 2002:a25:cfca:0:b0:d9a:556d:5f8a with SMTP id f193-20020a25cfca000000b00d9a556d5f8amr67456ybg.12.1698438005024; Fri, 27 Oct 2023 13:20:05 -0700 (PDT) Date: Fri, 27 Oct 2023 13:19:56 -0700 In-Reply-To: <73309396-3856-43a2-9a6f-81a40ed594db@google.com> Mime-Version: 1.0 References: <73309396-3856-43a2-9a6f-81a40ed594db@google.com> X-Mailer: git-send-email 2.42.0.820.g83a721a137-goog Message-ID: <20231027201959.1869181-1-arakesh@google.com> Subject: [PATCH v9 1/4] usb: gadget: uvc: prevent use of disabled endpoint From: Avichal Rakesh To: arakesh@google.com, dan.scally@ideasonboard.com Cc: etalvala@google.com, gregkh@linuxfoundation.org, jchowdhary@google.com, laurent.pinchart@ideasonboard.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, m.grzeschik@pengutronix.de X-Spam-Status: No, score=-5.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SORTED_RECIPS,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Fri, 27 Oct 2023 13:20:24 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780941353830649923 X-GMAIL-MSGID: 1780941353830649923 Currently the set_alt callback immediately disables the endpoint and queues the v4l2 streamoff event. However, as the streamoff event is processed asynchronously, it is possible that the video_pump thread attempts to queue requests to an already disabled endpoint. This change moves disabling usb endpoint to the end of streamoff event callback. As the endpoint's state can no longer be used, video_pump is now guarded by uvc->state as well. To be consistent with the actual streaming state, uvc->state is now toggled between CONNECTED and STREAMING from the v4l2 event callback only. Link: https://lore.kernel.org/20230615171558.GK741@pendragon.ideasonboard.com/ Link: https://lore.kernel.org/20230531085544.253363-1-dan.scally@ideasonboard.com/ Reviewed-by: Daniel Scally Reviewed-by: Michael Grzeschik Tested-by: Michael Grzeschik Signed-off-by: Avichal Rakesh --- v1 -> v2: Rebased to ToT and reworded commit message. v2 -> v3: Fix email threading goof-up v3 -> v4: Address review comments & re-rebase to ToT v4 -> v5: Add Reviewed-by & Tested-by v5 -> v6: No change v6 -> v7: No change v7 -> v8: No change. Getting back in review queue v8 -> v9: Fix typo. No functional change. drivers/usb/gadget/function/f_uvc.c | 11 +++++------ drivers/usb/gadget/function/f_uvc.h | 2 +- drivers/usb/gadget/function/uvc.h | 2 +- drivers/usb/gadget/function/uvc_v4l2.c | 20 +++++++++++++++++--- drivers/usb/gadget/function/uvc_video.c | 3 ++- 5 files changed, 26 insertions(+), 12 deletions(-) -- 2.42.0.820.g83a721a137-goog diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index faa398109431..ae08341961eb 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -263,10 +263,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) return 0; } -void uvc_function_setup_continue(struct uvc_device *uvc) +void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep) { struct usb_composite_dev *cdev = uvc->func.config->cdev; + if (disable_ep && uvc->video.ep) + usb_ep_disable(uvc->video.ep); + usb_composite_setup_continue(cdev); } @@ -337,15 +340,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) if (uvc->state != UVC_STATE_STREAMING) return 0; - if (uvc->video.ep) - usb_ep_disable(uvc->video.ep); - memset(&v4l2_event, 0, sizeof(v4l2_event)); v4l2_event.type = UVC_EVENT_STREAMOFF; v4l2_event_queue(&uvc->vdev, &v4l2_event); - uvc->state = UVC_STATE_CONNECTED; - return 0; + return USB_GADGET_DELAYED_STATUS; case 1: if (uvc->state != UVC_STATE_CONNECTED) diff --git a/drivers/usb/gadget/function/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h index 1db972d4beeb..083aef0c65c6 100644 --- a/drivers/usb/gadget/function/f_uvc.h +++ b/drivers/usb/gadget/function/f_uvc.h @@ -11,7 +11,7 @@ struct uvc_device; -void uvc_function_setup_continue(struct uvc_device *uvc); +void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep); void uvc_function_connect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 6751de8b63ad..989bc6b4e93d 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -177,7 +177,7 @@ struct uvc_file_handle { * Functions */ -extern void uvc_function_setup_continue(struct uvc_device *uvc); +extern void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep); extern void uvc_function_connect(struct uvc_device *uvc); extern void uvc_function_disconnect(struct uvc_device *uvc); diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 3f0a9795c0d4..7cb8d027ff0c 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -451,7 +451,7 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) * Complete the alternate setting selection setup phase now that * userspace is ready to provide video frames. */ - uvc_function_setup_continue(uvc); + uvc_function_setup_continue(uvc, 0); uvc->state = UVC_STATE_STREAMING; return 0; @@ -463,11 +463,18 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) struct video_device *vdev = video_devdata(file); struct uvc_device *uvc = video_get_drvdata(vdev); struct uvc_video *video = &uvc->video; + int ret = 0; if (type != video->queue.queue.type) return -EINVAL; - return uvcg_video_enable(video, 0); + uvc->state = UVC_STATE_CONNECTED; + ret = uvcg_video_enable(video, 0); + if (ret < 0) + return ret; + + uvc_function_setup_continue(uvc, 1); + return 0; } static int @@ -500,6 +507,14 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, static void uvc_v4l2_disable(struct uvc_device *uvc) { uvc_function_disconnect(uvc); + /* + * Drop uvc->state to CONNECTED if it was streaming before. + * This ensures that the usb_requests are no longer queued + * to the controller. + */ + if (uvc->state == UVC_STATE_STREAMING) + uvc->state = UVC_STATE_CONNECTED; + uvcg_video_enable(&uvc->video, 0); uvcg_free_buffers(&uvc->video.queue); uvc->func_connected = false; @@ -647,4 +662,3 @@ const struct v4l2_file_operations uvc_v4l2_fops = { .get_unmapped_area = uvcg_v4l2_get_unmapped_area, #endif }; - diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 91af3b1ef0d4..c334802ac0a4 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -384,13 +384,14 @@ static void uvcg_video_pump(struct work_struct *work) struct uvc_video_queue *queue = &video->queue; /* video->max_payload_size is only set when using bulk transfer */ bool is_bulk = video->max_payload_size; + struct uvc_device *uvc = video->uvc; struct usb_request *req = NULL; struct uvc_buffer *buf; unsigned long flags; bool buf_done; int ret; - while (video->ep->enabled) { + while (uvc->state == UVC_STATE_STREAMING && video->ep->enabled) { /* * Retrieve the first available USB request, protected by the * request lock. From patchwork Fri Oct 27 20:19:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avichal Rakesh X-Patchwork-Id: 159146 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp862235vqb; Fri, 27 Oct 2023 13:20:39 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEhmfmnVCHvjDVbDGciS/j4YaUiXQlwTsF1lZM3lUY0wgGdsb5x1c7eVeuppWUvcx96nXfS X-Received: by 2002:a81:b65c:0:b0:5a7:b3d0:82c2 with SMTP id h28-20020a81b65c000000b005a7b3d082c2mr7030215ywk.12.1698438039773; Fri, 27 Oct 2023 13:20:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698438039; cv=none; d=google.com; s=arc-20160816; b=VmUbLR/stG+S3PYC57/a/Wd6d9gzBhjd0xJRC92HJ+Zdzg0L77iZkUtJSISqOEnQhh exZ58BCThIdzatV3/5sg5KWcorxnoEd/8F7n68F/4UCbVlM5ZQevyWe1LE7VR9OX1cAt aKUOSC2ULnMRlQnbChyhSj1tzMolCZCm5pailF9b44esmXfsG2N/oPs9t0PPjjQNr6LT 8ax4t1vEf5Za9LeS9D2k7LWlzrTo8cDC2rdf7ewRZh7sZrL7z7YoTEIc6NiTFiBx/7mT mLmwHsxLhHBnhLOwre5dfXvCvMwt0xi3i+I/E2NVSwJbYAUsquBGTfjabBxHmBdsOkdi rPcg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=XhqTHx+LqMazygh0ctOMGj9jIaaBIvzmi3aKCCPNWqo=; fh=p+LYTnSpNzrqEe7IwOmRmqfbsNd6xnlNPhpiE7PelQI=; b=lZD6rKqI5le8EpoDHnZRGNhXIwuVjdU1NLgSDfmGFyOvsGXlKJxxHEkCcA9DL8rHj0 bLUhCFGIc2Gyiyze7PMrpNGe9/1Z83ZKvc9GKDz+mUa9hhBHhrpnrhu3GqajDRWl5wpG UYX/MBBnF4ICpJBk+RRGs9SK/NEUpDrmaLM+Lij8hn3N6/bBy/BQV2C75CHE3npA4JMy 1OrRuJTmCSSSTBxDKU3hKlfYwq+b7HjgzH3xSRA/byLCG7Jg1wbT/v8MO6Pj8zPhQ97W FT603AXk300uk33t11+cjZW1rZlWaurMRst5ccTCbTmYxHOMJAKU9gd/Q6gueXV1/25K 1e4A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="a7f7UG4/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from howler.vger.email (howler.vger.email. [2620:137:e000::3:4]) by mx.google.com with ESMTPS id w64-20020a814943000000b005afa07156ecsi3822276ywa.28.2023.10.27.13.20.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 13:20:39 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) client-ip=2620:137:e000::3:4; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="a7f7UG4/"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:4 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by howler.vger.email (Postfix) with ESMTP id 791F283EB303; Fri, 27 Oct 2023 13:20:33 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at howler.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346400AbjJ0UUM (ORCPT + 27 others); Fri, 27 Oct 2023 16:20:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230451AbjJ0UUL (ORCPT ); Fri, 27 Oct 2023 16:20:11 -0400 Received: from mail-yw1-x114a.google.com (mail-yw1-x114a.google.com [IPv6:2607:f8b0:4864:20::114a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F07431B3 for ; Fri, 27 Oct 2023 13:20:08 -0700 (PDT) Received: by mail-yw1-x114a.google.com with SMTP id 00721157ae682-5b02ed0f886so4738947b3.0 for ; Fri, 27 Oct 2023 13:20:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698438008; x=1699042808; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=XhqTHx+LqMazygh0ctOMGj9jIaaBIvzmi3aKCCPNWqo=; b=a7f7UG4/QLHhQ5SM3b7M3pXPz6rjvtzDxYhyYdd3XU9VCVUkdt86vH2ttiiOx6M0d7 Ebyydw+xJt+JSUpNNR5qjVrnAYG5Ns7BJ+XILNuk/uLZVjqKvC28AszIDrKC9IUpSyJ9 dgYEvg7g/InSb6bh6PTr5Df0zY40uwmeEpA8KV33qkrn0HJZIaRVlDSsnj+MseEDXmSB 6LYK4bIZAcFD9dei0bfxoSPVTEE+zT1ZG0Hjm/xowr2h8XTVm6oizmgaElg7/hLchEX0 kdAzuNBdXVEDpPp1Un26mxjTMS7b7Mkh0kf3A/z0TuDyRGjsVw4Tq+nuEmif66t/O7b7 YbWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698438008; x=1699042808; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=XhqTHx+LqMazygh0ctOMGj9jIaaBIvzmi3aKCCPNWqo=; b=JXG47E4+DrCCHDqbvCxhpM6Yx38YSuWzZa8Gvp8h9e+my2nCoStfyuWb2vygT/Gi7Q AS86BVyoJXk3+uPA1NfW3798ulr8GMod/DE7REVpQaEmQo5VNXgLDdoJctSWwYLNAAC+ ao6FywoWxEKyf+C0m2rn9wewUdVj9j/C10dR1KbJi4xiL9atYexSoZgEiSjB0a+MwqgY tDnv/7Mg5ILDEDnwc8oVZW7FZMz/sSygVR+2ChP4u1Fv7NcPnMMAoPnfrHs9aGTl9TeC 4JNxasJt+N99gqFUNf8q0xQo5+bbG+DgfoAMtGkU7BJI0R0YMkaFcMHwfV4fpD1GLv+Q /nDw== X-Gm-Message-State: AOJu0YzLYoGX6USiysEcK0jR0AI8aW8r2HdSl5Dih3j5wex2Z83JfO7h A/ggK3ZtFesHxsCrNPf4UWjipkUkLMkJ X-Received: from hi-h2o-specialist.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:3cef]) (user=arakesh job=sendgmr) by 2002:a0d:df48:0:b0:5a7:b496:5983 with SMTP id i69-20020a0ddf48000000b005a7b4965983mr74286ywe.9.1698438008227; Fri, 27 Oct 2023 13:20:08 -0700 (PDT) Date: Fri, 27 Oct 2023 13:19:57 -0700 In-Reply-To: <20231027201959.1869181-1-arakesh@google.com> Mime-Version: 1.0 References: <73309396-3856-43a2-9a6f-81a40ed594db@google.com> <20231027201959.1869181-1-arakesh@google.com> X-Mailer: git-send-email 2.42.0.820.g83a721a137-goog Message-ID: <20231027201959.1869181-2-arakesh@google.com> Subject: [PATCH v9 2/4] usb: gadget: uvc: Allocate uvc_requests one at a time From: Avichal Rakesh To: arakesh@google.com, dan.scally@ideasonboard.com Cc: etalvala@google.com, gregkh@linuxfoundation.org, jchowdhary@google.com, laurent.pinchart@ideasonboard.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, m.grzeschik@pengutronix.de X-Spam-Status: No, score=-5.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SORTED_RECIPS,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on howler.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (howler.vger.email [0.0.0.0]); Fri, 27 Oct 2023 13:20:33 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780941366189213007 X-GMAIL-MSGID: 1780941366189213007 Currently, the uvc gadget driver allocates all uvc_requests as one array and deallocates them all when the video stream stops. This includes de-allocating all the usb_requests associated with those uvc_requests. This can lead to use-after-free issues if any of those de-allocated usb_requests were still owned by the usb controller. This patch is 1 of 2 patches addressing the use-after-free issue. Instead of bulk allocating all uvc_requests as an array, this patch allocates uvc_requests one at a time, which should allows for similar granularity when deallocating the uvc_requests. This patch has no functional changes other than allocating each uvc_request separately, and similarly freeing each of them separately. Link: https://lore.kernel.org/7cd81649-2795-45b6-8c10-b7df1055020d@google.com Suggested-by: Michael Grzeschik Reviewed-by: Daniel Scally Reviewed-by: Michael Grzeschik Tested-by: Michael Grzeschik Signed-off-by: Avichal Rakesh --- v1 -> v2: Rebased to ToT v2 -> v3: Fix email threading goof-up v3 -> v4: Address review comments & re-rebase to ToT v4 -> v5: Address more review comments. Add Reviewed-by & Tested-by. v5 -> v6: No change v6 -> v7: No change v7 -> v8: No change. Getting back in review queue v8 -> v9: Address review comments. drivers/usb/gadget/function/uvc.h | 3 +- drivers/usb/gadget/function/uvc_video.c | 89 ++++++++++++++----------- 2 files changed, 52 insertions(+), 40 deletions(-) -- 2.42.0.820.g83a721a137-goog diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 989bc6b4e93d..993694da0bbc 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -81,6 +81,7 @@ struct uvc_request { struct sg_table sgt; u8 header[UVCG_REQUEST_HEADER_LEN]; struct uvc_buffer *last_buf; + struct list_head list; }; struct uvc_video { @@ -102,7 +103,7 @@ struct uvc_video { /* Requests */ unsigned int req_size; - struct uvc_request *ureq; + struct list_head ureqs; /* all uvc_requests allocated by uvc_video */ struct list_head req_free; spinlock_t req_lock; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index c334802ac0a4..f8f9209fee50 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -227,6 +227,24 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, * Request handling */ +static void +uvc_video_free_request(struct uvc_request *ureq, struct usb_ep *ep) +{ + sg_free_table(&ureq->sgt); + if (ureq->req && ep) { + usb_ep_free_request(ep, ureq->req); + ureq->req = NULL; + } + + kfree(ureq->req_buffer); + ureq->req_buffer = NULL; + + if (!list_empty(&ureq->list)) + list_del_init(&ureq->list); + + kfree(ureq); +} + static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req) { int ret; @@ -293,27 +311,12 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) static int uvc_video_free_requests(struct uvc_video *video) { - unsigned int i; - - if (video->ureq) { - for (i = 0; i < video->uvc_num_requests; ++i) { - sg_free_table(&video->ureq[i].sgt); + struct uvc_request *ureq, *temp; - if (video->ureq[i].req) { - usb_ep_free_request(video->ep, video->ureq[i].req); - video->ureq[i].req = NULL; - } - - if (video->ureq[i].req_buffer) { - kfree(video->ureq[i].req_buffer); - video->ureq[i].req_buffer = NULL; - } - } - - kfree(video->ureq); - video->ureq = NULL; - } + list_for_each_entry_safe(ureq, temp, &video->ureqs, list) + uvc_video_free_request(ureq, video->ep); + INIT_LIST_HEAD(&video->ureqs); INIT_LIST_HEAD(&video->req_free); video->req_size = 0; return 0; @@ -322,39 +325,45 @@ uvc_video_free_requests(struct uvc_video *video) static int uvc_video_alloc_requests(struct uvc_video *video) { + struct uvc_request *ureq; unsigned int req_size; unsigned int i; int ret = -ENOMEM; BUG_ON(video->req_size); + BUG_ON(!list_empty(&video->ureqs)); req_size = video->ep->maxpacket * max_t(unsigned int, video->ep->maxburst, 1) * (video->ep->mult); - video->ureq = kcalloc(video->uvc_num_requests, sizeof(struct uvc_request), GFP_KERNEL); - if (video->ureq == NULL) - return -ENOMEM; + for (i = 0; i < video->uvc_num_requests; i++) { + ureq = kzalloc(sizeof(struct uvc_request), GFP_KERNEL); + if (ureq == NULL) + goto error; + + INIT_LIST_HEAD(&ureq->list); + + list_add_tail(&ureq->list, &video->ureqs); - for (i = 0; i < video->uvc_num_requests; ++i) { - video->ureq[i].req_buffer = kmalloc(req_size, GFP_KERNEL); - if (video->ureq[i].req_buffer == NULL) + ureq->req_buffer = kmalloc(req_size, GFP_KERNEL); + if (ureq->req_buffer == NULL) goto error; - video->ureq[i].req = usb_ep_alloc_request(video->ep, GFP_KERNEL); - if (video->ureq[i].req == NULL) + ureq->req = usb_ep_alloc_request(video->ep, GFP_KERNEL); + if (ureq->req == NULL) goto error; - video->ureq[i].req->buf = video->ureq[i].req_buffer; - video->ureq[i].req->length = 0; - video->ureq[i].req->complete = uvc_video_complete; - video->ureq[i].req->context = &video->ureq[i]; - video->ureq[i].video = video; - video->ureq[i].last_buf = NULL; + ureq->req->buf = ureq->req_buffer; + ureq->req->length = 0; + ureq->req->complete = uvc_video_complete; + ureq->req->context = ureq; + ureq->video = video; + ureq->last_buf = NULL; - list_add_tail(&video->ureq[i].req->list, &video->req_free); + list_add_tail(&ureq->req->list, &video->req_free); /* req_size/PAGE_SIZE + 1 for overruns and + 1 for header */ - sg_alloc_table(&video->ureq[i].sgt, + sg_alloc_table(&ureq->sgt, DIV_ROUND_UP(req_size - UVCG_REQUEST_HEADER_LEN, PAGE_SIZE) + 2, GFP_KERNEL); } @@ -489,8 +498,8 @@ static void uvcg_video_pump(struct work_struct *work) */ int uvcg_video_enable(struct uvc_video *video, int enable) { - unsigned int i; int ret; + struct uvc_request *ureq; if (video->ep == NULL) { uvcg_info(&video->uvc->func, @@ -502,9 +511,10 @@ int uvcg_video_enable(struct uvc_video *video, int enable) cancel_work_sync(&video->pump); uvcg_queue_cancel(&video->queue, 0); - for (i = 0; i < video->uvc_num_requests; ++i) - if (video->ureq && video->ureq[i].req) - usb_ep_dequeue(video->ep, video->ureq[i].req); + list_for_each_entry(ureq, &video->ureqs, list) { + if (ureq->req) + usb_ep_dequeue(video->ep, ureq->req); + } uvc_video_free_requests(video); uvcg_queue_enable(&video->queue, 0); @@ -536,6 +546,7 @@ int uvcg_video_enable(struct uvc_video *video, int enable) */ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) { + INIT_LIST_HEAD(&video->ureqs); INIT_LIST_HEAD(&video->req_free); spin_lock_init(&video->req_lock); INIT_WORK(&video->pump, uvcg_video_pump); From patchwork Fri Oct 27 20:19:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avichal Rakesh X-Patchwork-Id: 159148 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp862372vqb; Fri, 27 Oct 2023 13:20:54 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFrukz/5kaiR+PpPe7eP1lXVRnL3DBUKmvKExfdCyFWxkGgZ2il92Yt4F1JgCCObCAGJDR5 X-Received: by 2002:a25:d047:0:b0:da0:3b6c:fc22 with SMTP id h68-20020a25d047000000b00da03b6cfc22mr3715792ybg.31.1698438054566; Fri, 27 Oct 2023 13:20:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698438054; cv=none; d=google.com; s=arc-20160816; b=B5+714hVpF/bx+GtRNi/ZSy4xgBNVhrhyoPR5r1hb+XZLaUtq0Nqsi2r6Sa6tQ5lim YGfE77tILPRg3vXH2zGZmCrHttAp7Kg6OzLdhk4b/bKwHfTrfxOCh8A06og9By/3TLw7 AMeqm45PsyTE+pa5HNurapG1kWUJ8jb0I6znTmz3kvO2+UtHULi+jiL7zg4VMQyB5/fq IAZPnzuV39nHMy4Oyoqr4eLa/cIld3n+pTFqed833fPp1BwVhnZfHOZ2ygPHA7okPp4L UHTeXm3Rp1Sk4PbZ1Bp4ZMPq5Zx70HVFdEjw8IAdFB/z+pmRt/5eLnTeicub2s73+UlZ aelg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=hpZGNvK+8AimoR1c5B/6cfe/M0yZF2viXEDURopJcAk=; fh=p+LYTnSpNzrqEe7IwOmRmqfbsNd6xnlNPhpiE7PelQI=; b=cjaIs02a0ggG46Fb+sMAzIGq8a/xcEkJfyQirditaKZT8pV0DSRUelAWfGeOd0xFs5 mcnBj3cBO27/XCQRQgXbpwJKtHUAQx9mUbHbE8dUawxc07XoZuuJ72WBKGI/CnmtEsiu ZpGbAFPsrk/heJygSIZqv30sTvUt9oBe2ctVVwXgfBNC++SH6Ywgisl9B1xQXZQrbo6C sft8thjb+SM/W1p31ecwc+ylJYlAa78dc6yHoPdhfVrMkDuc4Mt58MLt5mfirIG9iDk2 OOOFNrUyu5lqXu4UWDQRplBOE3lVz6jUovIIRDM5rqMPVDmLfDN1OapZWF25+RuhTplr WJjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=ijtoTyfI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id j145-20020a25d297000000b00da07ec3f394si3618988ybg.635.2023.10.27.13.20.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 13:20:54 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b=ijtoTyfI; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 3674A834B100; Fri, 27 Oct 2023 13:20:51 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346420AbjJ0UUS (ORCPT + 27 others); Fri, 27 Oct 2023 16:20:18 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230451AbjJ0UUO (ORCPT ); Fri, 27 Oct 2023 16:20:14 -0400 Received: from mail-pg1-x54a.google.com (mail-pg1-x54a.google.com [IPv6:2607:f8b0:4864:20::54a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 805B81B5 for ; Fri, 27 Oct 2023 13:20:12 -0700 (PDT) Received: by mail-pg1-x54a.google.com with SMTP id 41be03b00d2f7-5b95ee4ae94so30861a12.0 for ; Fri, 27 Oct 2023 13:20:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698438012; x=1699042812; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=hpZGNvK+8AimoR1c5B/6cfe/M0yZF2viXEDURopJcAk=; b=ijtoTyfIfLp9OtCPostsmsmL/UMWXojbPow/DCb58u28QSAaE760iodJKGA0fc29VX rYhzENEmMht0UBc6Hz++1jorkpfI1XEh8UV7JPRCyBz692I1otqbcJI5L5W71ElWdOKb A83L+AT212XJTqil9VK298nZDJkPMBy74eZqL5HTfTRZXF+Z6O0LH53rDyOzlxPYmLoz W5iI9tceIOrIiFX/PPGOf2UUHnNfWtUNkhJk5aJu+RhbeGxGzwsXAj6vAHXYPWbjkxDP LYin4yVG83kBNuruAiVlu2XTv6MGrtKf1sukUHACr9KkTb8hLObK7QiYGdrVWL+o+u4L S2Ug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698438012; x=1699042812; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=hpZGNvK+8AimoR1c5B/6cfe/M0yZF2viXEDURopJcAk=; b=FaJqsv6T9DtpfCwfa22ZRDlDxi6BBIRngAJRFS67qMpWxXDUDVcpFukNpj0MEPk7hT mlwykGT1fUYOSalQm+ZZ8dvZNQYcBUopD3CVQMYCtuAGze2RosaJdZAiWTvZHIB+6YRh WNqiaABJsC68DEk/xcIMb8VhgbGr0Tj4mrKbnWXnkE2CM44zMU8BkKqVCAaZewD45NND kvzpFBrM0TpyBZN6k9pP0arhwGJ7w7nGrKBPPnpzKW1JYsBRa2mHdvFrJLhHWFrY5gm4 SRUVqSteRCWkO0sVM3jIS1fA0eEXF0saf4HoAXilRflE59CuWcOw6Dn2GWRS9UlRKH2x ypqw== X-Gm-Message-State: AOJu0YxN3D9exMiiaGW0pIpNYbdKPv9NOLB2VsjfSIZRbAXl7E/65nxN gb1qD4KCnLlUH+t6mFV5AD9tjpNonNJs X-Received: from hi-h2o-specialist.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:3cef]) (user=arakesh job=sendgmr) by 2002:a63:6d46:0:b0:589:91f7:c89 with SMTP id i67-20020a636d46000000b0058991f70c89mr68069pgc.12.1698438011926; Fri, 27 Oct 2023 13:20:11 -0700 (PDT) Date: Fri, 27 Oct 2023 13:19:58 -0700 In-Reply-To: <20231027201959.1869181-1-arakesh@google.com> Mime-Version: 1.0 References: <73309396-3856-43a2-9a6f-81a40ed594db@google.com> <20231027201959.1869181-1-arakesh@google.com> X-Mailer: git-send-email 2.42.0.820.g83a721a137-goog Message-ID: <20231027201959.1869181-3-arakesh@google.com> Subject: [PATCH v9 3/4] usb: gadget: uvc: move video disable logic to its own function From: Avichal Rakesh To: arakesh@google.com, dan.scally@ideasonboard.com Cc: etalvala@google.com, gregkh@linuxfoundation.org, jchowdhary@google.com, laurent.pinchart@ideasonboard.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, m.grzeschik@pengutronix.de X-Spam-Status: No, score=-5.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SORTED_RECIPS,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Fri, 27 Oct 2023 13:20:51 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780941381866226962 X-GMAIL-MSGID: 1780941381866226962 This patch refactors the video disable logic in uvcg_video_enable into its own separate function 'uvcg_video_disable'. This function is now used anywhere uvcg_video_enable(video, 0) was used. Reviewed-by: Daniel Scally Suggested-by: Michael Grzeschik Signed-off-by: Avichal Rakesh --- v6: Introduced this patch to make the next one easier to review v6 -> v7: Add Suggested-by v7 -> v8: No change. Getting back in review queue v8 -> v9: Call uvcg_video_disable directly instead of uvcg_video_enable(video, 0) drivers/usb/gadget/function/uvc_v4l2.c | 6 ++-- drivers/usb/gadget/function/uvc_video.c | 40 ++++++++++++++++--------- drivers/usb/gadget/function/uvc_video.h | 3 +- 3 files changed, 31 insertions(+), 18 deletions(-) -- 2.42.0.820.g83a721a137-goog diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 7cb8d027ff0c..904dd283cbf7 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -443,7 +443,7 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) return -EINVAL; /* Enable UVC video. */ - ret = uvcg_video_enable(video, 1); + ret = uvcg_video_enable(video); if (ret < 0) return ret; @@ -469,7 +469,7 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) return -EINVAL; uvc->state = UVC_STATE_CONNECTED; - ret = uvcg_video_enable(video, 0); + ret = uvcg_video_disable(video); if (ret < 0) return ret; @@ -515,7 +515,7 @@ static void uvc_v4l2_disable(struct uvc_device *uvc) if (uvc->state == UVC_STATE_STREAMING) uvc->state = UVC_STATE_CONNECTED; - uvcg_video_enable(&uvc->video, 0); + uvcg_video_disable(&uvc->video); uvcg_free_buffers(&uvc->video.queue); uvc->func_connected = false; wake_up_interruptible(&uvc->func_connected_queue); diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index f8f9209fee50..1081dd790fd6 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -494,31 +494,43 @@ static void uvcg_video_pump(struct work_struct *work) } /* - * Enable or disable the video stream. + * Disable the video stream */ -int uvcg_video_enable(struct uvc_video *video, int enable) +int +uvcg_video_disable(struct uvc_video *video) { - int ret; struct uvc_request *ureq; if (video->ep == NULL) { uvcg_info(&video->uvc->func, - "Video enable failed, device is uninitialized.\n"); + "Video disable failed, device is uninitialized.\n"); return -ENODEV; } - if (!enable) { - cancel_work_sync(&video->pump); - uvcg_queue_cancel(&video->queue, 0); + cancel_work_sync(&video->pump); + uvcg_queue_cancel(&video->queue, 0); - list_for_each_entry(ureq, &video->ureqs, list) { - if (ureq->req) - usb_ep_dequeue(video->ep, ureq->req); - } + list_for_each_entry(ureq, &video->ureqs, list) { + if (ureq->req) + usb_ep_dequeue(video->ep, ureq->req); + } - uvc_video_free_requests(video); - uvcg_queue_enable(&video->queue, 0); - return 0; + uvc_video_free_requests(video); + uvcg_queue_enable(&video->queue, 0); + return 0; +} + +/* + * Enable the video stream. + */ +int uvcg_video_enable(struct uvc_video *video) +{ + int ret; + + if (video->ep == NULL) { + uvcg_info(&video->uvc->func, + "Video enable failed, device is uninitialized.\n"); + return -ENODEV; } if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0) diff --git a/drivers/usb/gadget/function/uvc_video.h b/drivers/usb/gadget/function/uvc_video.h index 03adeefa343b..8ef6259741f1 100644 --- a/drivers/usb/gadget/function/uvc_video.h +++ b/drivers/usb/gadget/function/uvc_video.h @@ -14,7 +14,8 @@ struct uvc_video; -int uvcg_video_enable(struct uvc_video *video, int enable); +int uvcg_video_enable(struct uvc_video *video); +int uvcg_video_disable(struct uvc_video *video); int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc); From patchwork Fri Oct 27 20:19:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Avichal Rakesh X-Patchwork-Id: 159147 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:d641:0:b0:403:3b70:6f57 with SMTP id cy1csp862297vqb; Fri, 27 Oct 2023 13:20:46 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHyqX11Qee7fn5vFeM1umKzvLTAl39VSn7dRMuebc0rfKKtxXCfnxlrlKod61EBHAR+b0oG X-Received: by 2002:a05:6808:2024:b0:3a7:4509:ecc7 with SMTP id q36-20020a056808202400b003a74509ecc7mr4879462oiw.16.1698438046398; Fri, 27 Oct 2023 13:20:46 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1698438046; cv=none; d=google.com; s=arc-20160816; b=WllrGQFQptxFgdUEz86/d6QQeIpa8FmHnEjFZCzyggZADQrNMATXDgbUqN6kpw9BFT /SnBCi9RrxG1XHwLjLwLDrrT+LO/hQVwZjO5IkuQW5wcyUxXzCsq5j18U4aiCiol32mn gvn+jF068KHCtYNV6aZdTXb/px5MycN6eNfW6UMIBGzYA3RWr6Y4ieT5g2mZnN8PLaVj sL/WiGmmPZ5NRx/XoUazIwsxzNRmeUPW7TL0BZFhjJMneY3fxWdOYnTvz277rAw3Lrjz POVbg7QpWCgVvHZqPXAmRXUh3YRLfC64UWiMylgK57MsDlZpsKph4Ch59QqJPc04nFad CwOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:message-id:references :mime-version:in-reply-to:date:dkim-signature; bh=MY86achGTDpNgW4B8g3xuDMDu7MnnMgc9PXwE1CZLOM=; fh=p+LYTnSpNzrqEe7IwOmRmqfbsNd6xnlNPhpiE7PelQI=; b=EHuriZ7f8xtuhliLC6Yk+59+kHsyITAiC+ID6lB/tPlOVXCTg/Fd37gjgfFaGbvqLK M4KrclBrP9PNTKB4GLNAKovzjxXreguRENSRPBhWEVCMaHTdhYzUMu16+ZXcLbmyDQCH jsuVDOiqcW6J1+jOmhb5wnOQRqDe+2zK8dQOrcXJLEHxcFkByzMuA28TLRuYdghbRYtt kyTOxNgopCKmACOUSdABKDl+qSAOzPggedFfShbqmDT4bX5lhrV7FArrArdjoP2hj2yL Nv3fvz2/TplpszDI9lL0QL/LF/b2FXiUMh0BBYtw/lvPu/J22zLXX9T2xQFXOshQTs6V 5ihg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="ikvd/aSu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from fry.vger.email (fry.vger.email. [2620:137:e000::3:8]) by mx.google.com with ESMTPS id i126-20020a256d84000000b00da052e38ac7si3784926ybc.425.2023.10.27.13.20.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 27 Oct 2023 13:20:46 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) client-ip=2620:137:e000::3:8; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20230601 header.b="ikvd/aSu"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::3:8 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by fry.vger.email (Postfix) with ESMTP id 553DD834B11B; Fri, 27 Oct 2023 13:20:42 -0700 (PDT) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.10 at fry.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346434AbjJ0UUV (ORCPT + 27 others); Fri, 27 Oct 2023 16:20:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346419AbjJ0UUT (ORCPT ); Fri, 27 Oct 2023 16:20:19 -0400 Received: from mail-pg1-x549.google.com (mail-pg1-x549.google.com [IPv6:2607:f8b0:4864:20::549]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7F78F1B5 for ; Fri, 27 Oct 2023 13:20:15 -0700 (PDT) Received: by mail-pg1-x549.google.com with SMTP id 41be03b00d2f7-5b87150242cso2137228a12.0 for ; Fri, 27 Oct 2023 13:20:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1698438015; x=1699042815; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=MY86achGTDpNgW4B8g3xuDMDu7MnnMgc9PXwE1CZLOM=; b=ikvd/aSul5XtUqulDGPvr83TG28RMjysiWUVryeyfAZogZUb3RhOQ7TxBgAUqNaG2J kSnz+kqiZVFBIb4MSMFV8KYQ2rxvcxok+dR7JorYbMh9JB0h/BWgqkBPtH9h6zWVJtsM //mLYVDzdnYZYOb0OoT2OVW0wSG8EjgXGGJVP2zjNxaNLfynRyXq2c0kIM7zETd0rkj/ /fXb5ChPcH6KoYw6FtC0Ci/m6Kr8N7cy85gZZo9s191rLpyL1aVXVpX7ZlYiKd93Z5iU hCRFXNPeNTXkQ0RVMFyZdjlP/z/7zGx/woEBkMxWg4J2HjoZQ+gK8KRXexPLFL9KZDry FA3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698438015; x=1699042815; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=MY86achGTDpNgW4B8g3xuDMDu7MnnMgc9PXwE1CZLOM=; b=d5Sy+WZrMz+g3VwBn7jQnIFKha58coJnOFaoLyCo8/60ijLWFm/woqLqiC7+ky2OPw 6EJWLRpPH4ISgBWtjZc0rWWowCF/voaBAZn+W8tTEwKUkgJt9uZKVhteCaPpWWQ2qWLR EdLxgig8iscZIvgGMb369RxTfvIW3aXaa4RVXwTF32GGIVxjNLwtWQNL6Fp9F/wwLbfC eIfoRJiyHWUYNCLwXdYZouJ3bDuxu7rgcUGJBLIasGRlxe1Eg3ZT3rI+/6u4niW1d5AM L7xqPJgm04zXIKwF/Bn1R3A2Nn+UmmYlVXZH/UuTYPFvRZ8BfhSZMlrQHpKuGg4srAd/ SCqw== X-Gm-Message-State: AOJu0Yw5Ze1N4AIaWe0WFvVPZwRnlVw2DzI7T792sqjiTzqSRDg5GdIK jjyzti8exaRnnnByYn+lTu0Wi3P+mtXR X-Received: from hi-h2o-specialist.c.googlers.com ([fda3:e722:ac3:cc00:24:72f4:c0a8:3cef]) (user=arakesh job=sendgmr) by 2002:a63:7b13:0:b0:5ad:17a8:19b9 with SMTP id w19-20020a637b13000000b005ad17a819b9mr63642pgc.3.1698438014761; Fri, 27 Oct 2023 13:20:14 -0700 (PDT) Date: Fri, 27 Oct 2023 13:19:59 -0700 In-Reply-To: <20231027201959.1869181-1-arakesh@google.com> Mime-Version: 1.0 References: <73309396-3856-43a2-9a6f-81a40ed594db@google.com> <20231027201959.1869181-1-arakesh@google.com> X-Mailer: git-send-email 2.42.0.820.g83a721a137-goog Message-ID: <20231027201959.1869181-4-arakesh@google.com> Subject: [PATCH v9 4/4] usb: gadget: uvc: Fix use-after-free for inflight usb_requests From: Avichal Rakesh To: arakesh@google.com, dan.scally@ideasonboard.com Cc: etalvala@google.com, gregkh@linuxfoundation.org, jchowdhary@google.com, laurent.pinchart@ideasonboard.com, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, m.grzeschik@pengutronix.de X-Spam-Status: No, score=-5.9 required=5.0 tests=DKIMWL_WL_MED,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,SORTED_RECIPS,SPF_HELO_NONE,SPF_PASS, USER_IN_DEF_DKIM_WL autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on fry.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (fry.vger.email [0.0.0.0]); Fri, 27 Oct 2023 13:20:42 -0700 (PDT) X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780941373184978938 X-GMAIL-MSGID: 1780941373184978938 Currently, the uvc gadget driver allocates all uvc_requests as one array and deallocates them all when the video stream stops. This includes de-allocating all the usb_requests associated with those uvc_requests. This can lead to use-after-free issues if any of those de-allocated usb_requests were still owned by the usb controller. This is patch 2 of 2 in fixing the use-after-free issue. It adds a new flag to uvc_video to track when frames and requests should be flowing. When disabling the video stream, the flag is tripped and, instead of de-allocating all uvc_requests and usb_requests, the gadget driver only de-allocates those usb_requests that are currently owned by it (as present in req_free). Other usb_requests are left untouched until their completion handler is called which takes care of freeing the usb_request and its corresponding uvc_request. Now that uvc_video does not depends on uvc->state, this patch removes unnecessary upates to uvc->state that were made to accommodate uvc_video logic. This should ensure that uvc gadget driver never accidentally de-allocates a usb_request that it doesn't own. Link: https://lore.kernel.org/7cd81649-2795-45b6-8c10-b7df1055020d@google.com Suggested-by: Michael Grzeschik Reviewed-by: Michael Grzeschik Tested-by: Michael Grzeschik Signed-off-by: Avichal Rakesh --- v1 -> v2: Rebased to ToT, and fixed deadlock reported in https://lore.kernel.org/all/ZRv2UnKztgyqk2pt@pengutronix.de/ v2 -> v3: Fix email threading goof-up v3 -> v4: re-rebase to ToT & moved to a uvc_video level lock as discussed in https://lore.kernel.org/b14b296f-2e08-4edf-aeea-1c5b621e2d0c@google.com/ v4 -> v5: Address review comments. Add Reviewed-by & Tested-by. v5 -> v6: Added another patch before this one to make uvcg_video_disable easier to review. v6 -> v7: Fix warning reported in https://lore.kernel.org/202310200457.GwPPFuHX-lkp@intel.com/ v7 -> v8: No change. Getting back in review queue v8 -> v9: No change. drivers/usb/gadget/function/uvc.h | 1 + drivers/usb/gadget/function/uvc_v4l2.c | 12 +-- drivers/usb/gadget/function/uvc_video.c | 128 ++++++++++++++++++++---- 3 files changed, 111 insertions(+), 30 deletions(-) -- 2.42.0.820.g83a721a137-goog diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 993694da0bbc..be0d012aa244 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -102,6 +102,7 @@ struct uvc_video { unsigned int uvc_num_requests; /* Requests */ + bool is_enabled; /* tracks whether video stream is enabled */ unsigned int req_size; struct list_head ureqs; /* all uvc_requests allocated by uvc_video */ struct list_head req_free; diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c index 904dd283cbf7..2f8634e05612 100644 --- a/drivers/usb/gadget/function/uvc_v4l2.c +++ b/drivers/usb/gadget/function/uvc_v4l2.c @@ -451,8 +451,8 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) * Complete the alternate setting selection setup phase now that * userspace is ready to provide video frames. */ - uvc_function_setup_continue(uvc, 0); uvc->state = UVC_STATE_STREAMING; + uvc_function_setup_continue(uvc, 0); return 0; } @@ -468,11 +468,11 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) if (type != video->queue.queue.type) return -EINVAL; - uvc->state = UVC_STATE_CONNECTED; ret = uvcg_video_disable(video); if (ret < 0) return ret; + uvc->state = UVC_STATE_CONNECTED; uvc_function_setup_continue(uvc, 1); return 0; } @@ -507,14 +507,6 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, static void uvc_v4l2_disable(struct uvc_device *uvc) { uvc_function_disconnect(uvc); - /* - * Drop uvc->state to CONNECTED if it was streaming before. - * This ensures that the usb_requests are no longer queued - * to the controller. - */ - if (uvc->state == UVC_STATE_STREAMING) - uvc->state = UVC_STATE_CONNECTED; - uvcg_video_disable(&uvc->video); uvcg_free_buffers(&uvc->video.queue); uvc->func_connected = false; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 1081dd790fd6..8f330ce696ec 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -227,6 +227,9 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, * Request handling */ +/* + * Must be called with req_lock held as it modifies the list ureq is held in + */ static void uvc_video_free_request(struct uvc_request *ureq, struct usb_ep *ep) { @@ -271,9 +274,25 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) struct uvc_request *ureq = req->context; struct uvc_video *video = ureq->video; struct uvc_video_queue *queue = &video->queue; - struct uvc_device *uvc = video->uvc; + struct uvc_buffer *last_buf = NULL; unsigned long flags; + spin_lock_irqsave(&video->req_lock, flags); + if (!video->is_enabled) { + /* + * When is_enabled is false, uvc_video_disable ensures that + * in-flight uvc_buffers are returned, so we can safely + * call free_request without worrying about last_buf. + */ + uvc_video_free_request(ureq, ep); + spin_unlock_irqrestore(&video->req_lock, flags); + return; + } + + last_buf = ureq->last_buf; + ureq->last_buf = NULL; + spin_unlock_irqrestore(&video->req_lock, flags); + switch (req->status) { case 0: break; @@ -295,17 +314,26 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) uvcg_queue_cancel(queue, 0); } - if (ureq->last_buf) { - uvcg_complete_buffer(&video->queue, ureq->last_buf); - ureq->last_buf = NULL; + if (last_buf) { + spin_lock_irqsave(&queue->irqlock, flags); + uvcg_complete_buffer(&video->queue, last_buf); + spin_unlock_irqrestore(&queue->irqlock, flags); } spin_lock_irqsave(&video->req_lock, flags); - list_add_tail(&req->list, &video->req_free); - spin_unlock_irqrestore(&video->req_lock, flags); - - if (uvc->state == UVC_STATE_STREAMING) + /* + * Video stream might have been disabled while we were + * processing the current usb_request. So make sure + * we're still streaming before queueing the usb_request + * back to req_free + */ + if (video->is_enabled) { + list_add_tail(&req->list, &video->req_free); queue_work(video->async_wq, &video->pump); + } else { + uvc_video_free_request(ureq, ep); + } + spin_unlock_irqrestore(&video->req_lock, flags); } static int @@ -393,20 +421,22 @@ static void uvcg_video_pump(struct work_struct *work) struct uvc_video_queue *queue = &video->queue; /* video->max_payload_size is only set when using bulk transfer */ bool is_bulk = video->max_payload_size; - struct uvc_device *uvc = video->uvc; struct usb_request *req = NULL; struct uvc_buffer *buf; unsigned long flags; bool buf_done; int ret; - while (uvc->state == UVC_STATE_STREAMING && video->ep->enabled) { + while (true) { + if (!video->ep->enabled) + return; + /* - * Retrieve the first available USB request, protected by the - * request lock. + * Check is_enabled and retrieve the first available USB + * request, protected by the request lock. */ spin_lock_irqsave(&video->req_lock, flags); - if (list_empty(&video->req_free)) { + if (!video->is_enabled || list_empty(&video->req_free)) { spin_unlock_irqrestore(&video->req_lock, flags); return; } @@ -488,9 +518,11 @@ static void uvcg_video_pump(struct work_struct *work) return; spin_lock_irqsave(&video->req_lock, flags); - list_add_tail(&req->list, &video->req_free); + if (video->is_enabled) + list_add_tail(&req->list, &video->req_free); + else + uvc_video_free_request(req->context, video->ep); spin_unlock_irqrestore(&video->req_lock, flags); - return; } /* @@ -499,7 +531,11 @@ static void uvcg_video_pump(struct work_struct *work) int uvcg_video_disable(struct uvc_video *video) { - struct uvc_request *ureq; + unsigned long flags; + struct list_head inflight_bufs; + struct usb_request *req, *temp; + struct uvc_buffer *buf, *btemp; + struct uvc_request *ureq, *utemp; if (video->ep == NULL) { uvcg_info(&video->uvc->func, @@ -507,15 +543,58 @@ uvcg_video_disable(struct uvc_video *video) return -ENODEV; } + INIT_LIST_HEAD(&inflight_bufs); + spin_lock_irqsave(&video->req_lock, flags); + video->is_enabled = false; + + /* + * Remove any in-flight buffers from the uvc_requests + * because we want to return them before cancelling the + * queue. This ensures that we aren't stuck waiting for + * all complete callbacks to come through before disabling + * vb2 queue. + */ + list_for_each_entry(ureq, &video->ureqs, list) { + if (ureq->last_buf) { + list_add_tail(&ureq->last_buf->queue, &inflight_bufs); + ureq->last_buf = NULL; + } + } + spin_unlock_irqrestore(&video->req_lock, flags); + cancel_work_sync(&video->pump); uvcg_queue_cancel(&video->queue, 0); - list_for_each_entry(ureq, &video->ureqs, list) { - if (ureq->req) - usb_ep_dequeue(video->ep, ureq->req); + spin_lock_irqsave(&video->req_lock, flags); + /* + * Remove all uvc_reqeusts from ureqs with list_del_init + * This lets uvc_video_free_request correctly identify + * if the uvc_request is attached to a list or not when freeing + * memory. + */ + list_for_each_entry_safe(ureq, utemp, &video->ureqs, list) + list_del_init(&ureq->list); + + list_for_each_entry_safe(req, temp, &video->req_free, list) { + list_del(&req->list); + uvc_video_free_request(req->context, video->ep); } - uvc_video_free_requests(video); + INIT_LIST_HEAD(&video->ureqs); + INIT_LIST_HEAD(&video->req_free); + video->req_size = 0; + spin_unlock_irqrestore(&video->req_lock, flags); + + /* + * Return all the video buffers before disabling the queue. + */ + spin_lock_irqsave(&video->queue.irqlock, flags); + list_for_each_entry_safe(buf, btemp, &inflight_bufs, queue) { + list_del(&buf->queue); + uvcg_complete_buffer(&video->queue, buf); + } + spin_unlock_irqrestore(&video->queue.irqlock, flags); + uvcg_queue_enable(&video->queue, 0); return 0; } @@ -533,6 +612,14 @@ int uvcg_video_enable(struct uvc_video *video) return -ENODEV; } + /* + * Safe to access request related fields without req_lock because + * this is the only thread currently active, and no other + * request handling thread will become active until this function + * returns. + */ + video->is_enabled = true; + if ((ret = uvcg_queue_enable(&video->queue, 1)) < 0) return ret; @@ -558,6 +645,7 @@ int uvcg_video_enable(struct uvc_video *video) */ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc) { + video->is_enabled = false; INIT_LIST_HEAD(&video->ureqs); INIT_LIST_HEAD(&video->req_free); spin_lock_init(&video->req_lock);