]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
char: misc: restrict the dynamic range to exclude reserved minors
authorThadeu Lima de Souza Cascardo <cascardo@igalia.com>
Wed, 23 Apr 2025 08:45:42 +0000 (05:45 -0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:32 +0000 (15:34 -0500)
[ Upstream commit 31b636d2c41613e3bd36256a4bd53e9dacfa2677 ]

When this was first reported [1], the possibility of having sufficient
number of dynamic misc devices was theoretical, in the case of dlm driver.
In practice, its userspace never created more than one device.

What we know from commit ab760791c0cf ("char: misc: Increase the maximum
number of dynamic misc devices to 1048448"), is that the miscdevice
interface has been used for allocating more than the single-shot devices it
was designed for. And it is not only coresight_tmc, but many other drivers
are able to create multiple devices.

On systems like the ones described in the above commit, it is certain that
the dynamic allocation will allocate certain reserved minor numbers,
leading to failures when a later driver tries to claim its reserved number.

Instead of excluding the historically statically allocated range from
dynamic allocation, restrict the latter to minors above 255. That also
removes the need for DYNAMIC_MINORS and the convolution in allocating minor
numbers, simplifying the code.

Since commit ab760791c0cf ("char: misc: Increase the maximum number of
dynamic misc devices to 1048448") has been applied, such range is already
possible. And given such devices already need to be dynamically created,
there should be no systems where this might become a problem.

[1] https://lore.kernel.org/all/1257813017-28598-3-git-send-email-cascardo@holoscopio.com/

Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
Link: https://lore.kernel.org/r/20250423-misc-dynrange-v4-1-133b5ae4ca18@igalia.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/char/misc.c

index 792a1412faffefb8cc147f3c384d29a34d8ace9c..8d8c4bcf07e1c2edfc266d30584c83765c0debc6 100644 (file)
@@ -58,9 +58,8 @@ static LIST_HEAD(misc_list);
 static DEFINE_MUTEX(misc_mtx);
 
 /*
- * Assigned numbers, used for dynamic minors
+ * Assigned numbers.
  */
-#define DYNAMIC_MINORS 128 /* like dynamic majors */
 static DEFINE_IDA(misc_minors_ida);
 
 static int misc_minor_alloc(int minor)
@@ -69,34 +68,17 @@ static int misc_minor_alloc(int minor)
 
        if (minor == MISC_DYNAMIC_MINOR) {
                /* allocate free id */
-               ret = ida_alloc_max(&misc_minors_ida, DYNAMIC_MINORS - 1, GFP_KERNEL);
-               if (ret >= 0) {
-                       ret = DYNAMIC_MINORS - ret - 1;
-               } else {
-                       ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
-                                             MINORMASK, GFP_KERNEL);
-               }
+               ret = ida_alloc_range(&misc_minors_ida, MISC_DYNAMIC_MINOR + 1,
+                                     MINORMASK, GFP_KERNEL);
        } else {
-               /* specific minor, check if it is in dynamic or misc dynamic range  */
-               if (minor < DYNAMIC_MINORS) {
-                       minor = DYNAMIC_MINORS - minor - 1;
-                       ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
-               } else if (minor > MISC_DYNAMIC_MINOR) {
-                       ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
-               } else {
-                       /* case of non-dynamic minors, no need to allocate id */
-                       ret = 0;
-               }
+               ret = ida_alloc_range(&misc_minors_ida, minor, minor, GFP_KERNEL);
        }
        return ret;
 }
 
 static void misc_minor_free(int minor)
 {
-       if (minor < DYNAMIC_MINORS)
-               ida_free(&misc_minors_ida, DYNAMIC_MINORS - minor - 1);
-       else if (minor > MISC_DYNAMIC_MINOR)
-               ida_free(&misc_minors_ida, minor);
+       ida_free(&misc_minors_ida, minor);
 }
 
 #ifdef CONFIG_PROC_FS