From: "Luis R. Rodriguez" <mcgrof@kernel.org>
To: akpm@linux-foundation.org, acme@redhat.com, mingo@kernel.org,
mgorman@suse.de, subashab@codeaurora.org
Cc: jeyu@redhat.com, rusty@rustcorp.com.au, matt@codeblueprint.co.uk,
adobriyan@gmail.com, bp@suse.de, ebiederm@xmission.com,
dmitry.torokhov@gmail.com, shuah@kernel.org,
torvalds@linux-foundation.org, linux-kselftest@vger.kernel.org,
linux-kernel@vger.kernel.org,
"Luis R. Rodriguez" <mcgrof@kernel.org>,
Heinrich Schuchardt <xypron.glpk@gmx.de>,
Kees Cook <keescook@chromium.org>,
"David S. Miller" <davem@davemloft.net>,
Ingo Molnar <mingo@redhat.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subject: [PATCH] sysctl: add proper unsigned int support
Date: Sun, 29 Jan 2017 11:29:09 -0800 [thread overview]
Message-ID: <20170129192909.8626-1-mcgrof@kernel.org> (raw)
Commit e7d316a02f6838 ("sysctl: handle error writing UINT_MAX to u32 fields")
added proc_douintvec() to start help adding support for unsigned int,
this however was only half the work needed, all these issues are present
with the current implementation:
o Printing the values shows a negative value, this happens
since do_proc_dointvec() and this uses proc_put_long()
o We can easily wrap around the int values: UINT_MAX is
4294967295, if we echo in 4294967295 + 1 we end up with 0,
using 4294967295 + 2 we end up with 1.
o We echo negative values in and they are accepted
Fix all these issues by adding our own do_proc_douintvec().
Cc: Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
Cc: Heinrich Schuchardt <xypron.glpk@gmx.de>
Cc: Kees Cook <keescook@chromium.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Fixes: e7d316a02f68 ("sysctl: handle error writing UINT_MAX to u32 fields")
Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org>
---
I split this off as its own atomic fix from a larger RFC series [0].
I've only provided the fix here, and split off further functionality
into a separate patch for the future. Although this is a fix I don't think
its super critical, and specially due to its size do not think it can
be stable material.
I do have proc_douintvec_minmax() but since we have no users for it
it can wait until I add something that makes use of it. If someone
needs it now though please let me know.
Likewise adding proc_douintvec_minmax_sysadmin() is very trivial but I have no
immediate users for it so it can wait even longer.
[0] https://lkml.kernel.org/r/20161208184801.1689-1-mcgrof@kernel.org
kernel/sysctl.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 115 insertions(+), 6 deletions(-)
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8dbaec0e4f7f..118341d3a139 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2125,12 +2125,12 @@ static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp,
return 0;
}
-static int do_proc_douintvec_conv(bool *negp, unsigned long *lvalp,
- int *valp,
- int write, void *data)
+static int do_proc_douintvec_conv(unsigned long *lvalp,
+ unsigned int *valp,
+ int write, void *data)
{
if (write) {
- if (*negp)
+ if (*lvalp > (unsigned long) UINT_MAX)
return -EINVAL;
*valp = *lvalp;
} else {
@@ -2243,6 +2243,115 @@ static int do_proc_dointvec(struct ctl_table *table, int write,
buffer, lenp, ppos, conv, data);
}
+static int __do_proc_douintvec(void *tbl_data, struct ctl_table *table,
+ int write, void __user *buffer,
+ size_t *lenp, loff_t *ppos,
+ int (*conv)(unsigned long *lvalp,
+ unsigned int *valp,
+ int write, void *data),
+ void *data)
+{
+ unsigned int *i, vleft;
+ bool first = true;
+ int err = 0;
+ size_t left;
+ char *kbuf = NULL, *p;
+
+ if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) {
+ *lenp = 0;
+ return 0;
+ }
+
+ i = (unsigned int *) tbl_data;
+ vleft = table->maxlen / sizeof(*i);
+ left = *lenp;
+
+ if (!conv)
+ conv = do_proc_douintvec_conv;
+
+ if (write) {
+ if (*ppos) {
+ switch (sysctl_writes_strict) {
+ case SYSCTL_WRITES_STRICT:
+ goto out;
+ case SYSCTL_WRITES_WARN:
+ warn_sysctl_write(table);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (left > PAGE_SIZE - 1)
+ left = PAGE_SIZE - 1;
+ p = kbuf = memdup_user_nul(buffer, left);
+ if (IS_ERR(kbuf))
+ return PTR_ERR(kbuf);
+ }
+
+ for (; left && vleft--; i++, first=false) {
+ unsigned long lval;
+ bool neg;
+
+ if (write) {
+ left -= proc_skip_spaces(&p);
+
+ if (!left)
+ break;
+ err = proc_get_long(&p, &left, &lval, &neg,
+ proc_wspace_sep,
+ sizeof(proc_wspace_sep), NULL);
+ if (neg) {
+ err = -EINVAL;
+ break;
+ }
+ if (err)
+ break;
+ if (conv(&lval, i, 1, data)) {
+ err = -EINVAL;
+ break;
+ }
+ } else {
+ if (conv(&lval, i, 0, data)) {
+ err = -EINVAL;
+ break;
+ }
+ if (!first)
+ err = proc_put_char(&buffer, &left, '\t');
+ if (err)
+ break;
+ err = proc_put_long(&buffer, &left, lval, false);
+ if (err)
+ break;
+ }
+ }
+
+ if (!write && !first && left && !err)
+ err = proc_put_char(&buffer, &left, '\n');
+ if (write && !err && left)
+ left -= proc_skip_spaces(&p);
+ if (write) {
+ kfree(kbuf);
+ if (first)
+ return err ? : -EINVAL;
+ }
+ *lenp -= left;
+out:
+ *ppos += *lenp;
+ return err;
+}
+
+static int do_proc_douintvec(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp, loff_t *ppos,
+ int (*conv)(unsigned long *lvalp,
+ unsigned int *valp,
+ int write, void *data),
+ void *data)
+{
+ return __do_proc_douintvec(table->data, table, write,
+ buffer, lenp, ppos, conv, data);
+}
+
/**
* proc_dointvec - read a vector of integers
* @table: the sysctl table
@@ -2278,8 +2387,8 @@ int proc_dointvec(struct ctl_table *table, int write,
int proc_douintvec(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
- return do_proc_dointvec(table, write, buffer, lenp, ppos,
- do_proc_douintvec_conv, NULL);
+ return do_proc_douintvec(table, write, buffer, lenp, ppos,
+ do_proc_douintvec_conv, NULL);
}
/*
--
2.11.0
next reply other threads:[~2017-01-29 20:24 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-01-29 19:29 Luis R. Rodriguez [this message]
2017-01-30 12:56 ` [PATCH] sysctl: add proper unsigned int support Alexey Dobriyan
2017-02-01 19:56 ` Luis R. Rodriguez
2017-02-09 1:28 ` Luis R. Rodriguez
2017-02-09 1:32 ` Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 0/9] sysctl: add and fix " Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 1/9] sysctl: fix lax sysctl_check_table() sanity check Luis R. Rodriguez
2017-02-13 20:13 ` Kees Cook
2017-02-11 0:36 ` [PATCH v2 2/9] sysctl: add proper unsigned int support Luis R. Rodriguez
2017-02-13 20:19 ` Kees Cook
2017-05-16 22:25 ` Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 3/9] sysctl: add unsigned int range support Luis R. Rodriguez
2017-02-13 20:21 ` Kees Cook
2017-02-11 0:36 ` [PATCH v2 4/9] test_sysctl: add dedicated proc sysctl test driver Luis R. Rodriguez
2017-02-13 20:27 ` Kees Cook
2017-02-11 0:36 ` [PATCH v2 5/9] test_sysctl: add generic script to expand on tests Luis R. Rodriguez
2017-02-13 20:30 ` Kees Cook
2017-05-16 22:55 ` Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 6/9] test_sysctl: test against PAGE_SIZE for int Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 7/9] test_sysctl: add simple proc_dointvec() case Luis R. Rodriguez
2017-02-13 22:00 ` Kees Cook
2017-05-16 22:46 ` Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 8/9] test_sysctl: add simple proc_douintvec() case Luis R. Rodriguez
2017-02-11 0:36 ` [PATCH v2 9/9] test_sysctl: test against int proc_dointvec() array support Luis R. Rodriguez
2017-02-13 22:07 ` Kees Cook
2017-05-16 22:40 ` Luis R. Rodriguez
2017-02-13 20:11 ` [PATCH v2 0/9] sysctl: add and fix proper unsigned int support Kees Cook
2017-05-19 3:35 ` [PATCH v3 0/5] sysctl: few fixes Luis R. Rodriguez
2017-05-19 3:35 ` [PATCH v3 1/5] sysctl: fix lax sysctl_check_table() sanity check Luis R. Rodriguez
2017-05-22 22:40 ` Andrew Morton
2017-05-19 3:35 ` [PATCH v3 2/5] sysctl: kdoc'ify sysctl_writes_strict Luis R. Rodriguez
2017-05-19 3:35 ` [PATCH v3 3/5] sysctl: fold sysctl_writes_strict checks into helper Luis R. Rodriguez
2017-05-19 3:35 ` [PATCH v3 4/5] sysctl: simplify unsigned int support Luis R. Rodriguez
2017-05-19 3:35 ` [PATCH v3 5/5] sysctl: add unsigned int range support Luis R. Rodriguez
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=20170129192909.8626-1-mcgrof@kernel.org \
--to=mcgrof@kernel.org \
--cc=acme@redhat.com \
--cc=adobriyan@gmail.com \
--cc=akpm@linux-foundation.org \
--cc=bp@suse.de \
--cc=davem@davemloft.net \
--cc=dmitry.torokhov@gmail.com \
--cc=ebiederm@xmission.com \
--cc=gregkh@linuxfoundation.org \
--cc=jeyu@redhat.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=matt@codeblueprint.co.uk \
--cc=mgorman@suse.de \
--cc=mingo@kernel.org \
--cc=mingo@redhat.com \
--cc=rusty@rustcorp.com.au \
--cc=shuah@kernel.org \
--cc=subashab@codeaurora.org \
--cc=torvalds@linux-foundation.org \
--cc=xypron.glpk@gmx.de \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.