From ea053e164cc812f0c00a58cbbf8c65e27ceb6148 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 19 Jun 2019 12:30:13 -0400 Subject: nfsd: escape high characters in binary data I'm exposing some information about NFS clients in pseudofiles. I expect to eventually have simple tools to help read those pseudofiles. But it's also helpful if the raw files are human-readable to the extent possible. It aids debugging and makes them usable on systems that don't have the latest nfs-utils. A minor challenge there is opaque client-generated protocol objects like state owners and client identifiers. Some clients generate those to include handy information in plain ascii. But they may also include arbitrary byte sequences. I think the simplest approach is to limit to isprint(c) && isascii(c) and escape everything else. That means you can just cat the file and get something that looks OK. Also, I'm trying to keep these files legal YAML, which requires them to UTF-8, and this is a simple way to guarantee that. Acked-by: Kees Cook Signed-off-by: J. Bruce Fields --- lib/string_helpers.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'lib/string_helpers.c') diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 4403e1924f73..3a90a9e2b94a 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -540,6 +540,25 @@ int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz, } EXPORT_SYMBOL(string_escape_mem); +int string_escape_mem_ascii(const char *src, size_t isz, char *dst, + size_t osz) +{ + char *p = dst; + char *end = p + osz; + + while (isz--) { + unsigned char c = *src++; + + if (!isprint(c) || !isascii(c) || c == '"' || c == '\\') + escape_hex(c, &p, end); + else + escape_passthrough(c, &p, end); + } + + return p - dst; +} +EXPORT_SYMBOL(string_escape_mem_ascii); + /* * Return an allocated string that has been escaped of special characters * and double quotes, making it safe to log in quotes. -- cgit From b4658cdd8cab49c978334dc5db9070d0d881e3dd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Tue, 16 Jul 2019 16:27:36 -0700 Subject: lib/string_helpers: fix some kerneldoc warnings Due to some sad limitations in how kerneldoc comments are parsed, the documentation in lib/string_helpers.c generates these warnings: lib/string_helpers.c:236: WARNING: Unexpected indentation. lib/string_helpers.c:241: WARNING: Block quote ends without a blank line; unexpected unindent. lib/string_helpers.c:446: WARNING: Unexpected indentation. lib/string_helpers.c:451: WARNING: Block quote ends without a blank line; unexpected unindent. lib/string_helpers.c:474: WARNING: Unexpected indentation. Rework the comments to obtain something like the desired result. Link: http://lkml.kernel.org/r/20190607110952.409011ba@lwn.net Signed-off-by: Jonathan Corbet Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/string_helpers.c | 77 +++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) (limited to 'lib/string_helpers.c') diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 3a90a9e2b94a..963050c0283e 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -231,35 +231,36 @@ static bool unescape_special(char **src, char **dst) * @src: source buffer (escaped) * @dst: destination buffer (unescaped) * @size: size of the destination buffer (0 to unlimit) - * @flags: combination of the flags (bitwise OR): - * %UNESCAPE_SPACE: + * @flags: combination of the flags. + * + * Description: + * The function unquotes characters in the given string. + * + * Because the size of the output will be the same as or less than the size of + * the input, the transformation may be performed in place. + * + * Caller must provide valid source and destination pointers. Be aware that + * destination buffer will always be NULL-terminated. Source string must be + * NULL-terminated as well. The supported flags are:: + * + * UNESCAPE_SPACE: * '\f' - form feed * '\n' - new line * '\r' - carriage return * '\t' - horizontal tab * '\v' - vertical tab - * %UNESCAPE_OCTAL: + * UNESCAPE_OCTAL: * '\NNN' - byte with octal value NNN (1 to 3 digits) - * %UNESCAPE_HEX: + * UNESCAPE_HEX: * '\xHH' - byte with hexadecimal value HH (1 to 2 digits) - * %UNESCAPE_SPECIAL: + * UNESCAPE_SPECIAL: * '\"' - double quote * '\\' - backslash * '\a' - alert (BEL) * '\e' - escape - * %UNESCAPE_ANY: + * UNESCAPE_ANY: * all previous together * - * Description: - * The function unquotes characters in the given string. - * - * Because the size of the output will be the same as or less than the size of - * the input, the transformation may be performed in place. - * - * Caller must provide valid source and destination pointers. Be aware that - * destination buffer will always be NULL-terminated. Source string must be - * NULL-terminated as well. - * * Return: * The amount of the characters processed to the destination buffer excluding * trailing '\0' is returned. @@ -441,7 +442,29 @@ static bool escape_hex(unsigned char c, char **dst, char *end) * @isz: source buffer size * @dst: destination buffer (escaped) * @osz: destination buffer size - * @flags: combination of the flags (bitwise OR): + * @flags: combination of the flags + * @only: NULL-terminated string containing characters used to limit + * the selected escape class. If characters are included in @only + * that would not normally be escaped by the classes selected + * in @flags, they will be copied to @dst unescaped. + * + * Description: + * The process of escaping byte buffer includes several parts. They are applied + * in the following sequence. + * + * 1. The character is matched to the printable class, if asked, and in + * case of match it passes through to the output. + * 2. The character is not matched to the one from @only string and thus + * must go as-is to the output. + * 3. The character is checked if it falls into the class given by @flags. + * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any + * character. Note that they actually can't go together, otherwise + * %ESCAPE_HEX will be ignored. + * + * Caller must provide valid source and destination pointers. Be aware that + * destination buffer will not be NULL-terminated, thus caller have to append + * it if needs. The supported flags are:: + * * %ESCAPE_SPACE: (special white space, not space itself) * '\f' - form feed * '\n' - new line @@ -464,26 +487,6 @@ static bool escape_hex(unsigned char c, char **dst, char *end) * all previous together * %ESCAPE_HEX: * '\xHH' - byte with hexadecimal value HH (2 digits) - * @only: NULL-terminated string containing characters used to limit - * the selected escape class. If characters are included in @only - * that would not normally be escaped by the classes selected - * in @flags, they will be copied to @dst unescaped. - * - * Description: - * The process of escaping byte buffer includes several parts. They are applied - * in the following sequence. - * 1. The character is matched to the printable class, if asked, and in - * case of match it passes through to the output. - * 2. The character is not matched to the one from @only string and thus - * must go as-is to the output. - * 3. The character is checked if it falls into the class given by @flags. - * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any - * character. Note that they actually can't go together, otherwise - * %ESCAPE_HEX will be ignored. - * - * Caller must provide valid source and destination pointers. Be aware that - * destination buffer will not be NULL-terminated, thus caller have to append - * it if needs. * * Return: * The total size of the escaped output that would be generated for -- cgit