lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250131124421.152497-1-r.smirnov@omp.ru>
Date: Fri, 31 Jan 2025 15:44:17 +0300
From: Roman Smirnov <r.smirnov@....ru>
To: Maarten Lankhorst <maarten.lankhorst@...ux.intel.com>, Maxime Ripard
	<mripard@...nel.org>, Thomas Zimmermann <tzimmermann@...e.de>, David Airlie
	<airlied@...il.com>, Simona Vetter <simona@...ll.ch>
CC: Roman Smirnov <r.smirnov@....ru>, Dave Airlie <airlied@...hat.com>, Keith
 Packard <keithp@...thp.com>, <dri-devel@...ts.freedesktop.org>,
	<linux-kernel@...r.kernel.org>, <lvc-project@...uxtesting.org>, syzbot
	<syzbot+6754751ad05524dae739@...kaller.appspotmail.com>
Subject: [PATCH] drm/drm_lease: add sanity check to drm_mode_create_lease_ioctl()

Syzkaller found a case of dangerous call via drm_ioctl(). If user makes
object_count too large, WARN() is called when allocating memory:

------------[ cut here ]------------
WARNING: CPU: 0 PID: 5229 at mm/page_alloc.c:4709 __alloc_pages_noprof+0x3bd/0x710 mm/page_alloc.c:4709
Modules linked in:
CPU: 0 UID: 0 PID: 5229 Comm: syz-executor478 Not tainted 6.12.0-rc4-syzkaller-00047-gc2ee9f594da8 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
Call Trace:
 <TASK>
 __alloc_pages_node_noprof include/linux/gfp.h:269 [inline]
 alloc_pages_node_noprof include/linux/gfp.h:296 [inline]
 ___kmalloc_large_node+0x8b/0x1d0 mm/slub.c:4209
 __kmalloc_large_node_noprof+0x1a/0x80 mm/slub.c:4236
 __do_kmalloc_node mm/slub.c:4252 [inline]
 __kmalloc_noprof+0x2ae/0x400 mm/slub.c:4276
 kmalloc_noprof include/linux/slab.h:882 [inline]
 kmalloc_array_noprof include/linux/slab.h:923 [inline]
 fill_object_idr drivers/gpu/drm/drm_lease.c:389 [inline]
 drm_mode_create_lease_ioctl+0x580/0x1db0 drivers/gpu/drm/drm_lease.c:522
 drm_ioctl_kernel+0x337/0x440 drivers/gpu/drm/drm_ioctl.c:745
 drm_ioctl+0x60e/0xad0 drivers/gpu/drm/drm_ioctl.c:842
 vfs_ioctl fs/ioctl.c:51 [inline]
 __do_sys_ioctl fs/ioctl.c:907 [inline]
 __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893
 do_syscall_x64 arch/x86/entry/common.c:52 [inline]
 do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
 </TASK>

The number of objects requested for lessee must not exceed the
number of objects already in lessor because if the user requests
more identifiers than lessor has, one of the calls of idr_find()
in drm_lease_create() will return NULL. Then ioctl() will
terminate with an error.

The added check handles this case before calling kcalloc(),
which prevents WARN() from being called.

Reported-by: syzbot <syzbot+6754751ad05524dae739@...kaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=6754751ad05524dae739
Fixes: 62884cd386b8 ("drm: Add four ioctls for managing drm mode object leases [v7]")
Signed-off-by: Roman Smirnov <r.smirnov@....ru>
---
 drivers/gpu/drm/drm_lease.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 94375c6a5425..c1bebc70e544 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -336,6 +336,23 @@ static void _drm_lease_revoke(struct drm_master *top)
 	}
 }
 
+static int validate_object_count(struct drm_device *dev,
+				 size_t object_count)
+{
+	size_t available_objects = 0;
+	int object;
+	void *entry;
+
+	mutex_lock(&dev->mode_config.idr_mutex);
+	idr_for_each_entry(&dev->mode_config.object_idr, entry, object)
+		available_objects++;
+	mutex_unlock(&dev->mode_config.idr_mutex);
+
+	if (available_objects < object_count)
+		return -EINVAL;
+	return 0;
+}
+
 void drm_lease_revoke(struct drm_master *top)
 {
 	mutex_lock(&top->dev->mode_config.idr_mutex);
@@ -507,6 +524,12 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
 	object_count = cl->object_count;
 
+	ret = validate_object_count(lessor->dev, object_count);
+	if (ret) {
+		drm_dbg_lease(dev, "requested too many objects\n");
+		goto out_lessor;
+	}
+
 	/* Handle leased objects, if any */
 	idr_init(&leases);
 	if (object_count != 0) {
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ