Received: by 2002:a6b:fb09:0:0:0:0:0 with SMTP id h9csp2905886iog; Mon, 27 Jun 2022 05:30:23 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sUK9lQuwzlFJtsVOh9AgjmSer28hjJClXVTOpfg9Tykjbyz+ViNpPcMFQVSiMSosHQovhZ X-Received: by 2002:aa7:d9c3:0:b0:435:bb08:9ada with SMTP id v3-20020aa7d9c3000000b00435bb089adamr16028545eds.171.1656333022889; Mon, 27 Jun 2022 05:30:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1656333022; cv=none; d=google.com; s=arc-20160816; b=O2qvrFVK1wHUrcCTG0JuJW05p4KNJTs/lg0Bh4BUWiSS7/41yiAneKm+0Z+TQr1bnf Pd5vIRzvKh3y+Y60l7e5eYDenAf2bYUCl3ABm77+AXX3ewHQyhDoWp2K++2Q/cHEwDZs L0usV9hFQ47CUzCzOaD7mHknUy3ZO+haZsjiAPyLNiGqHw8Txv4CtuvcY8RIOW8vCXqy Zk7Ueo0aUlG8C80ECRgDugF9VW81gRwEfSsp+mZFVHa7DR+H7d75R4nYyAvS9TvFa0t8 HCjJvn0E6OAboduQj62v1n1QDSyhlxab1XiOSMqTPHMKLoi7zyf5HpZeACrayJgrma0S 73BA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=B6Phz3xzDvrD+WTd/Nlt0KmRZOmdke4Z8cKqRhJMqB4=; b=VpQv5+2y+ousBlyIGuXPxYPmXED0SqaHSdpmK63hUImyQsAlzlAFBRfm90oBRoq60M NZox7DuLBSDpMWMH08U+RmC1hjT1nGfkEBxG+5TxO7xQlGWQNt8u8xQjR/nhFZjOJxu9 sXx/3Ciw/51A8hxMehOhWeG9u8dCRNWjYKyF6HVuaAkrNu9Xm79yuBMl5Aal/fWCO+dU 6aca5ZXdoBxqwTv0sok5F2F/64H4cxuDwlYSJKozLjTIzR4DziyZejl7ZKa6/WaIknv9 +/up7J4iJr/1AxAcAwbyTMd4wS1lj1iMKMXLS1vgqJUqd6Zz1lakxIqFzocD/z8k07wb oImA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xuPb19l4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id j20-20020a05640211d400b004355e62629fsi14426583edw.157.2022.06.27.05.29.58; Mon, 27 Jun 2022 05:30:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xuPb19l4; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239364AbiF0L5E (ORCPT + 99 others); Mon, 27 Jun 2022 07:57:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49948 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238147AbiF0Lu1 (ORCPT ); Mon, 27 Jun 2022 07:50:27 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 38F4110D9; Mon, 27 Jun 2022 04:43:30 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id C95C661192; Mon, 27 Jun 2022 11:43:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CC73BC3411D; Mon, 27 Jun 2022 11:43:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1656330209; bh=ZeZLL/oJitZEoiyARL1KO7IjtoeRu3fDu/1zE3CmHeM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xuPb19l4VfXIlcD/X3sL+TUptpZuXyA7mSFHbYJtqfp/gsTO5R5FuUU7SICNKWDdX noc3Eu3/yajfNdmZHWohO7GUpElbPK2vTsTWOYXQf5SCJ6OzhDPoXmmSZoVyC56Aqb jvEipcU6zi9Ju4obME591s2V0mqN4fQQbisDInNc= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Andrey Konovalov , Hillf Danton , Alan Stern , syzbot+02b16343704b3af1667e@syzkaller.appspotmail.com Subject: [PATCH 5.18 119/181] usb: gadget: Fix non-unique driver names in raw-gadget driver Date: Mon, 27 Jun 2022 13:21:32 +0200 Message-Id: <20220627111948.146279033@linuxfoundation.org> X-Mailer: git-send-email 2.36.1 In-Reply-To: <20220627111944.553492442@linuxfoundation.org> References: <20220627111944.553492442@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-7.5 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alan Stern commit f2d8c2606825317b77db1f9ba0fc26ef26160b30 upstream. In a report for a separate bug (which has already been fixed by commit 5f0b5f4d50fa "usb: gadget: fix race when gadget driver register via ioctl") in the raw-gadget driver, the syzbot console log included error messages caused by attempted registration of a new driver with the same name as an existing driver: > kobject_add_internal failed for raw-gadget with -EEXIST, don't try to register things with the same name in the same directory. > UDC core: USB Raw Gadget: driver registration failed: -17 > misc raw-gadget: fail, usb_gadget_register_driver returned -17 These errors arise because raw_gadget.c registers a separate UDC driver for each of the UDC instances it creates, but these drivers all have the same name: "raw-gadget". Until recently this wasn't a problem, but when the "gadget" bus was added and UDC drivers were registered on this bus, it became possible for name conflicts to cause the registrations to fail. The reason is simply that the bus code in the driver core uses the driver name as a sysfs directory name (e.g., /sys/bus/gadget/drivers/raw-gadget/), and you can't create two directories with the same pathname. To fix this problem, the driver names used by raw-gadget are made distinct by appending a unique ID number: "raw-gadget.N", with a different value of N for each driver instance. And to avoid the proliferation of error handling code in the raw_ioctl_init() routine, the error return paths are refactored into the common pattern (goto statements leading to cleanup code at the end of the routine). Link: https://lore.kernel.org/all/0000000000008c664105dffae2eb@google.com/ Fixes: fc274c1e9973 "USB: gadget: Add a new bus for gadgets" CC: Andrey Konovalov CC: Reported-and-tested-by: syzbot+02b16343704b3af1667e@syzkaller.appspotmail.com Reviewed-by: Andrey Konovalov Acked-by: Hillf Danton Signed-off-by: Alan Stern Link: https://lore.kernel.org/r/YqdG32w+3h8c1s7z@rowland.harvard.edu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/legacy/raw_gadget.c | 62 ++++++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 16 deletions(-) --- a/drivers/usb/gadget/legacy/raw_gadget.c +++ b/drivers/usb/gadget/legacy/raw_gadget.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,9 @@ MODULE_LICENSE("GPL"); /*----------------------------------------------------------------------*/ +static DEFINE_IDA(driver_id_numbers); +#define DRIVER_DRIVER_NAME_LENGTH_MAX 32 + #define RAW_EVENT_QUEUE_SIZE 16 struct raw_event_queue { @@ -161,6 +165,9 @@ struct raw_dev { /* Reference to misc device: */ struct device *dev; + /* Make driver names unique */ + int driver_id_number; + /* Protected by lock: */ enum dev_state state; bool gadget_registered; @@ -189,6 +196,7 @@ static struct raw_dev *dev_new(void) spin_lock_init(&dev->lock); init_completion(&dev->ep0_done); raw_event_queue_init(&dev->queue); + dev->driver_id_number = -1; return dev; } @@ -199,6 +207,9 @@ static void dev_free(struct kref *kref) kfree(dev->udc_name); kfree(dev->driver.udc_name); + kfree(dev->driver.driver.name); + if (dev->driver_id_number >= 0) + ida_free(&driver_id_numbers, dev->driver_id_number); if (dev->req) { if (dev->ep0_urb_queued) usb_ep_dequeue(dev->gadget->ep0, dev->req); @@ -422,6 +433,7 @@ static int raw_ioctl_init(struct raw_dev struct usb_raw_init arg; char *udc_driver_name; char *udc_device_name; + char *driver_driver_name; unsigned long flags; if (copy_from_user(&arg, (void __user *)value, sizeof(arg))) @@ -440,36 +452,44 @@ static int raw_ioctl_init(struct raw_dev return -EINVAL; } + ret = ida_alloc(&driver_id_numbers, GFP_KERNEL); + if (ret < 0) + return ret; + dev->driver_id_number = ret; + + driver_driver_name = kmalloc(DRIVER_DRIVER_NAME_LENGTH_MAX, GFP_KERNEL); + if (!driver_driver_name) { + ret = -ENOMEM; + goto out_free_driver_id_number; + } + snprintf(driver_driver_name, DRIVER_DRIVER_NAME_LENGTH_MAX, + DRIVER_NAME ".%d", dev->driver_id_number); + udc_driver_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); - if (!udc_driver_name) - return -ENOMEM; + if (!udc_driver_name) { + ret = -ENOMEM; + goto out_free_driver_driver_name; + } ret = strscpy(udc_driver_name, &arg.driver_name[0], UDC_NAME_LENGTH_MAX); - if (ret < 0) { - kfree(udc_driver_name); - return ret; - } + if (ret < 0) + goto out_free_udc_driver_name; ret = 0; udc_device_name = kmalloc(UDC_NAME_LENGTH_MAX, GFP_KERNEL); if (!udc_device_name) { - kfree(udc_driver_name); - return -ENOMEM; + ret = -ENOMEM; + goto out_free_udc_driver_name; } ret = strscpy(udc_device_name, &arg.device_name[0], UDC_NAME_LENGTH_MAX); - if (ret < 0) { - kfree(udc_driver_name); - kfree(udc_device_name); - return ret; - } + if (ret < 0) + goto out_free_udc_device_name; ret = 0; spin_lock_irqsave(&dev->lock, flags); if (dev->state != STATE_DEV_OPENED) { dev_dbg(dev->dev, "fail, device is not opened\n"); - kfree(udc_driver_name); - kfree(udc_device_name); ret = -EINVAL; goto out_unlock; } @@ -484,14 +504,24 @@ static int raw_ioctl_init(struct raw_dev dev->driver.suspend = gadget_suspend; dev->driver.resume = gadget_resume; dev->driver.reset = gadget_reset; - dev->driver.driver.name = DRIVER_NAME; + dev->driver.driver.name = driver_driver_name; dev->driver.udc_name = udc_device_name; dev->driver.match_existing_only = 1; dev->state = STATE_DEV_INITIALIZED; + spin_unlock_irqrestore(&dev->lock, flags); + return ret; out_unlock: spin_unlock_irqrestore(&dev->lock, flags); +out_free_udc_device_name: + kfree(udc_device_name); +out_free_udc_driver_name: + kfree(udc_driver_name); +out_free_driver_driver_name: + kfree(driver_driver_name); +out_free_driver_id_number: + ida_free(&driver_id_numbers, dev->driver_id_number); return ret; }