]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
nfsd: escape high characters in binary data
authorJ. Bruce Fields <bfields@redhat.com>
Wed, 19 Jun 2019 16:30:13 +0000 (12:30 -0400)
committerJ. Bruce Fields <bfields@redhat.com>
Wed, 3 Jul 2019 21:52:50 +0000 (17:52 -0400)
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 <keescook@chromium.org>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
fs/seq_file.c
include/linux/seq_file.h
include/linux/string_helpers.h
lib/string_helpers.c

index abe27ec431766f9ae05cd0b87c6acf3f680f2981..04f09689cd6d5bfb23b9757b7cb01fd1af180924 100644 (file)
@@ -384,6 +384,17 @@ void seq_escape(struct seq_file *m, const char *s, const char *esc)
 }
 EXPORT_SYMBOL(seq_escape);
 
+void seq_escape_mem_ascii(struct seq_file *m, const char *src, size_t isz)
+{
+       char *buf;
+       size_t size = seq_get_buf(m, &buf);
+       int ret;
+
+       ret = string_escape_mem_ascii(src, isz, buf, size);
+       seq_commit(m, ret < size ? ret : -1);
+}
+EXPORT_SYMBOL(seq_escape_mem_ascii);
+
 void seq_vprintf(struct seq_file *m, const char *f, va_list args)
 {
        int len;
index a121982af0f5b1cd0fd1439e2abf13333702d426..5998e1f4ff06fcd78f713a0eb8e8ab3562ae0cff 100644 (file)
@@ -127,6 +127,7 @@ void seq_put_hex_ll(struct seq_file *m, const char *delimiter,
                    unsigned long long v, unsigned int width);
 
 void seq_escape(struct seq_file *m, const char *s, const char *esc);
+void seq_escape_mem_ascii(struct seq_file *m, const char *src, size_t isz);
 
 void seq_hex_dump(struct seq_file *m, const char *prefix_str, int prefix_type,
                  int rowsize, int groupsize, const void *buf, size_t len,
index d23c5030901a2fe91a436a1e449273a543e015ca..c2895513223422d9dac62bdac6313a25a31613b3 100644 (file)
@@ -54,6 +54,9 @@ static inline int string_unescape_any_inplace(char *buf)
 int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
                unsigned int flags, const char *only);
 
+int string_escape_mem_ascii(const char *src, size_t isz, char *dst,
+                                       size_t osz);
+
 static inline int string_escape_mem_any_np(const char *src, size_t isz,
                char *dst, size_t osz, const char *only)
 {
index 4403e1924f7307d190edd67f00e5e987a4d322b1..3a90a9e2b94ac14b374403ecf07e283086bc746a 100644 (file)
@@ -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.