[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