From nobody Mon May 25 00:08:59 2026 Received: from mail-pg1-f169.google.com (mail-pg1-f169.google.com [209.85.215.169]) (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 B08243B3C00 for ; Wed, 20 May 2026 09:09:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779268176; cv=none; b=Q8S1ILJ41va8RDeP1wLyliMdTskzGY3yw44eLNk+Hdhsbu6dsV1m6JUSyA2LYlrYfCdAX6SyQ3ZUpoDxILQBJ6cI29tAkUMIBD4rwrmcsq/eEiefW4os4f/PgwHidaqemU82/mkgMiWqFBMESQkq2hZZzrGAwYigNoHKhoL8WOQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779268176; c=relaxed/simple; bh=NeyEkYV1Wcj6ccjUih0btV95jGFumcK19aJw4byQneA=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=ubBw8GB/BRZEUPZVpjaCuyM7PPACIaKJPKikHMBU1pzDB4hc8m/Vv/ZpdCoGnLmAd+i2sRGgZLcdT9Z5OgT+MmMjGygE61MmiRTVNcsoLNr0R4hpOsto9IcH6Tt3L93rfhctcdm4OnguIMaKt5Y2NDNnPyumst5ii24XtyN5E28= 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=HvnCq9I7; arc=none smtp.client-ip=209.85.215.169 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="HvnCq9I7" Received: by mail-pg1-f169.google.com with SMTP id 41be03b00d2f7-c8021c8c42fso1894753a12.3 for ; Wed, 20 May 2026 02:09:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779268174; x=1779872974; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=scVhXrGhIJluENy8IAivxDBRwlP7LvJuAQpRY75tmO4=; b=HvnCq9I7SLEE4/zZMVTgi/IeWjyWfpklw9H2ClMbiZkc1BaYXrKvkXubGHbSKj5LTu BqHOcNfSGWSVPoOlE2tWVJqhn1kNixuNbfMCFXB9UIblRO82KAHM8kCj4FuKlxBe0xQ+ DGA60E2Gh8/GZtM4nJMyK8Q42F31QKmPrt4o50cgbs7octtoKmLevZ7lo8fpBV+T5Lir KH5slSA7eeKW3tE+ah8t9InNpHh6i67CeQfy5Qtov8lqsKUVf/NBULdz585BKABtyyn4 D8dURDQgUpoALXqJHxNiIv9NOsI3SdHi4Q0x4pXPpsDqiXpaJsWcJP2OBy1THBGHIVdm 8FPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779268174; x=1779872974; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=scVhXrGhIJluENy8IAivxDBRwlP7LvJuAQpRY75tmO4=; b=HOBHAjJNiZQHaae7bzYXlHM3ukrrY/wn5w8vfScV1OIGzDYsT1miekr0BXDwYcrDLf 0V+okRDn0t+pyFJzJDcO6muB6k1cgH3YKcBBhBeafq4GB30s6ATYybhz9oQKm72hvQfe /mAa/5pRYvn1buKQ/0ypn6jUGosNLiHGs3VP67N14zNjfW2fVmoX4Zw6BMuCnsEtnHnF NOY+XvMR7JbUK3D0/ai9Dm4MrUN/l1lTvGxqLSmy5VofDUMdGFAbf7Fc9tb3+vMVtsHS GU3YaOw0R8yxBowhK71G1WoZgi6oDImXXlV4oNBLxP+TjHuNz/7/kvMbh/vl0IuQxOy+ h4Ng== X-Forwarded-Encrypted: i=1; AFNElJ/hg17J7/u/TSGqW75+YK/J4eYfXG9vHFiXwGAvJ79m61ZEZQfRRehZkEotilVxtV+k8WhLN6ClOAdjtF0=@vger.kernel.org X-Gm-Message-State: AOJu0Yyr3sYBRS45CYKMDDYUYvvkcuD7ElUfZLpelR+EtxBtzrMDw/Ma /fhTJUBDCtdErP+ERQKSjyxQpg0AmOPwfVTTTsmpGRsM/KzbSRwpXsVZ X-Gm-Gg: Acq92OH7j0YSTC1ezbz5AeMJ7qDjVH7cWUacxWECn28LNOtdemVzqfbKkZR6Y/ZDlZH ZTYAGihZb/UykGLGE+t6GfMcObtVbQvSrf17BQedLRsH0+cDZVGTAITzBxzlvlyhJJDPI+XL6Xw UUmKa2NwZT4OEM/ioddb6mx3NddVJzDTqQQUMaMEBMoXbw3e7lPqsJCm/yxG0O5SRV6MlhCh8ss scM76b2CGUo2DfH9O2vNIPOrftW8OP17TyBoBv16IhxVj3nbamSEJ/jrEAFpcISLfcnL6ey9iQL c4xy8XR4Y1Sd+e1Atkr1zkzdmyympY6+OMtpyyPcMWPizpKTA6GQsKCAzYdHxiua5knVmi8kQ2Y F6P3ksvDULB+VaSTBIc2EMVEmjb58/owje7rWez6PRrWWTSrNc+lzDSp23NtsXzH5+1YroGSvjz veFYIi65WPO6Cl0ekj X-Received: by 2002:a17:902:b085:b0:2b9:86ca:5bf2 with SMTP id d9443c01a7336-2bd7e94c757mr174598995ad.30.1779268173671; Wed, 20 May 2026 02:09:33 -0700 (PDT) Received: from lgs.. ([2001:250:5800:1000::f280]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2bd5cfe4973sm216875815ad.41.2026.05.20.02.09.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 May 2026 02:09:33 -0700 (PDT) From: Guangshuo Li To: Mauro Carvalho Chehab , Laurent Pinchart , Hans Verkuil , Guangshuo Li , Kees Cook , Sakari Ailus , Ma Ke , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH] media: v4l2-dev: do not fire driver's release on __video_register_device() failure Date: Wed, 20 May 2026 17:06:24 +0800 Message-ID: <20260520090624.1071139-1-lgs201920130244@gmail.com> X-Mailer: git-send-email 2.43.0 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" video_register_device() / __video_register_device() registers vdev->dev with device_register(). Before the call the video core sets vdev->dev.release =3D v4l2_device_release; v4l2_device_release() invokes vdev->release(vdev) as its last step, and the driver's vdev->release hook is commonly video_device_release(), which kfree()s the vdev that the driver allocated with video_device_alloc(). When device_register() fails inside __video_register_device() the core does put_device(&vdev->dev); return ret; which drops the only reference and fires the v4l2_device_release() chain: __video_register_device() device_register() -> -E* put_device(&vdev->dev) -> v4l2_device_release() -> vdev->release(vdev) -> video_device_release(vdev) /* kfree(vdev), free #1 */ video_register_device() returns the error to the driver. Drivers that follow the documented ownership contract release vdev on their own error path, e.g. driver_probe() if (video_register_device(vdev, ...)) goto err_release_vdev; ... err_release_vdev: video_device_release(vdev); /* free #2 -- DOUBLE FREE */ This is the contract documented in Documentation/driver-api/media/v4l2-dev.rst: the driver owns vdev and is responsible for releasing it if video_register_device() fails. As Hans Verkuil pointed out, the right place to fix this is the v4l2 core rather than every individual driver, because drivers are expected to follow the documented ownership contract. Neutralise vdev->release around put_device() in the device_register() failure path so the device core cleanup does not run the driver's release hook. The driver-supplied release is restored before returning so the caller can release vdev according to the documented contract. Successful registration is unchanged, so the normal teardown sequence continues to call the driver's release hook and free vdev exactly once on unregister. Fixes: 2a934fdb01db ("media: v4l2-dev: fix error handling in __video_regist= er_device()") Signed-off-by: Guangshuo Li --- drivers/media/v4l2-core/v4l2-dev.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v= 4l2-dev.c index 6ce623a1245a..73648549eb2a 100644 --- a/drivers/media/v4l2-core/v4l2-dev.c +++ b/drivers/media/v4l2-core/v4l2-dev.c @@ -1075,9 +1075,14 @@ int __video_register_device(struct video_device *vde= v, mutex_lock(&videodev_lock); ret =3D device_register(&vdev->dev); if (ret < 0) { + void (*release)(struct video_device *) =3D vdev->release; + mutex_unlock(&videodev_lock); pr_err("%s: device_register failed\n", __func__); + + vdev->release =3D video_device_release_empty; put_device(&vdev->dev); + vdev->release =3D release; return ret; } =20 --=20 2.43.0