string_helpers: add kstrdup_quotable_cmdline

Provide an escaped (but readable: no inter-argument NULLs) commandline
safe for logging.

Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: James Morris <james.l.morris@oracle.com>
This commit is contained in:
Kees Cook 2016-04-20 15:46:24 -07:00 committed by James Morris
parent b53f27e4fa
commit 0d0443288f
2 changed files with 35 additions and 0 deletions

View file

@ -69,5 +69,6 @@ static inline int string_escape_str_any_np(const char *src, char *dst,
}
char *kstrdup_quotable(const char *src, gfp_t gfp);
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp);
#endif

View file

@ -10,6 +10,7 @@
#include <linux/export.h>
#include <linux/ctype.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/string_helpers.h>
@ -562,3 +563,36 @@ char *kstrdup_quotable(const char *src, gfp_t gfp)
return dst;
}
EXPORT_SYMBOL_GPL(kstrdup_quotable);
/*
* Returns allocated NULL-terminated string containing process
* command line, with inter-argument NULLs replaced with spaces,
* and other special characters escaped.
*/
char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp)
{
char *buffer, *quoted;
int i, res;
buffer = kmalloc(PAGE_SIZE, GFP_TEMPORARY);
if (!buffer)
return NULL;
res = get_cmdline(task, buffer, PAGE_SIZE - 1);
buffer[res] = '\0';
/* Collapse trailing NULLs, leave res pointing to last non-NULL. */
while (--res >= 0 && buffer[res] == '\0')
;
/* Replace inter-argument NULLs. */
for (i = 0; i <= res; i++)
if (buffer[i] == '\0')
buffer[i] = ' ';
/* Make sure result is printable. */
quoted = kstrdup_quotable(buffer, gfp);
kfree(buffer);
return quoted;
}
EXPORT_SYMBOL_GPL(kstrdup_quotable_cmdline);