Add macros that define a struct kernel_param_ops initializer through a
macro so the underlying field layout can evolve without touching every
call site. Three variants cover the three cases:

 DEFINE_KERNEL_PARAM_OPS(name, set, get) // basic
 DEFINE_KERNEL_PARAM_OPS_NOARG(name, set, get) // set KERNEL_PARAM_OPS_FL_NOARG
 DEFINE_KERNEL_PARAM_OPS_FREE(name, set, get, free) // also set .free

Callers prefix their own visibility qualifiers, e.g.:

  static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);

Also update module_param_call() and STANDARD_PARAM_DEF() to use
DEFINE_KERNEL_PARAM_OPS internally so the generated ops table will go
through the same macro as everything else.

Subsequent commits convert all open-coded struct kernel_param_ops
definitions to use these macros, in preparation for migrating to a
seq_buf .get API.

Signed-off-by: Kees Cook <[email protected]>
---
 include/linux/moduleparam.h | 36 ++++++++++++++++++++++++++++++++++--
 kernel/params.c             |  6 ++----
 2 files changed, 36 insertions(+), 6 deletions(-)

diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h
index 075f28585074..26bf45b36d02 100644
--- a/include/linux/moduleparam.h
+++ b/include/linux/moduleparam.h
@@ -68,6 +68,39 @@ struct kernel_param_ops {
        void (*free)(void *arg);
 };
 
+/*
+ * Define a const struct kernel_param_ops initializer. Callers prefix with
+ * any required visibility qualifiers (typically "static"):
+ *
+ *   static DEFINE_KERNEL_PARAM_OPS(my_ops, my_set, my_get);
+ *
+ * Routing the @_set and @_get function pointers through the macro
+ * (rather than naming the struct fields at every call site) lets the
+ * field layout change in one place when callbacks are migrated to a
+ * new signature.
+ */
+#define DEFINE_KERNEL_PARAM_OPS(_name, _set, _get)                     \
+       const struct kernel_param_ops _name = {                         \
+               .set = (_set),                                          \
+               .get = (_get),                                          \
+       }
+
+/* As DEFINE_KERNEL_PARAM_OPS, with KERNEL_PARAM_OPS_FL_NOARG set. */
+#define DEFINE_KERNEL_PARAM_OPS_NOARG(_name, _set, _get)               \
+       const struct kernel_param_ops _name = {                         \
+               .flags = KERNEL_PARAM_OPS_FL_NOARG,                     \
+               .set = (_set),                                          \
+               .get = (_get),                                          \
+       }
+
+/* As DEFINE_KERNEL_PARAM_OPS, with an additional .free callback. */
+#define DEFINE_KERNEL_PARAM_OPS_FREE(_name, _set, _get, _free)         \
+       const struct kernel_param_ops _name = {                         \
+               .set = (_set),                                          \
+               .get = (_get),                                          \
+               .free = (_free),                                        \
+       }
+
 /*
  * Flags available for kernel_param
  *
@@ -311,8 +344,7 @@ struct kparam_array
  * kernel_param_ops), use module_param_cb() instead.
  */
 #define module_param_call(name, _set, _get, arg, perm)                 \
-       static const struct kernel_param_ops __param_ops_##name =       \
-               { .flags = 0, .set = _set, .get = _get };               \
+       static DEFINE_KERNEL_PARAM_OPS(__param_ops_##name, _set, _get); \
        __module_param_call(MODULE_PARAM_PREFIX,                        \
                            name, &__param_ops_##name, arg, perm, -1, 0)
 
diff --git a/kernel/params.c b/kernel/params.c
index 752721922a15..2cbad1f4dd06 100644
--- a/kernel/params.c
+++ b/kernel/params.c
@@ -222,10 +222,8 @@ char *parse_args(const char *doing,
                return scnprintf(buffer, PAGE_SIZE, format "\n",        \
                                *((type *)kp->arg));                    \
        }                                                               \
-       const struct kernel_param_ops param_ops_##name = {                      
\
-               .set = param_set_##name,                                \
-               .get = param_get_##name,                                \
-       };                                                              \
+       DEFINE_KERNEL_PARAM_OPS(param_ops_##name,                       \
+                               param_set_##name, param_get_##name);    \
        EXPORT_SYMBOL(param_set_##name);                                \
        EXPORT_SYMBOL(param_get_##name);                                \
        EXPORT_SYMBOL(param_ops_##name)
-- 
2.34.1


Reply via email to