aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/proc_sysctl.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <mcgrof@kernel.org>2017-07-12 17:33:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-07-12 19:26:00 -0400
commit89c5b53b16bf577079d4f0311406dbea3c71202c (patch)
treea1733f0374ba74c88d0efc8011385d06780397c9 /fs/proc/proc_sysctl.c
parenta711bdc095d2c9b6ad15e737d1cdc46409b09538 (diff)
sysctl: fix lax sysctl_check_table() sanity check
Patch series "sysctl: few fixes", v5. I've been working on making kmod more deterministic, and as I did that I couldn't help but notice a few issues with sysctl. My end goal was just to fix unsigned int support, which back then was completely broken. Liping Zhang has sent up small atomic fixes, however it still missed yet one more fix and Alexey Dobriyan had also suggested to just drop array support given its complexity. I have inspected array support using Coccinelle and indeed its not that popular, so if in fact we can avoid it for new interfaces, I agree its best. I did develop a sysctl stress driver but will hold that off for another series. This patch (of 5): Commit 7c60c48f58a7 ("sysctl: Improve the sysctl sanity checks") improved sanity checks considerbly, however the enhancements on sysctl_check_table() meant adding a functional change so that only the last table entry's sanity error is propagated. It also changed the way errors were propagated so that each new check reset the err value, this means only last sanity check computed is used for an error. This has been in the kernel since v3.4 days. Fix this by carrying on errors from previous checks and iterations as we traverse the table and ensuring we keep any error from previous checks. We keep iterating on the table even if an error is found so we can complain for all errors found in one shot. This works as -EINVAL is always returned on error anyway, and the check for error is any non-zero value. Fixes: 7c60c48f58a7 ("sysctl: Improve the sysctl sanity checks") Link: http://lkml.kernel.org/r/20170519033554.18592-2-mcgrof@kernel.org Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Alexey Dobriyan <adobriyan@gmail.com> Cc: Kees Cook <keescook@chromium.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc/proc_sysctl.c')
-rw-r--r--fs/proc/proc_sysctl.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index 67985a7233c2..32c9c5630507 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -1066,7 +1066,7 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
1066 int err = 0; 1066 int err = 0;
1067 for (; table->procname; table++) { 1067 for (; table->procname; table++) {
1068 if (table->child) 1068 if (table->child)
1069 err = sysctl_err(path, table, "Not a file"); 1069 err |= sysctl_err(path, table, "Not a file");
1070 1070
1071 if ((table->proc_handler == proc_dostring) || 1071 if ((table->proc_handler == proc_dostring) ||
1072 (table->proc_handler == proc_dointvec) || 1072 (table->proc_handler == proc_dointvec) ||
@@ -1078,15 +1078,15 @@ static int sysctl_check_table(const char *path, struct ctl_table *table)
1078 (table->proc_handler == proc_doulongvec_minmax) || 1078 (table->proc_handler == proc_doulongvec_minmax) ||
1079 (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) { 1079 (table->proc_handler == proc_doulongvec_ms_jiffies_minmax)) {
1080 if (!table->data) 1080 if (!table->data)
1081 err = sysctl_err(path, table, "No data"); 1081 err |= sysctl_err(path, table, "No data");
1082 if (!table->maxlen) 1082 if (!table->maxlen)
1083 err = sysctl_err(path, table, "No maxlen"); 1083 err |= sysctl_err(path, table, "No maxlen");
1084 } 1084 }
1085 if (!table->proc_handler) 1085 if (!table->proc_handler)
1086 err = sysctl_err(path, table, "No proc_handler"); 1086 err |= sysctl_err(path, table, "No proc_handler");
1087 1087
1088 if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode) 1088 if ((table->mode & (S_IRUGO|S_IWUGO)) != table->mode)
1089 err = sysctl_err(path, table, "bogus .mode 0%o", 1089 err |= sysctl_err(path, table, "bogus .mode 0%o",
1090 table->mode); 1090 table->mode);
1091 } 1091 }
1092 return err; 1092 return err;