Motivation: https://lore.kernel.org/all/2026021413-CVE-2026-23149-8329@gregkh/

When user controlled data can pass start values < 0 to idr_alloc()
kernel hits a WARN_ON in run time. This check is to catch that using
static analysis.

Signed-off-by: Harshit Mogalapalli <[email protected]>
---
 check_idr_alloc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 check_list.h      |  1 +
 2 files changed, 47 insertions(+)
 create mode 100644 check_idr_alloc.c

diff --git a/check_idr_alloc.c b/check_idr_alloc.c
new file mode 100644
index 000000000000..ecd6a808e8ab
--- /dev/null
+++ b/check_idr_alloc.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2026 Oracle
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
+ */
+
+#include "parse.h"
+#include "smatch.h"
+#include "smatch_extra.h"
+
+static int my_id;
+
+static void match_idr_alloc(struct expression *expr)
+{
+       struct range_list *rl;
+
+       if (!get_user_rl(expr, &rl))
+               return;
+
+       rl = cast_rl(&int_ctype, rl);
+       if (!sval_is_negative(rl_min(rl)))
+               return;
+
+       sm_warning("idr_alloc start value from user can be < 0");
+}
+
+void check_idr_alloc(int id)
+{
+       if (option_project != PROJ_KERNEL)
+               return;
+
+       my_id = id;
+
+       add_param_key_expr_hook("idr_alloc", &match_idr_alloc, 2, "$", NULL);
+}
diff --git a/check_list.h b/check_list.h
index 799aa76c98cf..77d596a7c350 100644
--- a/check_list.h
+++ b/check_list.h
@@ -223,6 +223,7 @@ CK(check_no_increment)
 
 /* kernel specific */
 CK(check_kernel_printf)
+CK(check_idr_alloc)
 CK(check_inconsistent_locking)
 CK(check_puts_argument)
 CK(check_err_ptr)
-- 
2.47.3


Reply via email to