Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp103456ybl; Thu, 22 Aug 2019 20:47:08 -0700 (PDT) X-Google-Smtp-Source: APXvYqzY8FmH+glS8TTLTwE+MyNeCjwS2vLhX+u4q/DUWAICRcWIdKC6rz8iN9uaf/FCUvQnVbjt X-Received: by 2002:a17:902:449:: with SMTP id 67mr2395813ple.105.1566532028063; Thu, 22 Aug 2019 20:47:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1566532028; cv=none; d=google.com; s=arc-20160816; b=THjuZdu1dW/2kQqab150YwoDaHpmEHG8dmxTI/5Afnsbesh5f6L8W6Pm81/IwCU/fk TOzPUEiyRqo4mZ5Yntcm8f2wZUK0xt7UIFGqnd6jf6wm/I1zjEKOp//0/hTl4UAyaxcC spcHX9UddHD+8Web8Qq9cnb3Lq5WI3f9II5he6wo/cYlbFdNvuOAdgdwenuU4FYLtaKV 0PlZ8nRUlc8O2cytnhFFxuHCjbSf9i1XGEOe/wjAryLYNiIWT1nFsz/uJwYyAxbH0Jwc LslY069bGIpeBldwTSHi4DftcuXiBq81/z1RtIJjRPQugL1xfjwqYo7/ey6mzT1YJRIg lBEw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=k4wbyo2lh5wS0iDeIRp+HW0mCti5DrYM/V93VRCbJMU=; b=NaVLNfovEMHPeSe1QXd/TGmcndpMj+pP0R7G7IwBAkPUkUUrdnnbyU7szk0ufdunBH 6eq5G2wQl5Gg6bebIohMUbwPpCbtB70Gcb5L+BRELEh3WYPchl5XfrRtnTdBrbwAhY8b eQjwdfvNq35pE07ucLr72Jj13JGxtc/iGjDS4IjnMtLC+XrcdLx4ODISGn7mNRCuoJCC wq1i71uu+Q3nDsOHOtlNFxSegtPgWuPM49qFyKllAJ8T92C+lOaAzerfqRkYFBlBxH3c L1GgG7SUfxKTqi6z1nwb5HOTdOSCg7pdzr15vIwvQq/cSIjQDeBjxHgLcSgYJDFBKMB/ r7BQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=vY9oS3IK; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f17si1261652plj.17.2019.08.22.20.46.53; Thu, 22 Aug 2019 20:47:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=vY9oS3IK; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2404355AbfHVRel (ORCPT + 99 others); Thu, 22 Aug 2019 13:34:41 -0400 Received: from mail.kernel.org ([198.145.29.99]:48536 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404366AbfHVRZS (ORCPT ); Thu, 22 Aug 2019 13:25:18 -0400 Received: from localhost (wsip-184-188-36-2.sd.sd.cox.net [184.188.36.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 60B9D23400; Thu, 22 Aug 2019 17:25:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1566494717; bh=s0ApEAcmL3TT3fBlquZB8oeVyf6DwCkBqIEm+2y66aM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vY9oS3IKk4jCw4J4vGHtvdIO0UbTwxRVZCd8CgD27YdDGvlLWipRfoXQFs27PCUuM MQcgZ8d3AejDYHcUUdPP0UdVWH9Lp2Q4RvGAgF/8KLk4j4GFx1hzm3QI/N7i+OQ5+j J2XyK5cpzYrJ1+jLS5SXk0Y8+8IwbgJOq6quk63U= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Alan Stern , syzbot+30cf45ebfe0b0c4847a1@syzkaller.appspotmail.com Subject: [PATCH 4.14 46/71] USB: core: Fix races in character device registration and deregistraion Date: Thu, 22 Aug 2019 10:19:21 -0700 Message-Id: <20190822171729.863177187@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190822171726.131957995@linuxfoundation.org> References: <20190822171726.131957995@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alan Stern commit 303911cfc5b95d33687d9046133ff184cf5043ff upstream. The syzbot fuzzer has found two (!) races in the USB character device registration and deregistration routines. This patch fixes the races. The first race results from the fact that usb_deregister_dev() sets usb_minors[intf->minor] to NULL before calling device_destroy() on the class device. This leaves a window during which another thread can allocate the same minor number but will encounter a duplicate name error when it tries to register its own class device. A typical error message in the system log would look like: sysfs: cannot create duplicate filename '/class/usbmisc/ldusb0' The patch fixes this race by destroying the class device first. The second race is in usb_register_dev(). When that routine runs, it first allocates a minor number, then drops minor_rwsem, and then creates the class device. If the device creation fails, the minor number is deallocated and the whole routine returns an error. But during the time while minor_rwsem was dropped, there is a window in which the minor number is allocated and so another thread can successfully open the device file. Typically this results in use-after-free errors or invalid accesses when the other thread closes its open file reference, because the kernel then tries to release resources that were already deallocated when usb_register_dev() failed. The patch fixes this race by keeping minor_rwsem locked throughout the entire routine. Reported-and-tested-by: syzbot+30cf45ebfe0b0c4847a1@syzkaller.appspotmail.com Signed-off-by: Alan Stern CC: Link: https://lore.kernel.org/r/Pine.LNX.4.44L0.1908121607590.1659-100000@iolanthe.rowland.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) --- a/drivers/usb/core/file.c +++ b/drivers/usb/core/file.c @@ -193,9 +193,10 @@ int usb_register_dev(struct usb_interfac intf->minor = minor; break; } - up_write(&minor_rwsem); - if (intf->minor < 0) + if (intf->minor < 0) { + up_write(&minor_rwsem); return -EXFULL; + } /* create a usb class device for this usb interface */ snprintf(name, sizeof(name), class_driver->name, minor - minor_base); @@ -203,12 +204,11 @@ int usb_register_dev(struct usb_interfac MKDEV(USB_MAJOR, minor), class_driver, "%s", kbasename(name)); if (IS_ERR(intf->usb_dev)) { - down_write(&minor_rwsem); usb_minors[minor] = NULL; intf->minor = -1; - up_write(&minor_rwsem); retval = PTR_ERR(intf->usb_dev); } + up_write(&minor_rwsem); return retval; } EXPORT_SYMBOL_GPL(usb_register_dev); @@ -234,12 +234,12 @@ void usb_deregister_dev(struct usb_inter return; dev_dbg(&intf->dev, "removing %d minor\n", intf->minor); + device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); down_write(&minor_rwsem); usb_minors[intf->minor] = NULL; up_write(&minor_rwsem); - device_destroy(usb_class->class, MKDEV(USB_MAJOR, intf->minor)); intf->usb_dev = NULL; intf->minor = -1; destroy_usb_class();