aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorZhan Xusheng <zhanxusheng1024@gmail.com>2026-09-28 10:02:04 +0800
committerJoel Granados <joel.granados@kernel.org>2026-09-29 09:25:14 +0200
commite955f14fa8467d70aaeea5830b4d1773d5b25500 (patch)
tree0582d898792c474fcfabf2dcefbdde5614e12a01 /kernel
parent72d3fcf802c45d00b300f25b848a93c3a2bd7c7e (diff)
sysctl: Negate before converting in the int read path
proc_int_k2u_conv_kop() reports the sign through *negp and the magnitude through *u_ptr, but for a negative value it hands the sign-extended int to the converter and negates the result: *u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val; With div_hz() and CONFIG_HZ=1000 a stored -1000 becomes (ulong)-1000 / 1000 == 18446744073709550, and negating that wraps: # echo -1 > /proc/sys/net/ipv4/tcp_fin_timeout # cat /proc/sys/net/ipv4/tcp_fin_timeout -18428297329635842066 The magnitude is HZ dependent but the wrap is not: the negation happens after the division at every CONFIG_HZ. Take the magnitude first and convert that, which is what the open-coded version did before commit 2dc164a48e6f ("sysctl: Create converter functions with two new macros") folded it into a macro. The k_ptr_op == NULL branch was already correct. All three int converters that pass a k_ptr_op are affected: proc_dointvec_jiffies(), proc_dointvec_userhz_jiffies() and proc_dointvec_ms_jiffies(). Fixes: 2dc164a48e6f ("sysctl: Create converter functions with two new macros") Cc: stable@vger.kernel.org Reviewed-by: Bradley Morgan <brads@mainlining.org> Signed-off-by: Zhan Xusheng <zhanxusheng@xiaomi.com> Signed-off-by: Joel Granados <joel.granados@kernel.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sysctl.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f7b75985d542..38597f26b34c 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -483,7 +483,7 @@ int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
if (val < 0) {
*negp = true;
- *u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val;
+ *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;