From nobody Sat Sep 26 07:15:41 2026 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.223.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48AF344A3F9; Thu, 3 Sep 2026 16:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; cv=none; b=DIxsM5H2cn6YC08/tSkPYojZvq7sz+sVMXe2ldcy77gr9OAXgW/9zEsrMuWT/STj7t4d9zgOBs4KSf3rOaJQt/OiilmRG8EGv1xwIusR+/8PPKCJ/ddoxBu3lai32ReMdDqk/mMDzYpdM2YUqT/QslawrvPJ+caw99+7UGbgL7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; c=relaxed/simple; bh=17RZR2ZTMt59sbwE6Mx8M/WpENZsr6g+2QL+Zhn3GOM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AnrGrEsW07+hbAgzPXiCH14seZN13RiT1WfT2nhcWA0OCvFveLiDt/jkp0x5XmaR0D8OF9Byyl84sIsaqtLPcmumwfyaD3eri0YrOd8crvvb/J72k4gfLAGhaMfgeipAOwRTWOJ79UrDLgvdZNVowE1heXRxYI8HlWPAVevFCfw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=RKeubK/D; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=97CXDKZT; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=oRtIfLCl; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=3yXVa0Ro; arc=none smtp.client-ip=195.135.223.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="RKeubK/D"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="97CXDKZT"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="oRtIfLCl"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="3yXVa0Ro" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id D84AF1FAC5; Thu, 3 Sep 2026 16:05:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DpFSt+M0gpbm3frk/kVuPHJG1gAoCphQnHc2kyplzUU=; b=RKeubK/DnJ4KIaWzkHLFYF73WgVMis7ejEXObz94cgqALbI5dfZYDM/IIwP4aOun4jeotI gDd5YwBW1AGyR5U7vBNfnV7NcIMU/WOdXJNjevf0wKXilZlzav8+WqQtAZPvbpd42Jyyju nlEB5tB02kAOs6ngqD+riHTbekT1ckc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DpFSt+M0gpbm3frk/kVuPHJG1gAoCphQnHc2kyplzUU=; b=97CXDKZTpFxoYDxw2zRln4pC5/LboXleYY37xS1Z4VDmnGvIcd1UzqugWehy5mSZ2p0ro4 I/ewDv1rVJENreBQ== Authentication-Results: smtp-out2.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=oRtIfLCl; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=3yXVa0Ro DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451500; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DpFSt+M0gpbm3frk/kVuPHJG1gAoCphQnHc2kyplzUU=; b=oRtIfLCl4Q6thfoxg/dR7db2wXySUdP4ieSeuSLdXdjjzZu0bOIMUr+H/vX6bNiXVD0zAE vWZdvEoizWghNm7Nl+bse9D30r6ey19FYz9yDVW+PYy+ECHrHCUWhQxgsl55JNGBcpc3n/ npYPPHMZykoWemTsRgDncmU1DgcBfqE= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451500; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=DpFSt+M0gpbm3frk/kVuPHJG1gAoCphQnHc2kyplzUU=; b=3yXVa0RowgGbyFymZb3hOvPe0/xVoAPOa+x1N9YAKVtcoxL6TG6ToR4cE0e53n1ldE4AHm xjkV18WX88+M0qCg== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id 96278136E6; Thu, 3 Sep 2026 16:05:00 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id eIN3I6yamWo2dQAAD6G6ig (envelope-from ); Thu, 03 Sep 2026 16:05:00 +0000 From: Takashi Iwai To: linux-sound@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Michal Pecio Subject: [PATCH v2 1/3] ALSA: usb: ua101: Avoid embedded URBs Date: Thu, 3 Sep 2026 18:04:37 +0200 Message-ID: <20260903160458.1938392-2-tiwai@suse.de> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903160458.1938392-1-tiwai@suse.de> References: <20260903160458.1938392-1-tiwai@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -3.01 X-Rspamd-Queue-Id: D84AF1FAC5 X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_CC(0.00)[vger.kernel.org,gmail.com]; RCVD_TLS_ALL(0.00)[]; DKIM_TRACE(0.00)[suse.de:+]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; FROM_HAS_DN(0.00)[]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns,suse.de:dkim,suse.de:email,suse.de:mid]; TAGGED_RCPT(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received]; RCPT_COUNT_THREE(0.00)[3]; RCVD_VIA_SMTP_AUTH(0.00)[]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO Content-Type: text/plain; charset="utf-8" UA101 driver uses URBs embedded in struct ua101, and this is basically a buggy implementation nowadays; since a URB is managed with a refcount, this may lead to a UAF when the URB is released asynchronously. For addressing the problem, this patch converts the embedded URBs to ones that are properly allocated via usb_alloc_urb(). The iso_frame_desc[] is gone, as it's allocated together by usb_alloc_urb(). Along with the dynamic allocation of each URB, the ua101.urbs[] becomes a static array of struct ua101_urb, and struct ua101_urb contains the pointer to struct ua101. Those are needed to handle the ready_list linked list in the complete callback. No functional changes, only compile-tested. Link: https://lore.kernel.org/20260903130757.0668310a.michal.pecio@gmail.com Signed-off-by: Takashi Iwai --- sound/usb/misc/ua101.c | 102 ++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c index b9a62e94e06c..860a62a3d74b 100644 --- a/sound/usb/misc/ua101.c +++ b/sound/usb/misc/ua101.c @@ -109,10 +109,10 @@ struct ua101 { unsigned int buffer_pos; unsigned int queue_length; struct ua101_urb { - struct urb urb; - struct usb_iso_packet_descriptor iso_frame_desc[1]; + struct urb *urb; struct list_head ready_list; - } *urbs[MAX_QUEUE_LENGTH]; + struct ua101 *ua; + } urbs[MAX_QUEUE_LENGTH]; struct { unsigned int size; void *addr; @@ -167,15 +167,15 @@ static void abort_usb_playback(struct ua101 *ua) wake_up(&ua->alsa_playback_wait); } =20 -static void playback_urb_complete(struct urb *usb_urb) +static void playback_urb_complete(struct urb *urb) { - struct ua101_urb *urb =3D (struct ua101_urb *)usb_urb; - struct ua101 *ua =3D urb->urb.context; + struct ua101_urb *ua_urb =3D urb->context; + struct ua101 *ua =3D ua_urb->ua; =20 - if (unlikely(urb->urb.status =3D=3D -ENOENT || /* unlinked */ - urb->urb.status =3D=3D -ENODEV || /* device removed */ - urb->urb.status =3D=3D -ECONNRESET || /* unlinked */ - urb->urb.status =3D=3D -ESHUTDOWN)) { /* device disabled */ + if (unlikely(urb->status =3D=3D -ENOENT || /* unlinked */ + urb->status =3D=3D -ENODEV || /* device removed */ + urb->status =3D=3D -ECONNRESET || /* unlinked */ + urb->status =3D=3D -ESHUTDOWN)) { /* device disabled */ abort_usb_playback(ua); abort_alsa_playback(ua); return; @@ -184,18 +184,19 @@ static void playback_urb_complete(struct urb *usb_urb) if (test_bit(USB_PLAYBACK_RUNNING, &ua->states)) { /* append URB to FIFO */ guard(spinlock_irqsave)(&ua->lock); - list_add_tail(&urb->ready_list, &ua->ready_playback_urbs); + list_add_tail(&ua_urb->ready_list, &ua->ready_playback_urbs); if (ua->rate_feedback_count > 0) queue_work(system_highpri_wq, &ua->playback_work); ua->playback.substream->runtime->delay -=3D - urb->urb.iso_frame_desc[0].length / + urb->iso_frame_desc[0].length / ua->playback.frame_bytes; } } =20 static void first_playback_urb_complete(struct urb *urb) { - struct ua101 *ua =3D urb->context; + struct ua101_urb *ua_urb =3D urb->context; + struct ua101 *ua =3D ua_urb->ua; =20 urb->complete =3D playback_urb_complete; playback_urb_complete(urb); @@ -248,7 +249,8 @@ static void playback_work(struct work_struct *work) { struct ua101 *ua =3D container_of(work, struct ua101, playback_work); unsigned int frames; - struct ua101_urb *urb; + struct ua101_urb *ua_urb; + struct urb *urb; bool do_period_elapsed =3D false; int err; =20 @@ -275,23 +277,24 @@ static void playback_work(struct work_struct *work) ua->rate_feedback_count--; =20 /* take URB out of FIFO */ - urb =3D list_first_entry(&ua->ready_playback_urbs, - struct ua101_urb, ready_list); - list_del(&urb->ready_list); + ua_urb =3D list_first_entry(&ua->ready_playback_urbs, + struct ua101_urb, ready_list); + list_del(&ua_urb->ready_list); + urb =3D ua_urb->urb; =20 /* fill packet with data or silence */ - urb->urb.iso_frame_desc[0].length =3D + urb->iso_frame_desc[0].length =3D frames * ua->playback.frame_bytes; if (test_bit(ALSA_PLAYBACK_RUNNING, &ua->states)) do_period_elapsed |=3D copy_playback_data(&ua->playback, - &urb->urb, + urb, frames); else - memset(urb->urb.transfer_buffer, 0, - urb->urb.iso_frame_desc[0].length); + memset(urb->transfer_buffer, 0, + urb->iso_frame_desc[0].length); =20 /* and off you go ... */ - err =3D usb_submit_urb(&urb->urb, GFP_ATOMIC); + err =3D usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(err < 0)) { abort_usb_playback(ua); abort_alsa_playback(ua); @@ -342,7 +345,8 @@ static bool copy_capture_data(struct ua101_stream *stre= am, struct urb *urb, =20 static void capture_urb_complete(struct urb *urb) { - struct ua101 *ua =3D urb->context; + struct ua101_urb *ua_urb =3D urb->context; + struct ua101 *ua =3D ua_urb->ua; struct ua101_stream *stream =3D &ua->capture; unsigned int frames, write_ptr; bool do_period_elapsed; @@ -413,7 +417,8 @@ static void capture_urb_complete(struct urb *urb) =20 static void first_capture_urb_complete(struct urb *urb) { - struct ua101 *ua =3D urb->context; + struct ua101_urb *ua_urb =3D urb->context; + struct ua101 *ua =3D ua_urb->ua; =20 urb->complete =3D capture_urb_complete; capture_urb_complete(urb); @@ -427,7 +432,7 @@ static int submit_stream_urbs(struct ua101 *ua, struct = ua101_stream *stream) unsigned int i; =20 for (i =3D 0; i < stream->queue_length; ++i) { - int err =3D usb_submit_urb(&stream->urbs[i]->urb, GFP_KERNEL); + int err =3D usb_submit_urb(stream->urbs[i].urb, GFP_KERNEL); if (err < 0) { dev_err(&ua->dev->dev, "USB request error %d: %s\n", err, usb_error_string(err)); @@ -442,8 +447,8 @@ static void kill_stream_urbs(struct ua101_stream *strea= m) unsigned int i; =20 for (i =3D 0; i < stream->queue_length; ++i) - if (stream->urbs[i]) - usb_kill_urb(&stream->urbs[i]->urb); + if (stream->urbs[i].urb) + usb_kill_urb(stream->urbs[i].urb); } =20 static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index) @@ -508,7 +513,7 @@ static int start_usb_capture(struct ua101 *ua) return err; =20 clear_bit(CAPTURE_URB_COMPLETED, &ua->states); - ua->capture.urbs[0]->urb.complete =3D first_capture_urb_complete; + ua->capture.urbs[0].urb->complete =3D first_capture_urb_complete; ua->rate_feedback_start =3D 0; ua->rate_feedback_count =3D 0; =20 @@ -550,7 +555,7 @@ static int start_usb_playback(struct ua101 *ua) return err; =20 clear_bit(PLAYBACK_URB_COMPLETED, &ua->states); - ua->playback.urbs[0]->urb.complete =3D + ua->playback.urbs[0].urb->complete =3D first_playback_urb_complete; scoped_guard(spinlock_irq, &ua->lock) { INIT_LIST_HEAD(&ua->ready_playback_urbs); @@ -580,7 +585,7 @@ static int start_usb_playback(struct ua101 *ua) add_with_wraparound(ua, &ua->rate_feedback_start, 1); ua->rate_feedback_count--; } - urb =3D &ua->playback.urbs[i]->urb; + urb =3D ua->playback.urbs[i].urb; urb->iso_frame_desc[0].length =3D frames * ua->playback.frame_bytes; memset(urb->transfer_buffer, 0, @@ -1059,7 +1064,7 @@ static int alloc_stream_urbs(struct ua101 *ua, struct= ua101_stream *stream, void (*urb_complete)(struct urb *)) { unsigned max_packet_size =3D stream->max_packet_bytes; - struct ua101_urb *urb; + struct urb *urb; unsigned int b, u =3D 0; =20 for (b =3D 0; b < ARRAY_SIZE(stream->buffers); ++b) { @@ -1070,23 +1075,24 @@ static int alloc_stream_urbs(struct ua101 *ua, stru= ct ua101_stream *stream, while (size >=3D max_packet_size) { if (u >=3D stream->queue_length) goto bufsize_error; - urb =3D kmalloc_obj(*urb); + urb =3D usb_alloc_urb(1, GFP_KERNEL); if (!urb) return -ENOMEM; - usb_init_urb(&urb->urb); - urb->urb.dev =3D ua->dev; - urb->urb.pipe =3D stream->usb_pipe; - urb->urb.transfer_flags =3D URB_NO_TRANSFER_DMA_MAP; - urb->urb.transfer_buffer =3D addr; - urb->urb.transfer_dma =3D dma; - urb->urb.transfer_buffer_length =3D max_packet_size; - urb->urb.number_of_packets =3D 1; - urb->urb.interval =3D 1; - urb->urb.context =3D ua; - urb->urb.complete =3D urb_complete; - urb->urb.iso_frame_desc[0].offset =3D 0; - urb->urb.iso_frame_desc[0].length =3D max_packet_size; - stream->urbs[u++] =3D urb; + urb->dev =3D ua->dev; + urb->pipe =3D stream->usb_pipe; + urb->transfer_flags =3D URB_NO_TRANSFER_DMA_MAP; + urb->transfer_buffer =3D addr; + urb->transfer_dma =3D dma; + urb->transfer_buffer_length =3D max_packet_size; + urb->number_of_packets =3D 1; + urb->interval =3D 1; + urb->context =3D &stream->urbs[u]; + urb->complete =3D urb_complete; + urb->iso_frame_desc[0].offset =3D 0; + urb->iso_frame_desc[0].length =3D max_packet_size; + stream->urbs[u].ua =3D ua; + stream->urbs[u].urb =3D urb; + u++; size -=3D max_packet_size; addr +=3D max_packet_size; dma +=3D max_packet_size; @@ -1104,8 +1110,8 @@ static void free_stream_urbs(struct ua101_stream *str= eam) unsigned int i; =20 for (i =3D 0; i < stream->queue_length; ++i) { - kfree(stream->urbs[i]); - stream->urbs[i] =3D NULL; + usb_free_urb(stream->urbs[i].urb); + stream->urbs[i].urb =3D NULL; } } =20 --=20 2.55.0 From nobody Sat Sep 26 07:15:41 2026 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 628DC3806D2; Thu, 3 Sep 2026 16:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; cv=none; b=m9ZKedIMlOLaO03cQrS/ANqlXxxRtJfcCdmBhTWRefg/0xDLkWy9VPeihIDViQrZolS3n+iygcaRo4mxtQFt+ZYVfYcljVfUUa3hC/qOXheWNHR4co2MADuJmTKhEagxQ39frZ84sD51mZMRdwVHGcH95pAanwkKFOJAzr5Bp4s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; c=relaxed/simple; bh=LCw+wioHfEMflbDoNm2jee/VHPg6gaXQlxDgakjuaaU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Mknb4guMUn5jbyMmGSqMVI49qgr8ZdczYNLEEBLFRLgqDXAiQeqEzd7A2eV8aURpltG5vFHftvqpx77j1r2OPKGqggJQDGuhpX0+66FZmzalyTulvWfbvguYtmlO0qUqx97OQ9nyG4GZExjDZnxNs0za9W6yvjvjtgqG1Blw8mw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=p0e5WjCv; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=74JIz03J; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=DGhn9/Km; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=4EiYsBjG; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="p0e5WjCv"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="74JIz03J"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="DGhn9/Km"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="4EiYsBjG" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 3272A21F96; Thu, 3 Sep 2026 16:05:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mo4Kf8r9V3Se93h4wPj7DQauWWOEBF1zw3z/jmaN9v8=; b=p0e5WjCvVJSom47VNOVkaQyAO+LcsBsxq8Y20vJsYGhGeiREroTP+1YdVZotOkoO9+Bt6s /CLXjGFyU1E39CivQo9YRxsrvF4NxlyuT+QWYM/+UWwnZcq4D1xPYPMskvJYKBEAG1lKLT gPcevdYlQkPuElbM0X1pZs5P0z+XrLc= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mo4Kf8r9V3Se93h4wPj7DQauWWOEBF1zw3z/jmaN9v8=; b=74JIz03J1ctvjpb8J8qGMqlDVz6bzVwZiLJ/vpyKT/f/kjRlJ3TjzTrOlN217+GFTLY6EW cea3vPf4s+QB7fDQ== Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b="DGhn9/Km"; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=4EiYsBjG DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451501; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mo4Kf8r9V3Se93h4wPj7DQauWWOEBF1zw3z/jmaN9v8=; b=DGhn9/Km7Ll3uPd8ANAdi726wg3hQh9+O2s4CTQzcIBiz9cn5Ivv0JxenpTYi3uzAQGuji zrIKfjEArvVp7Aw4iSAtnNePqctdJ5LzYPtb2IpxNull3WC7PdflgeKa/k+3b4LzlkS+gG 2S9rD81wIO2pbv1cBMaWjLUJmMSFJPU= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451501; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Mo4Kf8r9V3Se93h4wPj7DQauWWOEBF1zw3z/jmaN9v8=; b=4EiYsBjGw0BNIDTO4aVUI2tC8nujW09suwUkNyMMIVh7qZOhjQLywqckZCSh5nWBS72qpE XefqO6HGNcBWioDA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id C2A1113736; Thu, 3 Sep 2026 16:05:00 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id 0DFcLqyamWo2dQAAD6G6ig (envelope-from ); Thu, 03 Sep 2026 16:05:00 +0000 From: Takashi Iwai To: linux-sound@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Michal Pecio Subject: [PATCH v2 2/3] ALSA: usb: hiface: Avoid embedded URBs Date: Thu, 3 Sep 2026 18:04:38 +0200 Message-ID: <20260903160458.1938392-3-tiwai@suse.de> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903160458.1938392-1-tiwai@suse.de> References: <20260903160458.1938392-1-tiwai@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -3.01 X-Rspamd-Queue-Id: 3272A21F96 X-Rspamd-Server: rspamd1.dmz-prg2.suse.org X-Spam-Level: X-Rspamd-Action: no action X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; NEURAL_HAM_LONG(-1.00)[-1.000]; MID_CONTAINS_FROM(1.00)[]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_CC(0.00)[vger.kernel.org,gmail.com]; RCVD_TLS_ALL(0.00)[]; DKIM_TRACE(0.00)[suse.de:+]; FROM_EQ_ENVFROM(0.00)[]; RCVD_COUNT_TWO(0.00)[2]; FROM_HAS_DN(0.00)[]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; DBL_BLOCKED_OPENRESOLVER(0.00)[suse.de:dkim,suse.de:email,suse.de:mid,imap1.dmz-prg2.suse.org:helo,imap1.dmz-prg2.suse.org:rdns]; TAGGED_RCPT(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received]; RCPT_COUNT_THREE(0.00)[3]; RCVD_VIA_SMTP_AUTH(0.00)[]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO Content-Type: text/plain; charset="utf-8" The hiface driver uses URBs embedded in struct pcm_urb, and this is basically a buggy implementation nowadays; since a URB is managed with a refcount, this may lead to a UAF when the URB is released asynchronously. For addressing the problem, this patch converts the embedded URBs to ones that are properly allocated via usb_alloc_urb(). The conversion is rather straightforward; pcm_urb.instance became a pointer, assigned/freed via usb_alloc_urb() and usb_free_urb(), and the call with this is corrected accordingly. Along with it, the resource release is done in the common destructor that is called from both at the error path and the disconnect. No functional changes, only compile-tested. Link: https://lore.kernel.org/20260903130757.0668310a.michal.pecio@gmail.com Signed-off-by: Takashi Iwai --- v1->v2: use a common destructor at error path and disconnect sound/usb/hiface/pcm.c | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/sound/usb/hiface/pcm.c b/sound/usb/hiface/pcm.c index cd1a4c871c5d..3157952e4c1d 100644 --- a/sound/usb/hiface/pcm.c +++ b/sound/usb/hiface/pcm.c @@ -24,7 +24,7 @@ struct pcm_urb { struct hiface_chip *chip; =20 - struct urb instance; + struct urb *instance; struct usb_anchor submitted; u8 *buffer; }; @@ -193,7 +193,7 @@ static void hiface_pcm_stream_stop(struct pcm_runtime *= rt) if (!time) usb_kill_anchored_urbs( &rt->out_urbs[i].submitted); - usb_kill_urb(&rt->out_urbs[i].instance); + usb_kill_urb(rt->out_urbs[i].instance); } =20 rt->stream_state =3D STREAM_DISABLED; @@ -215,9 +215,9 @@ static int hiface_pcm_stream_start(struct pcm_runtime *= rt) rt->stream_state =3D STREAM_STARTING; for (i =3D 0; i < PCM_N_URBS; i++) { memset(rt->out_urbs[i].buffer, 0, PCM_PACKET_SIZE); - usb_anchor_urb(&rt->out_urbs[i].instance, + usb_anchor_urb(rt->out_urbs[i].instance, &rt->out_urbs[i].submitted); - ret =3D usb_submit_urb(&rt->out_urbs[i].instance, + ret =3D usb_submit_urb(rt->out_urbs[i].instance, GFP_ATOMIC); if (ret) { hiface_pcm_stream_stop(rt); @@ -334,7 +334,7 @@ static void hiface_pcm_out_urb_handler(struct urb *usb_= urb) if (do_period_elapsed) snd_pcm_period_elapsed(sub->instance); =20 - ret =3D usb_submit_urb(&out_urb->instance, GFP_ATOMIC); + ret =3D usb_submit_urb(out_urb->instance, GFP_ATOMIC); if (ret < 0) goto out_fail; =20 @@ -492,16 +492,18 @@ static int hiface_pcm_init_urb(struct pcm_urb *urb, void (*handler)(struct urb *)) { urb->chip =3D chip; - usb_init_urb(&urb->instance); + urb->instance =3D usb_alloc_urb(0, GFP_KERNEL); + if (!urb->instance) + return -ENOMEM; =20 urb->buffer =3D kzalloc(PCM_PACKET_SIZE, GFP_KERNEL); if (!urb->buffer) return -ENOMEM; =20 - usb_fill_bulk_urb(&urb->instance, chip->dev, + usb_fill_bulk_urb(urb->instance, chip->dev, usb_sndbulkpipe(chip->dev, ep), (void *)urb->buffer, PCM_PACKET_SIZE, handler, urb); - if (usb_urb_ep_type_check(&urb->instance)) + if (usb_urb_ep_type_check(urb->instance)) return -EINVAL; init_usb_anchor(&urb->submitted); =20 @@ -520,24 +522,26 @@ void hiface_pcm_abort(struct hiface_chip *chip) } } =20 -static void hiface_pcm_destroy(struct hiface_chip *chip) +static void hiface_pcm_destroy(struct pcm_runtime *rt) { - struct pcm_runtime *rt =3D chip->pcm; int i; =20 - for (i =3D 0; i < PCM_N_URBS; i++) - kfree(rt->out_urbs[i].buffer); + if (!rt) + return; =20 - kfree(chip->pcm); - chip->pcm =3D NULL; + if (rt->chip) + rt->chip->pcm =3D NULL; + + for (i =3D 0; i < PCM_N_URBS; i++) { + usb_free_urb(rt->out_urbs[i].instance); + kfree(rt->out_urbs[i].buffer); + } + kfree(rt); } =20 static void hiface_pcm_free(struct snd_pcm *pcm) { - struct pcm_runtime *rt =3D pcm->private_data; - - if (rt) - hiface_pcm_destroy(rt->chip); + hiface_pcm_destroy(pcm->private_data); } =20 int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq) @@ -587,8 +591,6 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_= freq) return 0; =20 error: - for (i =3D 0; i < PCM_N_URBS; i++) - kfree(rt->out_urbs[i].buffer); - kfree(rt); + hiface_pcm_destroy(rt); return ret; } --=20 2.55.0 From nobody Sat Sep 26 07:15:41 2026 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.223.130]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7797149CF47; Thu, 3 Sep 2026 16:05:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.135.223.130 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; cv=none; b=LBDRKtCQ1z2M7uaEzVLRW6D1t6yuq0Jcr7zc5IyRj6rZmZQfN8ZWNWcLwJ/yRwPU/2vYNfmM02MDjQFiM3CU/YyfeucpdAbAB3Uk9T3ds5NdfDRaaXGVjcj4XMGU3cLrGvvyvHt4hbQI1tEIRx/b8P3hkOoFN9WSLTd7usczZfc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788451513; c=relaxed/simple; bh=unM4V85A2H8VqEifj9AgmdzgMZKvERyg4rW/Xp/SUEI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SSu2ATrVdDN2OlHK1Xxw9cBxuguzxZJvmgImO9iQrgYDADAGsT7TjlM5Dy8wp6zhU19VDIAUJX1jOb5LCEO33L61YPcsAMiA+SSNkmDJp2r2X+Jix0cKhUsw64pdLmvweIEI5N00B9B8C/wdP+Ok6yxS5HYySbnmXbJrJsSLqRY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de; spf=pass smtp.mailfrom=suse.de; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=Ii3WgA6T; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=gyggJq4T; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b=ht4Zq21C; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b=5HBkwZu6; arc=none smtp.client-ip=195.135.223.130 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=suse.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="Ii3WgA6T"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="gyggJq4T"; dkim=pass (1024-bit key) header.d=suse.de header.i=@suse.de header.b="ht4Zq21C"; dkim=permerror (0-bit key) header.d=suse.de header.i=@suse.de header.b="5HBkwZu6" Received: from imap1.dmz-prg2.suse.org (imap1.dmz-prg2.suse.org [IPv6:2a07:de40:b281:104:10:150:64:97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id 5868721FBF; Thu, 3 Sep 2026 16:05:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1ypIga7kRV5oC5FuU0wYWTCci6N08+7TB8tmWGwvgoo=; b=Ii3WgA6TT/dGDPq4dGd8y0itLnMr115EuCanRHKKMUDbWej1lEU5azfSYKCC3/BNreRv9w UJL8rfrIUgNRFIYSqDMr+0y/XUvy9WaQJ4doWKgSnwqkhljtHGF5hZQolxddAMos/zdHZu KK20nOb5Sgoj2YM3E9VtG00hYmnaz+8= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451505; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1ypIga7kRV5oC5FuU0wYWTCci6N08+7TB8tmWGwvgoo=; b=gyggJq4T3RBF+0iLGbCYuTxwvC5xApel7djLhjPSeXMFA4Fb5+Z5IQkY0Z39NgYfTJSECE TccZaRjdsfBshrAw== Authentication-Results: smtp-out1.suse.de; dkim=pass header.d=suse.de header.s=susede2_rsa header.b=ht4Zq21C; dkim=pass header.d=suse.de header.s=susede2_ed25519 header.b=5HBkwZu6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1788451501; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1ypIga7kRV5oC5FuU0wYWTCci6N08+7TB8tmWGwvgoo=; b=ht4Zq21CdQAt76uJHaWf+HDFrXSDbZWrqUn63C67uqv5hOUIYXrlpzRDgU1E7cqwpK9t/N Sz2aG4kblK0m/DClBM5YdO4fTHNE+fguzrodVSNzMFz9owBi2RX85kpBnA9ZpY/omN/gBp mSZXtlmXEvvRjMPV7eFvRmW5kLiFkB0= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1788451501; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1ypIga7kRV5oC5FuU0wYWTCci6N08+7TB8tmWGwvgoo=; b=5HBkwZu6g9k6k3LXmxDG+ywmSEPuwthkpmfDyYSomeGy8et19kyNazFkzZobIiQZgXNS0N GRhi4PZdV608aMBA== Received: from imap1.dmz-prg2.suse.org (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by imap1.dmz-prg2.suse.org (Postfix) with ESMTPS id EEBB613869; Thu, 3 Sep 2026 16:05:00 +0000 (UTC) Received: from dovecot-director2.suse.de ([2a07:de40:b281:106:10:150:64:167]) by imap1.dmz-prg2.suse.org with ESMTPSA id cEcZOayamWo2dQAAD6G6ig (envelope-from ); Thu, 03 Sep 2026 16:05:00 +0000 From: Takashi Iwai To: linux-sound@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Michal Pecio Subject: [PATCH v2 3/3] ALSA: usb: 6fire: Avoid embedded URBs Date: Thu, 3 Sep 2026 18:04:39 +0200 Message-ID: <20260903160458.1938392-4-tiwai@suse.de> X-Mailer: git-send-email 2.55.0 In-Reply-To: <20260903160458.1938392-1-tiwai@suse.de> References: <20260903160458.1938392-1-tiwai@suse.de> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Level: X-Rspamd-Action: no action X-Rspamd-Server: rspamd2.dmz-prg2.suse.org X-Rspamd-Queue-Id: 5868721FBF X-Spamd-Result: default: False [-3.01 / 50.00]; BAYES_HAM(-3.00)[100.00%]; MID_CONTAINS_FROM(1.00)[]; NEURAL_HAM_LONG(-1.00)[-1.000]; R_MISSING_CHARSET(0.50)[]; R_DKIM_ALLOW(-0.20)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; NEURAL_HAM_SHORT(-0.20)[-1.000]; MIME_GOOD(-0.10)[text/plain]; MX_GOOD(-0.01)[]; TO_MATCH_ENVRCPT_ALL(0.00)[]; DKIM_SIGNED(0.00)[suse.de:s=susede2_rsa,suse.de:s=susede2_ed25519]; ARC_NA(0.00)[]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:104:10:150:64:97:from]; TO_DN_SOME(0.00)[]; MIME_TRACE(0.00)[0:+]; FREEMAIL_CC(0.00)[vger.kernel.org,gmail.com]; RCVD_TLS_ALL(0.00)[]; DKIM_TRACE(0.00)[suse.de:+]; RCVD_COUNT_TWO(0.00)[2]; FROM_EQ_ENVFROM(0.00)[]; FROM_HAS_DN(0.00)[]; SPAMHAUS_XBL(0.00)[2a07:de40:b281:104:10:150:64:97:from]; DBL_BLOCKED_OPENRESOLVER(0.00)[imap1.dmz-prg2.suse.org:rdns,imap1.dmz-prg2.suse.org:helo,suse.de:dkim,suse.de:email,suse.de:mid]; TAGGED_RCPT(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[2a07:de40:b281:106:10:150:64:167:received]; RCPT_COUNT_THREE(0.00)[3]; RCVD_VIA_SMTP_AUTH(0.00)[]; FREEMAIL_ENVRCPT(0.00)[gmail.com] X-Spam-Flag: NO X-Spam-Score: -3.01 Content-Type: text/plain; charset="utf-8" The USB 6fire driver uses URBs embedded in different structs for PCM, MIDI and communication, and this is basically a buggy implementation nowadays; since a URB is managed with a refcount, this may lead to a UAF when the URB is released asynchronously. For addressing the problem, this patch converts those embedded URBs to ones that are properly allocated via usb_alloc_urb(). The pcm_urb.packets[] is gone, as it's allocated by usb_alloc_urb(), hence it's found in urb.iso_frame_desc[] instead. The conversions are rather straightforward; each embedded struct urb is changed to a pointer, and its callers are updated accordingly. The resource for those structs are released in the common destructor functions (usb6fire_comm_free(), etc), which are called at both the init error path and the disconnect. No functional changes, only compile-tested. Link: https://lore.kernel.org/20260903130757.0668310a.michal.pecio@gmail.com Signed-off-by: Takashi Iwai --- v1->v2: fix the incorrect conversion in usb6fire_pcm_in_urb_handler(); NULL checks in the destructor sound/usb/6fire/comm.c | 42 +++++++++----- sound/usb/6fire/comm.h | 2 +- sound/usb/6fire/midi.c | 43 +++++++++----- sound/usb/6fire/midi.h | 2 +- sound/usb/6fire/pcm.c | 128 ++++++++++++++++++++++++----------------- sound/usb/6fire/pcm.h | 5 +- 6 files changed, 136 insertions(+), 86 deletions(-) diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c index d3b7cab85699..510d310824e9 100644 --- a/sound/usb/6fire/comm.c +++ b/sound/usb/6fire/comm.c @@ -21,7 +21,6 @@ enum { static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *ur= b, u8 *buffer, void *context, void(*handler)(struct urb *urb)) { - usb_init_urb(urb); urb->transfer_buffer =3D buffer; urb->pipe =3D usb_sndintpipe(rt->chip->dev, COMM_EP); urb->complete =3D handler; @@ -142,6 +141,19 @@ static int usb6fire_comm_write16(struct comm_runtime *= rt, u8 request, return ret; } =20 +static void usb6fire_comm_free(struct comm_runtime *rt) +{ + if (!rt) + return; + + if (rt->chip) + rt->chip->comm =3D NULL; + + usb_free_urb(rt->receiver); + kfree(rt->receiver_buffer); + kfree(rt); +} + int usb6fire_comm_init(struct sfire_chip *chip) { struct comm_runtime *rt =3D kzalloc_obj(struct comm_runtime); @@ -153,14 +165,18 @@ int usb6fire_comm_init(struct sfire_chip *chip) =20 rt->receiver_buffer =3D kzalloc(COMM_RECEIVER_BUFSIZE, GFP_KERNEL); if (!rt->receiver_buffer) { - kfree(rt); - return -ENOMEM; + ret =3D -ENOMEM; + goto error; } =20 - urb =3D &rt->receiver; + urb =3D usb_alloc_urb(0, GFP_KERNEL); + if (!urb) { + ret =3D -ENOMEM; + goto error; + } + rt->receiver =3D urb; rt->serial =3D 1; rt->chip =3D chip; - usb_init_urb(urb); rt->init_urb =3D usb6fire_comm_init_urb; rt->write8 =3D usb6fire_comm_write8; rt->write16 =3D usb6fire_comm_write16; @@ -175,13 +191,15 @@ int usb6fire_comm_init(struct sfire_chip *chip) urb->interval =3D 1; ret =3D usb_submit_urb(urb, GFP_KERNEL); if (ret < 0) { - kfree(rt->receiver_buffer); - kfree(rt); dev_err(&chip->dev->dev, "cannot create comm data receiver."); - return ret; + goto error; } chip->comm =3D rt; return 0; + + error: + usb6fire_comm_free(rt); + return ret; } =20 void usb6fire_comm_abort(struct sfire_chip *chip) @@ -189,14 +207,10 @@ void usb6fire_comm_abort(struct sfire_chip *chip) struct comm_runtime *rt =3D chip->comm; =20 if (rt) - usb_poison_urb(&rt->receiver); + usb_poison_urb(rt->receiver); } =20 void usb6fire_comm_destroy(struct sfire_chip *chip) { - struct comm_runtime *rt =3D chip->comm; - - kfree(rt->receiver_buffer); - kfree(rt); - chip->comm =3D NULL; + usb6fire_comm_free(chip->comm); } diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h index 2447d7ecf179..89976f510f6c 100644 --- a/sound/usb/6fire/comm.h +++ b/sound/usb/6fire/comm.h @@ -19,7 +19,7 @@ enum /* settings for comm */ struct comm_runtime { struct sfire_chip *chip; =20 - struct urb receiver; + struct urb *receiver; u8 *receiver_buffer; =20 u8 serial; /* urb serial */ diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c index 6b0bb096f27a..279b449936e7 100644 --- a/sound/usb/6fire/midi.c +++ b/sound/usb/6fire/midi.c @@ -66,7 +66,7 @@ static void usb6fire_midi_out_trigger( struct snd_rawmidi_substream *alsa_sub, int up) { struct midi_runtime *rt =3D alsa_sub->rmidi->private_data; - struct urb *urb =3D &rt->out_urb; + struct urb *urb =3D rt->out_urb; __s8 ret; =20 guard(spinlock_irqsave)(&rt->out_lock); @@ -137,6 +137,19 @@ static const struct snd_rawmidi_ops in_ops =3D { .trigger =3D usb6fire_midi_in_trigger }; =20 +static void usb6fire_midi_free(struct midi_runtime *rt) +{ + if (!rt) + return; + + if (rt->chip) + rt->chip->midi =3D NULL; + + usb_free_urb(rt->out_urb); + kfree(rt->out_buffer); + kfree(rt); +} + int usb6fire_midi_init(struct sfire_chip *chip) { int ret; @@ -148,8 +161,14 @@ int usb6fire_midi_init(struct sfire_chip *chip) =20 rt->out_buffer =3D kzalloc(MIDI_BUFSIZE, GFP_KERNEL); if (!rt->out_buffer) { - kfree(rt); - return -ENOMEM; + ret =3D -ENOMEM; + goto error; + } + + rt->out_urb =3D usb_alloc_urb(0, GFP_KERNEL); + if (!rt->out_urb) { + ret =3D -ENOMEM; + goto error; } =20 rt->chip =3D chip; @@ -160,15 +179,13 @@ int usb6fire_midi_init(struct sfire_chip *chip) spin_lock_init(&rt->in_lock); spin_lock_init(&rt->out_lock); =20 - comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt, + comm_rt->init_urb(comm_rt, rt->out_urb, rt->out_buffer, rt, usb6fire_midi_out_handler); =20 ret =3D snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance); if (ret < 0) { - kfree(rt->out_buffer); - kfree(rt); dev_err(&chip->dev->dev, "unable to create midi.\n"); - return ret; + goto error; } rt->instance->private_data =3D rt; strscpy(rt->instance->name, "DMX6FireUSB MIDI"); @@ -182,6 +199,10 @@ int usb6fire_midi_init(struct sfire_chip *chip) =20 chip->midi =3D rt; return 0; + + error: + usb6fire_midi_free(rt); + return ret; } =20 void usb6fire_midi_abort(struct sfire_chip *chip) @@ -189,14 +210,10 @@ void usb6fire_midi_abort(struct sfire_chip *chip) struct midi_runtime *rt =3D chip->midi; =20 if (rt) - usb_poison_urb(&rt->out_urb); + usb_poison_urb(rt->out_urb); } =20 void usb6fire_midi_destroy(struct sfire_chip *chip) { - struct midi_runtime *rt =3D chip->midi; - - kfree(rt->out_buffer); - kfree(rt); - chip->midi =3D NULL; + usb6fire_midi_free(chip->midi); } diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h index 47640c845903..8716ab8a863a 100644 --- a/sound/usb/6fire/midi.h +++ b/sound/usb/6fire/midi.h @@ -22,7 +22,7 @@ struct midi_runtime { spinlock_t in_lock; spinlock_t out_lock; struct snd_rawmidi_substream *out; - struct urb out_urb; + struct urb *out_urb; u8 out_serial; /* serial number of out packet */ u8 *out_buffer; int buffer_offset; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index d2e274b731fe..21789db6657d 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -138,8 +138,8 @@ static void usb6fire_pcm_stream_stop(struct pcm_runtime= *rt) rt->stream_state =3D STREAM_STOPPING; =20 for (i =3D 0; i < PCM_N_URBS; i++) { - usb_kill_urb(&rt->in_urbs[i].instance); - usb_kill_urb(&rt->out_urbs[i].instance); + usb_kill_urb(rt->in_urbs[i].instance); + usb_kill_urb(rt->out_urbs[i].instance); } ctrl_rt->usb_streaming =3D false; ctrl_rt->update_streaming(ctrl_rt); @@ -161,13 +161,13 @@ static int usb6fire_pcm_stream_start(struct pcm_runti= me *rt) rt->stream_state =3D STREAM_STARTING; for (i =3D 0; i < PCM_N_URBS; i++) { for (k =3D 0; k < PCM_N_PACKETS_PER_URB; k++) { - packet =3D &rt->in_urbs[i].packets[k]; + packet =3D &rt->in_urbs[i].instance->iso_frame_desc[k]; packet->offset =3D k * rt->in_packet_size; packet->length =3D rt->in_packet_size; packet->actual_length =3D 0; packet->status =3D 0; } - ret =3D usb_submit_urb(&rt->in_urbs[i].instance, + ret =3D usb_submit_urb(rt->in_urbs[i].instance, GFP_ATOMIC); if (ret) { usb6fire_pcm_stream_stop(rt); @@ -197,6 +197,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *= sub, struct pcm_urb *urb) unsigned int total_length =3D 0; struct pcm_runtime *rt =3D snd_pcm_substream_chip(sub->instance); struct snd_pcm_runtime *alsa_rt =3D sub->instance->runtime; + struct usb_iso_packet_descriptor *isoc; u32 *src =3D NULL; u32 *dest =3D (u32 *) (alsa_rt->dma_area + sub->dma_off * (alsa_rt->frame_bits >> 3)); @@ -207,8 +208,9 @@ static void usb6fire_pcm_capture(struct pcm_substream *= sub, struct pcm_urb *urb) for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) { /* at least 4 header bytes for valid packet. * after that: 32 bits per sample for analog channels */ - if (urb->packets[i].actual_length > 4) - frame_count =3D (urb->packets[i].actual_length - 4) + isoc =3D &urb->instance->iso_frame_desc[i]; + if (isoc->actual_length > 4) + frame_count =3D (isoc->actual_length - 4) / (rt->in_n_analog << 2); else frame_count =3D 0; @@ -220,7 +222,7 @@ static void usb6fire_pcm_capture(struct pcm_substream *= sub, struct pcm_urb *urb) else return; src++; /* skip leading 4 bytes of every packet */ - total_length +=3D urb->packets[i].length; + total_length +=3D isoc->length; for (frame =3D 0; frame < frame_count; frame++) { memcpy(dest, src, bytes_per_frame); dest +=3D alsa_rt->channels; @@ -244,6 +246,7 @@ static void usb6fire_pcm_playback(struct pcm_substream = *sub, int frame_count; struct pcm_runtime *rt =3D snd_pcm_substream_chip(sub->instance); struct snd_pcm_runtime *alsa_rt =3D sub->instance->runtime; + struct usb_iso_packet_descriptor *isoc; u32 *src =3D (u32 *) (alsa_rt->dma_area + sub->dma_off * (alsa_rt->frame_bits >> 3)); u32 *src_end =3D (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size @@ -263,8 +266,9 @@ static void usb6fire_pcm_playback(struct pcm_substream = *sub, for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) { /* at least 4 header bytes for valid packet. * after that: 32 bits per sample for analog channels */ - if (urb->packets[i].length > 4) - frame_count =3D (urb->packets[i].length - 4) + isoc =3D &urb->instance->iso_frame_desc[i]; + if (isoc->length > 4) + frame_count =3D (isoc->length - 4) / (rt->out_n_analog << 2); else frame_count =3D 0; @@ -289,6 +293,7 @@ static void usb6fire_pcm_in_urb_handler(struct urb *usb= _urb) struct pcm_urb *out_urb =3D in_urb->peer; struct pcm_runtime *rt =3D in_urb->chip->pcm; struct pcm_substream *sub; + struct usb_iso_packet_descriptor *isoc_out, *isoc_in; bool period_elapsed; int total_length =3D 0; int frame_count; @@ -299,11 +304,13 @@ static void usb6fire_pcm_in_urb_handler(struct urb *u= sb_urb) =20 if (usb_urb->status || rt->panic || rt->stream_state =3D=3D STREAM_STOPPI= NG) return; - for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) - if (in_urb->packets[i].status) { + for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) { + isoc_in =3D &in_urb->instance->iso_frame_desc[i]; + if (isoc_in->status) { rt->panic =3D true; return; } + } =20 if (rt->stream_state =3D=3D STREAM_DISABLED) { dev_err(&rt->chip->dev->dev, @@ -328,12 +335,13 @@ static void usb6fire_pcm_in_urb_handler(struct urb *u= sb_urb) =20 /* setup out urb structure */ for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) { - out_urb->packets[i].offset =3D total_length; - out_urb->packets[i].length =3D (in_urb->packets[i].actual_length - - 4) / (rt->in_n_analog << 2) + isoc_out =3D &out_urb->instance->iso_frame_desc[i]; + isoc_in =3D &in_urb->instance->iso_frame_desc[i]; + isoc_out->offset =3D total_length; + isoc_out->length =3D (isoc_in->actual_length - 4) / (rt->in_n_analog << = 2) * (rt->out_n_analog << 2) + 4; - out_urb->packets[i].status =3D 0; - total_length +=3D out_urb->packets[i].length; + isoc_out->status =3D 0; + total_length +=3D isoc_out->length; } memset(out_urb->buffer, 0, total_length); =20 @@ -354,9 +362,10 @@ static void usb6fire_pcm_in_urb_handler(struct urb *us= b_urb) =20 /* setup the 4th byte of each sample (0x40 for analog channels) */ dest =3D out_urb->buffer; - for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) - if (out_urb->packets[i].length >=3D 4) { - frame_count =3D (out_urb->packets[i].length - 4) + for (i =3D 0; i < PCM_N_PACKETS_PER_URB; i++) { + isoc_out =3D &out_urb->instance->iso_frame_desc[i]; + if (isoc_out->length >=3D 4) { + frame_count =3D (isoc_out->length - 4) / (rt->out_n_analog << 2); *(dest++) =3D 0xaa; *(dest++) =3D 0xaa; @@ -370,8 +379,10 @@ static void usb6fire_pcm_in_urb_handler(struct urb *us= b_urb) *(dest++) =3D 0x40; } } - usb_submit_urb(&out_urb->instance, GFP_ATOMIC); - usb_submit_urb(&in_urb->instance, GFP_ATOMIC); + } + + usb_submit_urb(out_urb->instance, GFP_ATOMIC); + usb_submit_urb(in_urb->instance, GFP_ATOMIC); } =20 static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb) @@ -534,22 +545,25 @@ static const struct snd_pcm_ops pcm_ops =3D { .pointer =3D usb6fire_pcm_pointer, }; =20 -static void usb6fire_pcm_init_urb(struct pcm_urb *urb, - struct sfire_chip *chip, bool in, int ep, - void (*handler)(struct urb *)) +static int usb6fire_pcm_init_urb(struct pcm_urb *urb, + struct sfire_chip *chip, bool in, int ep, + void (*handler)(struct urb *)) { urb->chip =3D chip; - usb_init_urb(&urb->instance); - urb->instance.transfer_buffer =3D urb->buffer; - urb->instance.transfer_buffer_length =3D + urb->instance =3D usb_alloc_urb(PCM_N_PACKETS_PER_URB, GFP_KERNEL); + if (!urb->instance) + return -ENOMEM; + urb->instance->transfer_buffer =3D urb->buffer; + urb->instance->transfer_buffer_length =3D PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE; - urb->instance.dev =3D chip->dev; - urb->instance.pipe =3D in ? usb_rcvisocpipe(chip->dev, ep) + urb->instance->dev =3D chip->dev; + urb->instance->pipe =3D in ? usb_rcvisocpipe(chip->dev, ep) : usb_sndisocpipe(chip->dev, ep); - urb->instance.interval =3D 1; - urb->instance.complete =3D handler; - urb->instance.context =3D urb; - urb->instance.number_of_packets =3D PCM_N_PACKETS_PER_URB; + urb->instance->interval =3D 1; + urb->instance->complete =3D handler; + urb->instance->context =3D urb; + urb->instance->number_of_packets =3D PCM_N_PACKETS_PER_URB; + return 0; } =20 static int usb6fire_pcm_buffers_init(struct pcm_runtime *rt) @@ -571,14 +585,23 @@ static int usb6fire_pcm_buffers_init(struct pcm_runti= me *rt) return 0; } =20 -static void usb6fire_pcm_buffers_destroy(struct pcm_runtime *rt) +static void usb6fire_pcm_free(struct pcm_runtime *rt) { int i; =20 + if (!rt) + return; + + if (rt->chip) + rt->chip->pcm =3D NULL; + for (i =3D 0; i < PCM_N_URBS; i++) { + usb_free_urb(rt->out_urbs[i].instance); kfree(rt->out_urbs[i].buffer); + usb_free_urb(rt->in_urbs[i].instance); kfree(rt->in_urbs[i].buffer); } + kfree(rt); } =20 int usb6fire_pcm_init(struct sfire_chip *chip) @@ -593,11 +616,8 @@ int usb6fire_pcm_init(struct sfire_chip *chip) return -ENOMEM; =20 ret =3D usb6fire_pcm_buffers_init(rt); - if (ret) { - usb6fire_pcm_buffers_destroy(rt); - kfree(rt); - return ret; - } + if (ret) + goto error; =20 rt->chip =3D chip; rt->stream_state =3D STREAM_DISABLED; @@ -609,10 +629,14 @@ int usb6fire_pcm_init(struct sfire_chip *chip) spin_lock_init(&rt->capture.lock); =20 for (i =3D 0; i < PCM_N_URBS; i++) { - usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP, - usb6fire_pcm_in_urb_handler); - usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP, - usb6fire_pcm_out_urb_handler); + ret =3D usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP, + usb6fire_pcm_in_urb_handler); + if (ret < 0) + goto error; + ret =3D usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP, + usb6fire_pcm_out_urb_handler); + if (ret < 0) + goto error; =20 rt->in_urbs[i].peer =3D &rt->out_urbs[i]; rt->out_urbs[i].peer =3D &rt->in_urbs[i]; @@ -620,10 +644,8 @@ int usb6fire_pcm_init(struct sfire_chip *chip) =20 ret =3D snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm); if (ret < 0) { - usb6fire_pcm_buffers_destroy(rt); - kfree(rt); dev_err(&chip->dev->dev, "cannot create pcm instance.\n"); - return ret; + goto error; } =20 pcm->private_data =3D rt; @@ -636,6 +658,10 @@ int usb6fire_pcm_init(struct sfire_chip *chip) =20 chip->pcm =3D rt; return 0; + + error: + usb6fire_pcm_free(rt); + return ret; } =20 void usb6fire_pcm_abort(struct sfire_chip *chip) @@ -653,8 +679,8 @@ void usb6fire_pcm_abort(struct sfire_chip *chip) snd_pcm_stop_xrun(rt->capture.instance); =20 for (i =3D 0; i < PCM_N_URBS; i++) { - usb_poison_urb(&rt->in_urbs[i].instance); - usb_poison_urb(&rt->out_urbs[i].instance); + usb_poison_urb(rt->in_urbs[i].instance); + usb_poison_urb(rt->out_urbs[i].instance); } =20 } @@ -662,9 +688,5 @@ void usb6fire_pcm_abort(struct sfire_chip *chip) =20 void usb6fire_pcm_destroy(struct sfire_chip *chip) { - struct pcm_runtime *rt =3D chip->pcm; - - usb6fire_pcm_buffers_destroy(rt); - kfree(rt); - chip->pcm =3D NULL; + usb6fire_pcm_free(chip->pcm); } diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h index 5a092dfd69f5..b586fe220fd1 100644 --- a/sound/usb/6fire/pcm.h +++ b/sound/usb/6fire/pcm.h @@ -24,10 +24,7 @@ enum /* settings for pcm */ struct pcm_urb { struct sfire_chip *chip; =20 - /* BEGIN DO NOT SEPARATE */ - struct urb instance; - struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB]; - /* END DO NOT SEPARATE */ + struct urb *instance; u8 *buffer; =20 struct pcm_urb *peer; --=20 2.55.0