From: wen.yang@linux.dev
To: Joel Granados <joel.granados@kernel.org>
Cc: Wen Yang <wen.yang@linux.dev>,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 39/39] sysctl: remove the extra pointers and the compatibility bounds read
Date: Thu, 29 Oct 2026 00:35:18 +0800 [thread overview]
Message-ID: <b6e4cbd509687301a8ee2106f19a3ac01e7671a6.1793204511.git.wen.yang@linux.dev> (raw)
In-Reply-To: <cover.1793204511.git.wen.yang@linux.dev>
From: Wen Yang <wen.yang@linux.dev>
Every entry now carries numeric min/max, so the pointer bounds have no
remaining users. Drop extra1 and extra2 from struct ctl_table, remove the
pointer branch from the range converters, and delete the shared pointer
constants that only existed to initialise those fields.
Suggested-by: Eric W. Biederman <ebiederm@xmission.com>
Suggested-by: Joel Granados <joel.granados@kernel.org>
Signed-off-by: Wen Yang <wen.yang@linux.dev>
---
fs/proc/proc_sysctl.c | 26 ++++-------------
include/linux/sysctl.h | 65 +++++++++++++++++++-----------------------
kernel/sysctl.c | 47 ++++++++----------------------
kernel/time/jiffies.c | 2 +-
lib/test_sysctl.c | 24 ++++++++--------
5 files changed, 59 insertions(+), 105 deletions(-)
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 3e65d75710df..dbbc94b61b71 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1105,7 +1105,6 @@ static int sysctl_err(const char *path, const struct ctl_table *table, char *fmt
static int sysctl_check_table_array(const char *path, const struct ctl_table *table)
{
- unsigned int extra;
int err = 0;
if ((table->proc_handler == proc_douintvec) ||
@@ -1117,23 +1116,6 @@ static int sysctl_check_table_array(const char *path, const struct ctl_table *ta
if (table->proc_handler == proc_dou8vec_minmax) {
if (table->maxlen != sizeof(u8))
err |= sysctl_err(path, table, "array not allowed");
-
- if (table->extra1) {
- extra = *(unsigned int *) table->extra1;
- if (extra > 255U)
- err |= sysctl_err(path, table,
- "range value too large for proc_dou8vec_minmax");
- }
- if (table->extra2) {
- extra = *(unsigned int *) table->extra2;
- if (extra > 255U)
- err |= sysctl_err(path, table,
- "range value too large for proc_dou8vec_minmax");
- }
- }
-
- /* Numeric bounds are validated alongside the legacy pointer form. */
- if (table->proc_handler == proc_dou8vec_minmax) {
if (table->min > 255U || table->max > 255U)
err |= sysctl_err(path, table,
"range value too large for proc_dou8vec_minmax");
@@ -1366,9 +1348,11 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
* type - Defines the target type (described in struct definition)
* proc_handler - the text handler routine (described below)
*
- * extra1, extra2 - extra pointers usable by the proc handler routines
- * XXX: we should eventually modify these to use long min / max [0]
- * [0] https://lkml.kernel.org/87zgpte9o4.fsf@email.froward.int.ebiederm.org
+ * min, max - numeric bounds used by range-checking handlers. Signed handlers
+ * interpret these values as signed longs. Unrestricted ranges must
+ * explicitly use the corresponding type limits. Custom handlers
+ * keep their context in data and can substitute backing storage
+ * on an invocation-local copy without changing these bounds.
*
* Leaf nodes in the sysctl tree will be represented by a single file
* under /proc; non-leaf nodes are not allowed.
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 225c07faf2c9..9cda53941e22 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -37,27 +37,22 @@ struct ctl_table_root;
struct ctl_table_header;
struct ctl_dir;
-/* Keep the same order as in fs/proc/proc_sysctl.c */
-#define SYSCTL_ZERO ((void *)&sysctl_vals[0])
-#define SYSCTL_ONE ((void *)&sysctl_vals[1])
-#define SYSCTL_TWO ((void *)&sysctl_vals[2])
-#define SYSCTL_THREE ((void *)&sysctl_vals[3])
-#define SYSCTL_FOUR ((void *)&sysctl_vals[4])
-#define SYSCTL_ONE_HUNDRED ((void *)&sysctl_vals[5])
-#define SYSCTL_TWO_HUNDRED ((void *)&sysctl_vals[6])
-#define SYSCTL_ONE_THOUSAND ((void *)&sysctl_vals[7])
-#define SYSCTL_THREE_THOUSAND ((void *)&sysctl_vals[8])
-#define SYSCTL_INT_MAX ((void *)&sysctl_vals[9])
-
-/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
-#define SYSCTL_MAXOLDUID ((void *)&sysctl_vals[10])
-#define SYSCTL_NEG_ONE ((void *)&sysctl_vals[11])
-
-extern const int sysctl_vals[];
-
-#define SYSCTL_LONG_ZERO ((void *)&sysctl_long_vals[0])
-#define SYSCTL_LONG_ONE ((void *)&sysctl_long_vals[1])
-#define SYSCTL_LONG_MAX ((void *)&sysctl_long_vals[2])
+/* Numeric constants for sysctl ranges. */
+#define SYSCTL_ZERO 0
+#define SYSCTL_ONE 1
+#define SYSCTL_TWO 2
+#define SYSCTL_THREE 3
+#define SYSCTL_FOUR 4
+#define SYSCTL_ONE_HUNDRED 100
+#define SYSCTL_TWO_HUNDRED 200
+#define SYSCTL_ONE_THOUSAND 1000
+#define SYSCTL_THREE_THOUSAND 3000
+#define SYSCTL_INT_MAX INT_MAX
+#define SYSCTL_MAXOLDUID 65535
+#define SYSCTL_NEG_ONE (-1)
+#define SYSCTL_LONG_ZERO 0UL
+#define SYSCTL_LONG_ONE 1UL
+#define SYSCTL_LONG_MAX LONG_MAX
/*
*
@@ -72,8 +67,6 @@ extern const int sysctl_vals[];
#define SYSCTL_USER_TO_KERN(dir) (!!(dir))
#define SYSCTL_KERN_TO_USER(dir) (!dir)
-extern const unsigned long sysctl_long_vals[];
-
typedef int proc_handler(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
@@ -84,16 +77,17 @@ int proc_dobool(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
int proc_dointvec(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
-int proc_dointvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
- size_t *lenp, loff_t *ppos);
int proc_douintvec(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
-int proc_douintvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
- size_t *lenp, loff_t *ppos);
-int proc_dou8vec_minmax(const struct ctl_table *ctl, int dir, void *buf,
- size_t *lenp, loff_t *ppos);
-int proc_doulongvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
- size_t *lenp, loff_t *ppos);
+/* Range handlers consume numeric table bounds. */
+int proc_dointvec_minmax(const struct ctl_table *table, int dir,
+ void *buffer, size_t *lenp, loff_t *ppos);
+int proc_douintvec_minmax(const struct ctl_table *table, int dir,
+ void *buffer, size_t *lenp, loff_t *ppos);
+int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
+ void *buffer, size_t *lenp, loff_t *ppos);
+int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
+ void *buffer, size_t *lenp, loff_t *ppos);
int proc_do_large_bitmap(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_do_static_key(const struct ctl_table *ctl, int dir, void *buf,
@@ -116,15 +110,15 @@ int proc_do_static_key(const struct ctl_table *ctl, int dir, void *buf,
int proc_dointvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
- int dir, const struct ctl_table *ctl));
+ int dir, const struct ctl_table *ctl));
int proc_douintvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, uint *k_ptr,
- int dir, const struct ctl_table *ctl));
+ int dir, const struct ctl_table *ctl));
int proc_doulongvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, ulong *k_ptr,
- int dir, const struct ctl_table *ctl));
+ int dir, const struct ctl_table *ctl));
/*
* bi-directional converter functions
@@ -140,6 +134,7 @@ int proc_doulongvec_conv(const struct ctl_table *ctl, int dir, void *buf,
* { return proc_uint_conv(u_ptr, k_ptr, dir, ctl, true,
* custom_u2k, proc_uint_k2u_conv}
*/
+
int proc_int_conv(bool *negp, ulong *u_ptr, int *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const bool *negp, const ulong *u_ptr, int *k_ptr),
@@ -226,8 +221,6 @@ struct ctl_table {
umode_t mode;
proc_handler *proc_handler; /* Callback for text formatting */
struct ctl_table_poll *poll;
- void *extra1; /* Deprecated; being removed */
- void *extra2; /* Deprecated; being removed */
unsigned long min;
unsigned long max;
void *priv; /* Handler context, never used by the core */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ab25c75cb3ac..63a8a6b08090 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -22,13 +22,6 @@
#include <linux/uaccess.h>
#include <asm/processor.h>
-/* shared constants to be used in various sysctls */
-const int sysctl_vals[] = { 0, 1, 2, 3, 4, 100, 200, 1000, 3000, INT_MAX, 65535, -1 };
-EXPORT_SYMBOL(sysctl_vals);
-
-const unsigned long sysctl_long_vals[] = { 0, 1, LONG_MAX };
-EXPORT_SYMBOL_GPL(sysctl_long_vals);
-
#ifdef CONFIG_SYSCTL
/* Constants used for minimum and maximum */
@@ -423,15 +416,8 @@ int proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
ret = user_to_kern(u_ptr, &tmp_k);
if (ret)
return ret;
- if (tbl->extra1 || tbl->extra2) {
- if ((tbl->extra1 &&
- *(uint *)tbl->extra1 > tmp_k) ||
- (tbl->extra2 &&
- *(uint *)tbl->extra2 < tmp_k))
- return -ERANGE;
- } else if (tbl->min > tmp_k || tbl->max < tmp_k) {
+ if (tbl->min > tmp_k || tbl->max < tmp_k)
return -ERANGE;
- }
WRITE_ONCE(*k_ptr, tmp_k);
} else
return user_to_kern(u_ptr, k_ptr);
@@ -547,19 +533,16 @@ int proc_int_conv(bool *negp, ulong *u_ptr, int *k_ptr, int dir,
ret = user_to_kern(negp, u_ptr, &tmp_k);
if (ret)
return ret;
- if (tbl->extra1 || tbl->extra2) {
- if ((tbl->extra1 && *(int *)tbl->extra1 > tmp_k) ||
- (tbl->extra2 && *(int *)tbl->extra2 < tmp_k))
- return -EINVAL;
- } else if ((long)tbl->min > tmp_k || (long)tbl->max < tmp_k) {
+ if ((long)tbl->min > tmp_k || (long)tbl->max < tmp_k)
return -EINVAL;
- }
WRITE_ONCE(*k_ptr, tmp_k);
} else
return user_to_kern(negp, u_ptr, k_ptr);
return 0;
}
+
+
static int sysctl_user_to_kern_int_conv(const bool *negp, const ulong *u_ptr,
int *k_ptr)
{
@@ -930,7 +913,7 @@ int proc_douintvec(const struct ctl_table *table, int dir, void *buffer,
* values from/to the user buffer, treated as an ASCII string.
*
* This routine will ensure the values are within the range specified by
- * table->extra1 (min) and table->extra2 (max).
+ * table->min and table->max.
*
* Returns: %0 on success or -EINVAL when the range check fails and
* SYSCTL_USER_TO_KERN(dir) == true
@@ -955,9 +938,8 @@ int proc_dointvec_minmax(const struct ctl_table *table, int dir,
* strings are not allowed.
*
* When changing the kernel variable, this routine will ensure the values
- * are within the range specified by table->extra1 (min) and table->extra2
- * (max). And Check that the values are less than UINT_MAX to avoid having to
- * support wrap around uses from userspace.
+ * are within the range specified by table->min and table->max. Values larger
+ * than UINT_MAX are rejected to avoid wraparound from userspace.
*
* Returns: %0 on success or -ERANGE when range check failes and
* SYSCTL_USER_TO_KERN(dir) == true
@@ -982,7 +964,7 @@ int proc_douintvec_minmax(const struct ctl_table *table, int dir,
* strings are not allowed.
*
* This routine will ensure the values are within the range specified by
- * table->extra1 (min) and table->extra2 (max).
+ * table->min and table->max.
*
* Returns: %0 on success or an error on SYSCTL_USER_TO_KERN(dir) == true
* and the range check fails.
@@ -1047,13 +1029,8 @@ int proc_ulong_conv(ulong *u_ptr, ulong *k_ptr, int dir,
ret = user_to_kern(u_ptr, &tmp_k);
if (ret)
return ret;
- if (tbl->extra1 || tbl->extra2) {
- if ((tbl->extra1 && *(ulong *)tbl->extra1 > tmp_k) ||
- (tbl->extra2 && *(ulong *)tbl->extra2 < tmp_k))
- return -ERANGE;
- } else if (tbl->min > tmp_k || tbl->max < tmp_k) {
+ if (tbl->min > tmp_k || tbl->max < tmp_k)
return -ERANGE;
- }
WRITE_ONCE(*k_ptr, tmp_k);
} else
return user_to_kern(u_ptr, k_ptr);
@@ -1155,7 +1132,7 @@ int proc_doulongvec_conv(const struct ctl_table *table, int dir,
* values from/to the user buffer, treated as an ASCII string.
*
* This routine will ensure the values are within the range specified by
- * table->extra1 (min) and table->extra2 (max).
+ * table->min and table->max.
*
* Returns: %0 on success.
*/
@@ -1348,8 +1325,8 @@ int proc_do_static_key(const struct ctl_table *table, int dir,
.data = &val,
.maxlen = sizeof(val),
.mode = table->mode,
- .min = 0,
- .max = 1,
+ .min = 0,
+ .max = 1,
};
if (SYSCTL_USER_TO_KERN(dir) && !capable(CAP_SYS_ADMIN))
diff --git a/kernel/time/jiffies.c b/kernel/time/jiffies.c
index 8dde5a2cc532..184d4c5a7917 100644
--- a/kernel/time/jiffies.c
+++ b/kernel/time/jiffies.c
@@ -331,7 +331,7 @@ EXPORT_SYMBOL(proc_dointvec_ms_jiffies_minmax);
* are treated as milliseconds, and converted to jiffies when they are stored.
*
* This routine will ensure the values are within the range specified by
- * table->extra1 (min) and table->extra2 (max).
+ * table->min and table->max.
*
* Returns 0 on success.
*/
diff --git a/lib/test_sysctl.c b/lib/test_sysctl.c
index 64c82fd53975..ed3547401f41 100644
--- a/lib/test_sysctl.c
+++ b/lib/test_sysctl.c
@@ -258,18 +258,18 @@ static void test_sysctl_calc_match_int_ok(void)
int defined;
int wanted;
} match_int[] = {
- { .defined = 0, .wanted = 0 },
- { .defined = 1, .wanted = 1 },
- { .defined = 2, .wanted = 2 },
- { .defined = 3, .wanted = 3 },
- { .defined = 4, .wanted = 4 },
- { .defined = 100, .wanted = 100 },
- { .defined = 200, .wanted = 200 },
- { .defined = 1000, .wanted = 1000 },
- { .defined = 3000, .wanted = 3000 },
- { .defined = INT_MAX, .wanted = INT_MAX },
- { .defined = 65535, .wanted = 65535 },
- { .defined = -1, .wanted = -1 },
+ { .defined = SYSCTL_ZERO, .wanted = 0 },
+ { .defined = SYSCTL_ONE, .wanted = 1 },
+ { .defined = SYSCTL_TWO, .wanted = 2 },
+ { .defined = SYSCTL_THREE, .wanted = 3 },
+ { .defined = SYSCTL_FOUR, .wanted = 4 },
+ { .defined = SYSCTL_ONE_HUNDRED, .wanted = 100 },
+ { .defined = SYSCTL_TWO_HUNDRED, .wanted = 200 },
+ { .defined = SYSCTL_ONE_THOUSAND, .wanted = 1000 },
+ { .defined = SYSCTL_THREE_THOUSAND, .wanted = 3000 },
+ { .defined = SYSCTL_INT_MAX, .wanted = INT_MAX },
+ { .defined = SYSCTL_MAXOLDUID, .wanted = 65535 },
+ { .defined = SYSCTL_NEG_ONE, .wanted = -1 },
};
for (i = 0; i < ARRAY_SIZE(match_int); i++)
--
2.25.1
prev parent reply other threads:[~2026-10-28 16:39 UTC|newest]
Thread overview: 41+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 16:34 [RFC PATCH 00/39] sysctl: replace overloaded extra pointers with typed bounds and context wen.yang
2026-10-28 16:34 ` [RFC PATCH 01/39] " wen.yang
2026-10-28 21:09 ` David Laight
2026-10-28 16:34 ` [RFC PATCH 02/39] test_sysctl: convert bounds to numeric values wen.yang
2026-10-28 16:34 ` [RFC PATCH 03/39] sysctl: add KUnit coverage for numeric bounds and handlers wen.yang
2026-10-28 16:34 ` [RFC PATCH 04/39] sysctl: cover runtime ranges and context lifecycles in KUnit wen.yang
2026-10-28 16:34 ` [RFC PATCH 05/39] sysctl: cover priv in KUnit and the debug test module wen.yang
2026-10-28 16:34 ` [RFC PATCH 06/39] sysctl: convert core table bounds to numeric values wen.yang
2026-10-28 16:34 ` [RFC PATCH 07/39] sysctl: store architecture sysctl bounds by value wen.yang
2026-10-28 16:34 ` [RFC PATCH 08/39] sysctl: store crypto " wen.yang
2026-10-28 16:34 ` [RFC PATCH 09/39] sysctl: store device " wen.yang
2026-10-28 16:34 ` [RFC PATCH 10/39] sysctl: store filesystem " wen.yang
2026-10-28 16:34 ` [RFC PATCH 11/39] sysctl: store message-queue " wen.yang
2026-10-28 16:34 ` [RFC PATCH 12/39] sysctl: store kernel " wen.yang
2026-10-28 16:34 ` [RFC PATCH 13/39] sysctl: store memory-management " wen.yang
2026-10-28 16:34 ` [RFC PATCH 14/39] sysctl: store IPv6 scalar " wen.yang
2026-10-28 16:34 ` [RFC PATCH 15/39] sysctl: store netfilter " wen.yang
2026-10-28 16:34 ` [RFC PATCH 16/39] sysctl: store RPC " wen.yang
2026-10-28 16:34 ` [RFC PATCH 17/39] sysctl: store remaining network " wen.yang
2026-10-28 16:34 ` [RFC PATCH 18/39] sysctl: store security " wen.yang
2026-10-28 16:34 ` [RFC PATCH 19/39] io_uring: store its " wen.yang
2026-10-28 16:34 ` [RFC PATCH 20/39] sysctl: refresh dynamic scheduler and PID bounds per call wen.yang
2026-10-28 16:35 ` [RFC PATCH 21/39] sysctl: refresh device-dependent " wen.yang
2026-10-28 16:35 ` [RFC PATCH 22/39] sysctl: refresh namespace IPC " wen.yang
2026-10-28 16:35 ` [RFC PATCH 23/39] yama: preserve scope locking with numeric sysctl bounds wen.yang
2026-10-28 16:35 ` [RFC PATCH 24/39] net: refresh core sysctl limits without bound pointers wen.yang
2026-10-28 16:35 ` [RFC PATCH 25/39] sctp: resolve numeric ranges from the current namespace wen.yang
2026-10-28 16:35 ` [RFC PATCH 26/39] rds: preserve live reconnect limits with numeric bounds wen.yang
2026-10-28 16:35 ` [RFC PATCH 27/39] ipv4: preserve live and vector bounds with numeric sysctls wen.yang
2026-10-28 16:35 ` [RFC PATCH 28/39] net: refresh fragment and remaining dynamic sysctl bounds wen.yang
2026-10-28 16:35 ` [RFC PATCH 29/39] neighbour: derive sysctl ownership independently of bounds wen.yang
2026-10-28 16:35 ` [RFC PATCH 30/39] net: resolve sysctl owners from their backing data wen.yang
2026-10-28 16:35 ` [RFC PATCH 31/39] ipvs: derive sysctl ownership from numeric storage wen.yang
2026-10-28 16:35 ` [RFC PATCH 32/39] sysctl: remove obsolete nr_open bound variables wen.yang
2026-10-28 16:35 ` [RFC PATCH 33/39] ipv6: move address sysctl context to priv wen.yang
2026-10-28 16:35 ` [RFC PATCH 34/39] ipv4: move device " wen.yang
2026-10-28 16:35 ` [RFC PATCH 35/39] netfilter: move logger " wen.yang
2026-10-28 16:35 ` [RFC PATCH 36/39] parport: move device " wen.yang
2026-10-28 16:35 ` [RFC PATCH 37/39] net: move namespace " wen.yang
2026-10-28 16:35 ` [RFC PATCH 38/39] arm64: move vector-length " wen.yang
2026-10-28 16:35 ` wen.yang [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b6e4cbd509687301a8ee2106f19a3ac01e7671a6.1793204511.git.wen.yang@linux.dev \
--to=wen.yang@linux.dev \
--cc=joel.granados@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®