summaryrefslogtreecommitdiff
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorJoel Granados <joel.granados@kernel.org>2025-12-03 22:42:32 +0100
committerJoel Granados <joel.granados@kernel.org>2026-01-06 11:26:42 +0100
commitef153851af5b05c23b3484e7eebaadd18f2da6a9 (patch)
tree51af79667c55dbe49f0881221f7da7e78a9cba54 /kernel/sysctl.c
parentb3af263b8a83f2ed033ae83fe008004b061b84f4 (diff)
sysctl: Replace unidirectional INT converter macros with functions
Replace SYSCTL_USER_TO_KERN_INT_CONV and SYSCTL_KERN_TO_USER_INT_CONV macros with function implementing the same logic.This makes debugging easier and aligns with the functions preference described in coding-style.rst. Update all jiffies converters to use explicit function implementations instead of macro-generated versions. Signed-off-by: Joel Granados <joel.granados@kernel.org>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 54deced9ab69..42975aa84ee3 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -458,8 +458,73 @@ static int do_proc_uint_conv_minmax(ulong *u_ptr, uint *k_ptr, int dir,
proc_uint_u2k_conv, proc_uint_k2u_conv);
}
-static SYSCTL_USER_TO_KERN_INT_CONV(, SYSCTL_CONV_IDENTITY)
-static SYSCTL_KERN_TO_USER_INT_CONV(, SYSCTL_CONV_IDENTITY)
+/**
+ * proc_int_k2u_conv_kop - Assign kernel value to a user space pointer
+ * @u_ptr: pointer to user space variable
+ * @k_ptr: pointer to kernel variable
+ * @negp: assigned %TRUE if the converted kernel value is negative;
+ * %FALSE otherweise
+ * @k_ptr_op: execute this function before assigning to u_ptr
+ *
+ * Uses READ_ONCE to get value from k_ptr. Executes k_ptr_op before assigning
+ * to u_ptr if not NULL. Does **not** check for overflow.
+ *
+ * Returns: 0 on success.
+ */
+int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
+ ulong (*k_ptr_op)(const ulong))
+{
+ int val = READ_ONCE(*k_ptr);
+
+ if (val < 0) {
+ *negp = true;
+ *u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val;
+ } else {
+ *negp = false;
+ *u_ptr = k_ptr_op ? k_ptr_op((ulong)val) : (ulong) val;
+ }
+ return 0;
+}
+
+/**
+ * proc_int_u2k_conv_uop - Assign user value to a kernel pointer
+ * @u_ptr: pointer to user space variable
+ * @k_ptr: pointer to kernel variable
+ * @negp: If %TRUE, the converted user value is made negative.
+ * @u_ptr_op: execute this function before assigning to k_ptr
+ *
+ * Uses WRITE_ONCE to assign value to k_ptr. Executes u_ptr_op if
+ * not NULL. Check for overflow with UINT_MAX.
+ *
+ * Returns: 0 on success.
+ */
+int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
+ ulong (*u_ptr_op)(const ulong))
+{
+ ulong u = u_ptr_op ? u_ptr_op(*u_ptr) : *u_ptr;
+
+ if (*negp) {
+ if (u > (ulong) INT_MAX + 1)
+ return -EINVAL;
+ WRITE_ONCE(*k_ptr, -u);
+ } else {
+ if (u > (ulong) INT_MAX)
+ return -EINVAL;
+ WRITE_ONCE(*k_ptr, u);
+ }
+ return 0;
+}
+
+static int sysctl_user_to_kern_int_conv(const bool *negp, const ulong *u_ptr,
+ int *k_ptr)
+{
+ return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, NULL);
+}
+
+static int sysctl_kern_to_user_int_conv(bool *negp, ulong *u_ptr, const int *k_ptr)
+{
+ return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, NULL);
+}
static SYSCTL_INT_CONV_CUSTOM(, sysctl_user_to_kern_int_conv,
sysctl_kern_to_user_int_conv, false)