From 9b9aa9a6e9bc50cb5828fa31ed0a9a050e102d0c Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 8 Jun 2018 13:26:46 +0200 Subject: [PATCH 1/4] docs: fix "delimeter" typo in fprocopen man page --- proc/fprocopen.3 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proc/fprocopen.3 b/proc/fprocopen.3 index 043b0b80..020a1177 100644 --- a/proc/fprocopen.3 +++ b/proc/fprocopen.3 @@ -48,13 +48,13 @@ the beginning of the file. .BR w [ ] Open a file below .I /proc/## -for writing even large buffers. The optional delimeter character +for writing even large buffers. The optional delimiter character can be one of the follwoing .BR '\ ' ,\ ',' ,\ '.' ,\ and\ ':' where the default is the colon .BR ',' . This allows to split very large input lines into pieces at this -delimeter and write each of them to the opened file below +delimiter and write each of them to the opened file below .IR /proc/## . .TP .B e From 32720b2ee6c36b84005a002def17e79e3ab009e1 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Fri, 8 Jun 2018 13:27:20 +0200 Subject: [PATCH 2/4] procio: use the user-supplied delimiter to split large input The `fprocopen` function allows users to specify a delimiter chacter that is used to split very large input lines into smaller chunks. While the code checks that the caller did actually supply the delimiter, it is in fact never used to split the string. Instead, the hardcoded default character ',' is always used to split the string. Fix the issue by using `cookie->delim` instead. --- procio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procio.c b/procio.c index ad9b4de6..2813cd51 100644 --- a/procio.c +++ b/procio.c @@ -249,7 +249,7 @@ ssize_t proc_write(void *c, const char *buf, size_t count) do { token = NULL; if (cookie->offset > LINELEN) - token = (char*)memrchr(cookie->buf+offset, ',', LINELEN); + token = (char*)memrchr(cookie->buf+offset, cookie->delim, LINELEN); else token = (char*)memrchr(cookie->buf+offset, '\n', LINELEN); if (token) From 3eb4b5375f7ffca0e21fac479dfa688cae936641 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 29 May 2018 13:20:00 +0200 Subject: [PATCH 3/4] procio: fix potential out-of-bounds access when write fails When writing to procfs via `proc_write` fails, we try to chunk the buffer into smaller pieces to work around that issue. When searching for the next location to split the buffer, though, we can underflow the buffer in case the current offset is smaller than `LINELEN`. Fix the issue by passing `cookie->offset` instead of `LINELEN` into `memrchr` in case `cookie->offset` is smaller than `LINELEN`. This bug can be triggered on musl-based systems, e.g. by executing $ sysctl kernel.printk_ratelimit=1000000000000000 As the value is out-of-range, `write` will return an error and set `errno` to `EINVAL`. As we're only trying to write a smallish buffer with a length smaller than `LINELEN` and as the buffer does not contain any newlines, the call token = (char*)memrchr(cookie->buf+offset, '\n', LINELEN); will underflow the buffer and crash the program. Signed-off-by: Patrick Steinhardt --- procio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/procio.c b/procio.c index 2813cd51..f3258ff6 100644 --- a/procio.c +++ b/procio.c @@ -251,7 +251,7 @@ ssize_t proc_write(void *c, const char *buf, size_t count) if (cookie->offset > LINELEN) token = (char*)memrchr(cookie->buf+offset, cookie->delim, LINELEN); else - token = (char*)memrchr(cookie->buf+offset, '\n', LINELEN); + token = (char*)memrchr(cookie->buf+offset, '\n', cookie->offset); if (token) *token = '\n'; else { From da82fe49b1476d227874905068adb69577e11d96 Mon Sep 17 00:00:00 2001 From: Patrick Steinhardt Date: Tue, 29 May 2018 13:29:03 +0200 Subject: [PATCH 4/4] sysctl: do not report set key in case `close_stream` fails As we're using buffered I/O when writing kernel parameters, write errors may get delayed until we close the `FILE` stream. As we are currently outputting the key that is to be set disregarding the return value of `close_stream`, we may end up in a situation where we report error and success: $ sysctl kernel.printk_ratelimit=100000000000000 sysctl: setting key "kernel.printk_ratelimit": error code 22 kernel.printk_ratelimit = 100000000000000 Fix the issue by only outputting the updated value in case `close_stream` does not report an error. Signed-off-by: Patrick Steinhardt --- sysctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sysctl.c b/sysctl.c index 2371ca9a..2172759c 100644 --- a/sysctl.c +++ b/sysctl.c @@ -465,7 +465,7 @@ static int WriteSetting(const char *setting) rc = 0; if (close_stream(fp) != 0) xwarn(_("setting key \"%s\""), outname); - if (rc == 0 && !Quiet) { + else if (rc == 0 && !Quiet) { if (NameOnly) { fprintf(stdout, "%s\n", outname); } else {