[PATCH 35/61] dyndbg: check DYNDBG_CLASSMAP_DEFINE args at compile-time

Jim Cromie jim.cromie at gmail.com
Wed Sep 25 18:10:27 UTC 2024


Validate DYNDBG_CLASSMAP_DEFINE() args at compile:
	0 <= _base < 63
	class_names is not empty
	class_names[0] is a string
	(class_names.length + _base) < 63

These compile-time checks will prevent some misuses; 4 such examples
are added to test_dynamic_debug_submod.ko, and will fail compilation
if -DDD_MACRO_ARGCHECK is added to cflags.

They're implemented with 3 static_asserts in DYNDBG_CLASSMAP_DEFINE(),
checking the args.  The BUILD_BUG* options all appear to employ a
do-while-0 construct thats illegal at file-scope, which is the proper
usage of this macro (since it exports the classmap).

test-dynamic-debug-submod, when built with -DDD_MACRO_ARGCHECK, gets 4
_DEFINEs to break compilation when the 1st 3 rules above are violated.

Signed-off-by: Jim Cromie <jim.cromie at gmail.com>
---
 include/linux/dynamic_debug.h |  4 ++++
 lib/dynamic_debug.c           | 39 ++++++++++++++++++++++++-----------
 lib/test_dynamic_debug.c      | 19 +++++++++++++++++
 3 files changed, 50 insertions(+), 12 deletions(-)

diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index e729aff78ea7..62aadd2f4706 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -111,7 +111,11 @@ struct ddebug_class_map {
  * to the classmap.
  */
 #define __DYNDBG_CLASSMAP_DEFINE(_var, _maptype, _base, ...)		\
+	static_assert((_base >= 0 && _base < _DPRINTK_CLASS_DFLT));	\
 	static const char *_var##_classnames[] = { __VA_ARGS__ };	\
+	static_assert(ARRAY_SIZE(_var##_classnames) > 0);		\
+	static_assert((ARRAY_SIZE(_var##_classnames) + _base) <		\
+		      _DPRINTK_CLASS_DFLT);				\
 	struct ddebug_class_map __aligned(8) __used			\
 		__section("__dyndbg_classes") _var = {			\
 		.mod = THIS_MODULE,					\
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index e6b6f889a3d0..d9666ba72b48 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -1246,8 +1246,9 @@ static void ddebug_apply_params(const struct ddebug_class_map *cm, const char *m
  * modular classmap vector/section.  Save the start and length of the
  * subrange at its edges.
  */
-static void ddebug_attach_module_classes(struct ddebug_table *dt,
-					 const struct _ddebug_info *di)
+static int ddebug_attach_module_classes(struct ddebug_table *dt,
+					const struct _ddebug_info *di,
+					u64 *reserved_ids)
 {
 	struct ddebug_class_map *cm;
 	int i, nc = 0;
@@ -1260,13 +1261,14 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt,
 		}
 	}
 	if (!nc)
-		return;
+		return 0;
 
 	vpr_info("module:%s attached %d classes\n", dt->mod_name, nc);
 	dt->num_classes = nc;
 
 	for (i = 0, cm = dt->classes; i < dt->num_classes; i++, cm++)
 		ddebug_apply_params(cm, cm->mod_name);
+	return 0;
 }
 
 /*
@@ -1274,8 +1276,9 @@ static void ddebug_attach_module_classes(struct ddebug_table *dt,
  * means a query against the dt/module, which means it must be on the
  * list to be seen by ddebug_change.
  */
-static void ddebug_attach_user_module_classes(struct ddebug_table *dt,
-					      const struct _ddebug_info *di)
+static int ddebug_attach_user_module_classes(struct ddebug_table *dt,
+					      const struct _ddebug_info *di,
+					      u64 *reserved_ids)
 {
 	struct ddebug_class_user *cli;
 	int i, nc = 0;
@@ -1298,7 +1301,7 @@ static void ddebug_attach_user_module_classes(struct ddebug_table *dt,
 		}
 	}
 	if (!nc)
-		return;
+		return 0;
 
 	dt->num_class_users = nc;
 
@@ -1307,6 +1310,7 @@ static void ddebug_attach_user_module_classes(struct ddebug_table *dt,
 		ddebug_apply_params(cli->map, cli->user_mod_name);
 
 	vpr_dt_info(dt, "attach-client-module: ");
+	return 0;
 }
 
 /*
@@ -1316,6 +1320,8 @@ static void ddebug_attach_user_module_classes(struct ddebug_table *dt,
 static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 {
 	struct ddebug_table *dt;
+	u64 reserved_ids;
+	int rc;
 
 	if (!di->num_descs)
 		return 0;
@@ -1339,16 +1345,20 @@ static int ddebug_add_module(struct _ddebug_info *di, const char *modname)
 
 	INIT_LIST_HEAD(&dt->link);
 
-	if (di->num_classes)
-		ddebug_attach_module_classes(dt, di);
-
+	if (di->num_classes) {
+		rc = ddebug_attach_module_classes(dt, di, &reserved_ids);
+		if (rc)
+			return rc;
+	}
 	mutex_lock(&ddebug_lock);
 	list_add_tail(&dt->link, &ddebug_tables);
 	mutex_unlock(&ddebug_lock);
 
-	if (di->num_class_users)
-		ddebug_attach_user_module_classes(dt, di);
-
+	if (di->num_class_users) {
+		rc = ddebug_attach_user_module_classes(dt, di, &reserved_ids);
+		if (rc)
+			return rc;
+	}
 	vpr_info("%3u debug prints in module %s\n", di->num_descs, modname);
 	return 0;
 }
@@ -1433,6 +1443,11 @@ static int ddebug_module_notify(struct notifier_block *self, unsigned long val,
 	switch (val) {
 	case MODULE_STATE_COMING:
 		ret = ddebug_add_module(&mod->dyndbg_info, mod->name);
+		if (ret == -EINVAL) {
+			pr_err("conflicting dyndbg-classmap reservations\n");
+			ddebug_remove_module(mod->name);
+			break;
+		}
 		if (ret)
 			WARN(1, "Failed to allocate memory: dyndbg may not work properly.\n");
 		break;
diff --git a/lib/test_dynamic_debug.c b/lib/test_dynamic_debug.c
index 8ab8717fdf80..4d7b1709d055 100644
--- a/lib/test_dynamic_debug.c
+++ b/lib/test_dynamic_debug.c
@@ -118,8 +118,27 @@ DYNDBG_CLASSMAP_PARAM(p_level_num,	map_level_num, p);
 DYNDBG_CLASSMAP_USE(map_disjoint_bits);
 DYNDBG_CLASSMAP_USE(map_level_num);
 
+#if defined(FORCE_CLASSID_CONFLICT_MODPROBE)
+/*
+ * enable to test overlapping class-id range detection.
+ * This should break on modprobe (of submod)
+ */
+DYNDBG_CLASSMAP_DEFINE(classid_range_conflict_submod, 0, D2_CORE + 1, "D3_SUB");
 #endif
 
+#if defined(DD_MACRO_ARGCHECK)
+/*
+ * Exersize compile-time arg-checks in the macro.
+ * These will break compilation.
+ */
+DYNDBG_CLASSMAP_DEFINE(fail_base_neg, 0, -1, "NEGATIVE_BASE_ARG");
+DYNDBG_CLASSMAP_DEFINE(fail_base_big, 0, 100, "TOOBIG_BASE_ARG");
+DYNDBG_CLASSMAP_DEFINE(fail_str_type, 0, 0, 1 /* not a string */);
+DYNDBG_CLASSMAP_DEFINE(fail_emptyclass, 0, 0 /* ,empty */);
+#endif
+
+#endif /* TEST_DYNAMIC_DEBUG_SUBMOD */
+
 /* stand-in for all pr_debug etc */
 #define prdbg(SYM) __pr_debug_cls(SYM, #SYM " msg\n")
 
-- 
2.46.1



More information about the Intel-gfx-trybot mailing list