From nobody Sun May 24 18:41:32 2026 Received: from mail-lf1-f45.google.com (mail-lf1-f45.google.com [209.85.167.45]) (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 B0BAF31E84E for ; Sat, 23 May 2026 16:53:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779555234; cv=none; b=UQscRTMX9ejJqN8AubBdAujVUlTJ8paOtKs0/lrH7/KIFMVq1cqbqMmk+Dz8gGbMjfnc7q/tz5nZUBeDAA9+HDFUo17En2ugp0fmnJ9u4cGZkhn6/9/7F73u5vxigOVhO6emeCbev12cO/7aiQRFE8P7UQNSVdiaxWHNmtbwHXE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779555234; c=relaxed/simple; bh=DGZ1Iu78FNYWURpAerzc6calyIgHVwJu5yS0L/BzyJM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XVq/Utmq7ANGaCecFHf1MdsZIoe96fLyZjQuWkhI1Nx446Kh4EkF4b1tVBkBHbEPdUYglJ4qQx0+4gil277T82/V8hftkfudZuKeFiemYYHmWTxrvANuHiuWfsKUIfyyPIOuGJlUFzvwS9sDxPaDydUsgXflxSJuUyGxpa0VliE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=C+YanwQN; arc=none smtp.client-ip=209.85.167.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="C+YanwQN" Received: by mail-lf1-f45.google.com with SMTP id 2adb3069b0e04-5aa1b2327c8so10020481e87.0 for ; Sat, 23 May 2026 09:53:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779555231; x=1780160031; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=0KNiADcE9MK3Ayde/OGmbBhB9zN35/Oo61VBdFulAcM=; b=C+YanwQNeFjqTjMJVHH7bjIVzHMZD1nNjB8QWt8YPRHQk1KJ665xZcgEicBVbE4oan iJrMtHJNkWRbjR7r2bCjJU+DfwC4bSR08+/r4UoNZ0/xkQJKktVQkAJefEq94hUcsdve t2ooL3OdiXJW8j1DON+c0CEnv9AkRVFBls12wqqjo3GtOLNfx7cUf5IdNjqCCxgfZjjc 0uJLtvZ9mRXjamM94dJGpIqKRMXfoctw5/OSIJQErv5AWMD86chrbvvtwzgqqZurkrHp wGvzZBflWx/DUp61cmMVQF78k6IZsO384jDi3KTnQEn2ijOXjZGrchmPOiVDiTqD7x2S PHBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779555231; x=1780160031; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=0KNiADcE9MK3Ayde/OGmbBhB9zN35/Oo61VBdFulAcM=; b=hBfCxo1sdcWcCvde4mrpNpkB0gnPDGOOu/sraq0EKQGSsRYT48WVgfF8zXovLgmNe3 q3QTRQytvmk8YBLkfrxcHtmGQZqzDis1gL29OQUpUyxmKliN6+ieEPqNzIo0TCM43jIk /hTTDcDhvOvCl+PnUd3D9CYnuoFhFnG4gdK5PJ7TqCza8qMaSQyc+ghj/o1Q1OAVdfrp Jw7f7OIwsWQZzD9Ofyp1HUuLRf4gI6uEz869PgpdeWqn/XLTzpU7AHQg+sobyDzIJ/vJ jkEZbPe15j9+IWwOcAYazk+PiUXGhLhH2lkxUv4mN4PdArQpWa6QFIVd7bwUMnHmMDY6 R9dw== X-Forwarded-Encrypted: i=1; AFNElJ94EwEYIi3xptKIPq0z6aizgnlIwS2Zu1ISzrGbXeYgFUDkxmIt38zVYz3xK++AeteakLa+fABCNVY/b2M=@vger.kernel.org X-Gm-Message-State: AOJu0YxRHxTdfnT8yQIURrwzK/yt1pv5NLfbgURjmKyHqlEAVaeALeix 9lsrI9Ob1WMj1kRLwicT3orusgOCku8RJrQs5RGeSsmQn63zr6AmBf86 X-Gm-Gg: Acq92OElwtZnqJ2VoR3szY+4WrsjJq276PqTtyXZaSe5nFZwb4HzV0tl8/8yrb0yaeX vyUcim+bnPEyBiad5N5jNNEGE6QrrrxywCGWThzDcs+GkaIMhLuK7pmvkQaMp+w6GtdItADVFkt ZVZg8VDZ3qqCh626kJm9bDsd1J74aKsVWfsPK0nCDgbuO5TIViaHuQVAJNVVNoDQPYeBL0JzFyB aYrViY6UB+Yz6GWOe0ndfSXCBoTyXujop+oR7Hts+OdWqlpCwz+RDJWwVlfXmdOeOjer4pIdAvj GsDnSjmX2E7lU5KLj9uV9oYLrXZNrmAeBpibmV6VC9D4joIT40tjp+7njCkhmzG6bfBXNdT7iVO WauiHpNSkNTMFpdZGLjIyRMMzsvpawPLXGAlVZze8Y1jrtPK0STuE5xMaMYUibiKVFnB8GhFuW5 o1hPKLE75BBcfH80wJO65ans+5Q2frQpXVfm1FU9OPX9IFi2tCscIjpTQIYONOPPUumdSdEA== X-Received: by 2002:a05:6512:6399:20b0:5aa:2a4e:5b78 with SMTP id 2adb3069b0e04-5aa32326a7cmr1765641e87.17.1779555230628; Sat, 23 May 2026 09:53:50 -0700 (PDT) Received: from va-HP-Pavilion-Desktop-595-p0xxx.mshome.net ([193.0.150.248]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-5aa32cf96bfsm1267717e87.77.2026.05.23.09.53.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 23 May 2026 09:53:50 -0700 (PDT) From: Valery Borovsky To: mchehab@kernel.org Cc: hverkuil+cisco@kernel.org, linux-media@vger.kernel.org, stable@vger.kernel.org, linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org Subject: [PATCH v2] media: airspy: use vb2_video_unregister_device() on disconnect to fix NULL deref Date: Sat, 23 May 2026 19:53:49 +0300 Message-ID: <20260523165349.286212-1-vebohr@gmail.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: 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 Content-Type: text/plain; charset="utf-8" airspy_disconnect() clears s->udev under v4l2_lock, but airspy_stop_streaming() unconditionally calls airspy_ctrl_msg() and airspy_free_stream_bufs() afterwards. If a streaming user closes the device after disconnect, stop_streaming() runs and dereferences the NULL s->udev: airspy_stop_streaming() airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0) usb_sndctrlpipe(s->udev, 0) /* NULL deref */ airspy_free_stream_bufs(s) usb_free_coherent(s->udev, ...) /* NULL deref */ The airspy driver uses vb2_fop_release() in its file_operations, so replace video_unregister_device(&s->vdev) with vb2_video_unregister_device(&s->vdev) and move it before clearing s->udev. vb2_video_unregister_device() releases the vb2 queue, which synchronously runs airspy_stop_streaming() if streaming is active, so the URBs, coherent DMA stream buffers and the hardware stop control message all execute while s->udev is still valid. vb2_video_unregister_device() locks vdev->queue->lock (vb_queue_lock) internally, and stop_streaming() locks v4l2_lock, so the previous outer mutex_lock(&s->vb_queue_lock) / mutex_lock(&s->v4l2_lock) pair around the unregister sequence would self-deadlock and has been removed. A short v4l2_lock critical section around s->udev =3D NULL remains so any ioctl path that still holds the file descriptor sees coherent state. Issue identified by automated review of the INV-003 series at https://sashiko.dev/ Fixes: 634fe5033951 ("[media] airspy: AirSpy SDR driver") Cc: stable@vger.kernel.org Suggested-by: Hans Verkuil Signed-off-by: Valery Borovsky --- Changes since v1 (https://lore.kernel.org/linux-media/20260513052617.140688-1-vebohr@gmail.c= om/): - Rewritten per Hans Verkuil's review (https://lore.kernel.org/linux-media/f202c8ae-554f-49de-a9d1-add337e28515= @kernel.org/): fix the root cause in airspy_disconnect() by replacing video_unregister_device() with vb2_video_unregister_device() and moving it before clearing s->udev, instead of guarding the hardware teardown in airspy_stop_streaming() with "if (s->udev)". vb2_video_unregister_device() releases the queue, which synchronously calls stop_streaming() while s->udev is still valid, so the guard is no longer needed; airspy_stop_streaming() is unchanged. - Dropped the outer mutex_lock(&s->vb_queue_lock) / mutex_lock(&s->v4l2_lock) around the unregister sequence: vb2_video_unregister_device() acquires vb_queue_lock internally and stop_streaming() acquires v4l2_lock, so holding either of those while calling the unregister helper self-deadlocks. - Rebased on media-committers/next. drivers/media/usb/airspy/airspy.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/a= irspy.c index 57edb42463e8..358a66ab8e48 100644 --- a/drivers/media/usb/airspy/airspy.c +++ b/drivers/media/usb/airspy/airspy.c @@ -464,14 +464,21 @@ static void airspy_disconnect(struct usb_interface *i= ntf) =20 dev_dbg(s->dev, "\n"); =20 - mutex_lock(&s->vb_queue_lock); + /* + * vb2_video_unregister_device() releases the vb2 queue, which + * triggers airspy_stop_streaming() if streaming is active. + * stop_streaming() dereferences s->udev via airspy_ctrl_msg() and + * airspy_free_stream_bufs(), so it must run before s->udev is + * cleared. vb2_video_unregister_device() locks vb_queue_lock + * internally and stop_streaming() locks v4l2_lock, so neither may + * be held by the caller. + */ + v4l2_device_disconnect(&s->v4l2_dev); + vb2_video_unregister_device(&s->vdev); + mutex_lock(&s->v4l2_lock); - /* No need to keep the urbs around after disconnection */ s->udev =3D NULL; - v4l2_device_disconnect(&s->v4l2_dev); - video_unregister_device(&s->vdev); mutex_unlock(&s->v4l2_lock); - mutex_unlock(&s->vb_queue_lock); =20 v4l2_device_put(&s->v4l2_dev); } --=20 2.51.0