From nobody Sat Jul 25 00:15:20 2026 Received: from mail-yw1-f181.google.com (mail-yw1-f181.google.com [209.85.128.181]) (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 8046435F5E5 for ; Wed, 22 Jul 2026 00:50:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784681424; cv=none; b=pAYFZuTjYS+VF1HCe5pksVcbn8vKoCvwY3M+YDC1Sq14rSx7kb2o0gfi4h+v2yLEcRtWoBmtfWIGWbfFSotiX3fiGmP1dNZTNhWyW7/NQlcmHmIezQjcb0xaogiGQ/YvIkT5TvLSmtANT/KqrlttlkWiM5Vau3kwHM6RL0jo36M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784681424; c=relaxed/simple; bh=M6TNbmis4qFLnoCjfnxah+vvQJe8uq3U4DBgseOgzuA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=LwlV1AnfiD1dNL+kjv9ENUkRdokj6OnTZAL83+u7JLioj8qg/nh4CMvxfpQICagpRTOtbddZ9+JHBC6ZnUqiXYNYxkpEkVSE75P8TpXXVlP+CIJ6R5UNUMWG/nHJ3Gv+kaeyydBuI+ULGIc5vufYfhhGnC3NCcT2y168vqVxh2U= 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=YER/9dIp; arc=none smtp.client-ip=209.85.128.181 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="YER/9dIp" Received: by mail-yw1-f181.google.com with SMTP id 00721157ae682-81e8fa1b8d6so123273587b3.1 for ; Tue, 21 Jul 2026 17:50:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1784681421; x=1785286221; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=rJbH45gcna7VV6rOGg0H1UcXgV7i4qjnHK593sOvtX4=; b=YER/9dIp/hhIuHDh3z89vbH3yZrZKHjG0bVATpmgx85XY03iy2ahOjEvHoio5apmzb 6iOh7hgwxpSKy8j1JAEUCuEEb4uMwIaMj86+plcGieXcVrAP1bgmjxjt0DS36puejU2o P5aTjbTJUoH1LsjfUhqFpGDD0kTbrHaB2fyLHxZOaE1RZ8jg6W+DCVzxhucPnu1ssHWI Rb8ZnqTYvB8hmmnfyGZcNBeKfbA7bET/mGeSC+bpHto+MlFEXEAh6LX4yQMVBkmlkLOK Ol0Ffcozhj9Ki5xw6mTfNdfqlvcjuQA4+fyTUQHHa/iW5Cv4Hd4UIK/CnA0DMKdVWdhV QJVQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1784681421; x=1785286221; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=rJbH45gcna7VV6rOGg0H1UcXgV7i4qjnHK593sOvtX4=; b=Tpa827ZPikaRqNaZb8QHzUvJNl2oMkI7FKuGUr1YQYdtX27kHxGOyGZ18c6rJ+ErfB IZRy/biNYkcVy0CV3rHvuXM/rv7ZsSN223F7Y++6Byu66pQdXo1gg4YQz4F/Xvc67R0m ZNO9hfq3cvgsqWrCqwFTe1RZENe29MhYLSIT80guIyZA8vOSosg6CCGwdfpF/bss4M4L d/ywbl36rijs0qeXOcHHVmMC92iMWa2rSfJVghZZVz9DgUSkUu/Eo6Mfo+BCktqemS4x xw1rE9CcRK1gMyQjSvKRBfCjL9w85nrqLkA6QvhKSXHTSoc8m4Fg5Gks9w/KFoflXnfx cOdA== X-Forwarded-Encrypted: i=1; AHgh+RqiPFYzBalTIHYq3mUPzjELfsuuGLweTxR0olx+Ais2kBFYwSZ+pv4KTyQ7Pg8mFld0gVTQFSHjYAeKwsY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx/FKLneVqFFw+Qmw0upuzBeEQwUe/hTyX53iWL5YhOXGA1JsOl qrUrUDPYaZUuTJbaaBvdY0qswjQbdWS2meBCiJIlFGBf9Pag69qP/Kvc X-Gm-Gg: AR+sD10Nc8gnmSFCykKJ7nRdpTdtnxHfRCAPVTHVHVyr5v3GbgGpposRQh57hiwkDgT e0KdvvcV86O0tQtybHBTaagmDJOv4qqwImrXrd44MqfuorOG+QHLtS07PEOQrqsJqLsquGJvRLj QmTtoPW/3LaUh8o3VCJBIsNn9sQvuBqivl2w3ESDyuIqJKgYB9Q0/QLV6Fu8BtgHWajkqEjmX+R dpvS8dvWnwQOl0QvDVq5oRZ7fMz+K65R1YVpwAkuSo+UxDAg8+09a1ev3f6TNo+Ozp3x571GUxX g3+4pR3wuxrZhupdxcFZyKyDrTOktlpomxT/NDxa/DStTW6lCnx1gIb/Ge9WJ1KwdtI5x3RkyUR Y5dN6ztWxxfKNXoWNGBn1vRj5woerGT03cl22IwfcPe+eyqf34Cy1tZGoOfEI7m8HMT0cKNHoZv zbyvzt+gsz6UlYaCa93ALnUCmtSWQO3uo2hzV/Rf3Ht8ZNi28BQdxI7u+B8g6b9mXUscLfQP9ih 9NZjhQ+bRg6K+KPdoIVtKOn/5C56MirdNr3leP4DgV5EyluBDlb2QFXcyKeMxLSB+8= X-Received: by 2002:a05:690c:4c0b:b0:81c:f1f1:134 with SMTP id 00721157ae682-81ef27eba7fmr67979877b3.39.1784681421358; Tue, 21 Jul 2026 17:50:21 -0700 (PDT) Received: from LAPTOP-83ECOPAB.f7a5e5c3-cab1-4810-bdbb-207cdd06de9e.globalsecureaccess.local (76-204-101-112.lightspeed.tukrga.sbcglobal.net. [76.204.101.112]) by smtp.gmail.com with ESMTPSA id 00721157ae682-81f33c34ebdsm6080397b3.13.2026.07.21.17.50.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Jul 2026 17:50:20 -0700 (PDT) From: "Cen Zhang (Microsoft)" To: mchehab@kernel.org, linux-media@vger.kernel.org Cc: kees@kernel.org, linux-kernel@vger.kernel.org, AutonomousCodeSecurity@microsoft.com, tgopinath@linux.microsoft.com, kys@microsoft.com, blbllhy@gmail.com Subject: [PATCH] media: v4l2-event: limit number of event subscriptions per file handle Date: Tue, 21 Jul 2026 20:48:18 -0400 Message-ID: <20260722004818.72310-1-blbllhy@gmail.com> X-Mailer: git-send-email 2.53.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" v4l2_event_subscribe() allows an unbounded number of event subscriptions per file handle. Since the subscription id field is fully user-controlled (32-bit), an unprivileged user with access to a V4L2 device node can create up to 2^32 distinct subscriptions, each pinning a kernel allocation (~200 bytes). This can exhaust kernel memory, causing an OOM condition and kernel panic. An unprivileged local user can trigger this by issuing repeated VIDIOC_SUBSCRIBE_EVENT ioctls with incrementing id values. The allocated objects reside in kernel slab (not accounted to the process cgroup), so existing memory limits (ulimit, memcg) do not prevent this. Most V4L2 drivers are affected because the framework function v4l2_event_subscribe() enforces no limit, such as uvcvideo (USB webcams) and the vicodec test driver used to reproduce this issue. This leads to: Kernel panic - not syncing: Out of memory: compulsory panic_on_oom is ena= bled Fix by adding a per-filehandle subscription counter and capping it at 256. Fixes: 6e239399e580 ("[media] v4l2-ctrls: add control events") Reported-by: Autonomous Code Security Signed-off-by: Cen Zhang (Microsoft) --- drivers/media/v4l2-core/v4l2-event.c | 14 +++++++++++++- include/media/v4l2-fh.h | 2 ++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core= /v4l2-event.c index 9dd2aaa95a67..fcd8ce4addc1 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -18,6 +18,9 @@ #include #include =20 +/* Per-filehandle limit on the number of event subscriptions. */ +#define V4L2_MAX_EVENT_SUBSCRIPTIONS 256 + static unsigned int sev_pos(const struct v4l2_subscribed_event *sev, unsig= ned int idx) { idx +=3D sev->first; @@ -218,6 +221,7 @@ static void __v4l2_event_unsubscribe(struct v4l2_subscr= ibed_event *sev) fh->navailable--; } list_del(&sev->list); + fh->nsubscribed--; } =20 int v4l2_event_subscribe(struct v4l2_fh *fh, @@ -251,8 +255,16 @@ int v4l2_event_subscribe(struct v4l2_fh *fh, =20 spin_lock_irqsave(&fh->vdev->fh_lock, flags); found_ev =3D v4l2_event_subscribed(fh, sub->type, sub->id); - if (!found_ev) + if (!found_ev) { + if (fh->nsubscribed >=3D V4L2_MAX_EVENT_SUBSCRIPTIONS) { + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + kvfree(sev); + mutex_unlock(&fh->subscribe_lock); + return -ENOSPC; + } list_add(&sev->list, &fh->subscribed); + fh->nsubscribed++; + } spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); =20 if (found_ev) { diff --git a/include/media/v4l2-fh.h b/include/media/v4l2-fh.h index aad4b3689d7e..65a7f31af889 100644 --- a/include/media/v4l2-fh.h +++ b/include/media/v4l2-fh.h @@ -33,6 +33,7 @@ struct v4l2_ctrl_handler; * @subscribe_lock: serialise changes to the subscribed list; guarantee th= at * the add and del event callbacks are orderly called * @subscribed: list of subscribed events + * @nsubscribed: number of subscribed events at @subscribed list * @available: list of events waiting to be dequeued * @navailable: number of available events at @available list * @sequence: event sequence number @@ -49,6 +50,7 @@ struct v4l2_fh { wait_queue_head_t wait; struct mutex subscribe_lock; struct list_head subscribed; + unsigned int nsubscribed; struct list_head available; unsigned int navailable; u32 sequence; --=20 2.53.0