proc: fix /proc/*/map_files lookup

"Linux Kernel Mailing List" <[email protected]>
Newsgroups gmane.linux.kernel.commits.head
Message-ID <[email protected]>
Web:        https://git.kernel.org/torvalds/c/ac7f1061c2c11bb8936b1b6a94cdb48de732f7a4
Commit:     ac7f1061c2c11bb8936b1b6a94cdb48de732f7a4
Parent:     9f7118b2007d5e7c7a061550d2ca2ecb841537dc
Refname:    refs/heads/master
Author:     Alexey Dobriyan <[email protected]>
AuthorDate: Tue Feb 6 15:36:59 2018 -0800
Committer:  Linus Torvalds <[email protected]>
CommitDate: Tue Feb 6 18:32:43 2018 -0800

    proc: fix /proc/*/map_files lookup
    
    Current code does:
    
            if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2)
    
    However sscanf() is broken garbage.
    
    It silently accepts whitespace between format specifiers
    (did you know that?).
    
    It silently accepts valid strings which result in integer overflow.
    
    Do not use sscanf() for any even remotely reliable parsing code.
    
            OK
            # readlink '/proc/1/map_files/55a23af39000-55a23b05b000'
            /lib/systemd/systemd
    
            broken
            # readlink '/proc/1/map_files/               55a23af39000-55a23b05b000'
            /lib/systemd/systemd
    
            broken
            # readlink '/proc/1/map_files/55a23af39000-55a23b05b000    '
            /lib/systemd/systemd
    
            very broken
            # readlink '/proc/1/map_files/1000000000000000055a23af39000-55a23b05b000'
            /lib/systemd/systemd
    
    Andrei said:
    
    : This patch breaks criu.  It was a bug in criu.  And this bug is on a minor
    : path, which works when memfd_create() isn't available.  It is a reason why
    : I ask to not backport this patch to stable kernels.
    :
    : In CRIU this bug can be triggered, only if this patch will be backported
    : to a kernel which version is lower than v3.16.
    
    Link: http://lkml.kernel.org/r/20171120212706.GA14325@avx2
    Signed-off-by: Alexey Dobriyan <[email protected]>
    Cc: Pavel Emelyanov <[email protected]>
    Cc: Andrei Vagin <[email protected]>
    Signed-off-by: Andrew Morton <[email protected]>
    Signed-off-by: Linus Torvalds <[email protected]>
---
 fs/proc/base.c | 29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 373091249bdb..4c12cb2cd704 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -100,6 +100,8 @@
 #include "internal.h"
 #include "fd.h"
 
+#include "../../lib/kstrtox.h"
+
 /* NOTE:
  *	Implementing inode permission operations in /proc is almost
  *	certainly an error.  Permission checks need to happen during
@@ -1906,8 +1908,33 @@ end_instantiate:
 static int dname_to_vma_addr(struct dentry *dentry,
 			     unsigned long *start, unsigned long *end)
 {
-	if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2)
+	const char *str = dentry->d_name.name;
+	unsigned long long sval, eval;
+	unsigned int len;
+
+	len = _parse_integer(str, 16, &sval);
+	if (len & KSTRTOX_OVERFLOW)
+		return -EINVAL;
+	if (sval != (unsigned long)sval)
+		return -EINVAL;
+	str += len;
+
+	if (*str != '-')
 		return -EINVAL;
+	str++;
+
+	len = _parse_integer(str, 16, &eval);
+	if (len & KSTRTOX_OVERFLOW)
+		return -EINVAL;
+	if (eval != (unsigned long)eval)
+		return -EINVAL;
+	str += len;
+
+	if (*str != '\0')
+		return -EINVAL;
+
+	*start = sval;
+	*end = eval;
 
 	return 0;
 }
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.