aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-11-06 02:52:12 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-11-06 04:46:23 -0500
commitd99f160ac53e51090f015a8f0617cea25f81a191 (patch)
treea78f1169a937d211e8a02703e1e4ed9cc0edbef8
parent0e009be8a0c2309f3696df70f72ef0075aa34c9c (diff)
[PATCH] sysctl: allow a zero ctl_name in the middle of a sysctl table
Since it is becoming clear that there are just enough users of the binary sysctl interface that completely removing the binary interface from the kernel will not be an option for foreseeable future, we need to find a way to address the sysctl maintenance issues. The basic problem is that sysctl requires one central authority to allocate sysctl numbers, or else conflicts and ABI breakage occur. The proc interface to sysctl does not have that problem, as names are not densely allocated. By not terminating a sysctl table until I have neither a ctl_name nor a procname, it becomes simple to add sysctl entries that don't show up in the binary sysctl interface. Which allows people to avoid allocating a binary sysctl value when not needed. I have audited the kernel code and in my reading I have not found a single sysctl table that wasn't terminated by a completely zero filled entry. So this change in behavior should not affect anything. I think this mechanism eases the pain enough that combined with a little disciple we can solve the reoccurring sysctl ABI breakage. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--include/linux/sysctl.h9
-rw-r--r--kernel/sysctl.c8
2 files changed, 11 insertions, 6 deletions
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index 1b24bd45e080..c184732a70fc 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -961,8 +961,8 @@ extern ctl_handler sysctl_ms_jiffies;
961/* 961/*
962 * Register a set of sysctl names by calling register_sysctl_table 962 * Register a set of sysctl names by calling register_sysctl_table
963 * with an initialised array of ctl_table's. An entry with zero 963 * with an initialised array of ctl_table's. An entry with zero
964 * ctl_name terminates the table. table->de will be set up by the 964 * ctl_name and NULL procname terminates the table. table->de will be
965 * registration and need not be initialised in advance. 965 * set up by the registration and need not be initialised in advance.
966 * 966 *
967 * sysctl names can be mirrored automatically under /proc/sys. The 967 * sysctl names can be mirrored automatically under /proc/sys. The
968 * procname supplied controls /proc naming. 968 * procname supplied controls /proc naming.
@@ -973,7 +973,10 @@ extern ctl_handler sysctl_ms_jiffies;
973 * Leaf nodes in the sysctl tree will be represented by a single file 973 * Leaf nodes in the sysctl tree will be represented by a single file
974 * under /proc; non-leaf nodes will be represented by directories. A 974 * under /proc; non-leaf nodes will be represented by directories. A
975 * null procname disables /proc mirroring at this node. 975 * null procname disables /proc mirroring at this node.
976 * 976 *
977 * sysctl entries with a zero ctl_name will not be available through
978 * the binary sysctl interface.
979 *
977 * sysctl(2) can automatically manage read and write requests through 980 * sysctl(2) can automatically manage read and write requests through
978 * the sysctl table. The data and maxlen fields of the ctl_table 981 * the sysctl table. The data and maxlen fields of the ctl_table
979 * struct enable minimal validation of the values being written to be 982 * struct enable minimal validation of the values being written to be
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 0c8e805bbd6f..09e569f4792b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1315,7 +1315,9 @@ repeat:
1315 return -ENOTDIR; 1315 return -ENOTDIR;
1316 if (get_user(n, name)) 1316 if (get_user(n, name))
1317 return -EFAULT; 1317 return -EFAULT;
1318 for ( ; table->ctl_name; table++) { 1318 for ( ; table->ctl_name || table->procname; table++) {
1319 if (!table->ctl_name)
1320 continue;
1319 if (n == table->ctl_name || table->ctl_name == CTL_ANY) { 1321 if (n == table->ctl_name || table->ctl_name == CTL_ANY) {
1320 int error; 1322 int error;
1321 if (table->child) { 1323 if (table->child) {
@@ -1532,7 +1534,7 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root,
1532 int len; 1534 int len;
1533 mode_t mode; 1535 mode_t mode;
1534 1536
1535 for (; table->ctl_name; table++) { 1537 for (; table->ctl_name || table->procname; table++) {
1536 /* Can't do anything without a proc name. */ 1538 /* Can't do anything without a proc name. */
1537 if (!table->procname) 1539 if (!table->procname)
1538 continue; 1540 continue;
@@ -1579,7 +1581,7 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root,
1579static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root) 1581static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
1580{ 1582{
1581 struct proc_dir_entry *de; 1583 struct proc_dir_entry *de;
1582 for (; table->ctl_name; table++) { 1584 for (; table->ctl_name || table->procname; table++) {
1583 if (!(de = table->de)) 1585 if (!(de = table->de))
1584 continue; 1586 continue;
1585 if (de->mode & S_IFDIR) { 1587 if (de->mode & S_IFDIR) {