]> git.karo-electronics.de Git - linux-beck.git/commitdiff
staging/lustre/llite: fix ll_getname user buffer copy
authorOleg Drokin <green@linuxhacker.ru>
Thu, 11 Jun 2015 05:37:51 +0000 (01:37 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 11 Jun 2015 16:03:59 +0000 (09:03 -0700)
strncpy_from_user could return negative values on error,
so need to take those into account.
Since ll_getname is used to get a single component name from userspace
to transfer to server as-is, there's no need to allocate 4k buffer
as done by __getname. Allocate NAME_MAX+1 buffer instead to ensure
we have enough for a null terminated max valid length buffer.

This was discovered by Al Viro in https://lkml.org/lkml/2015/4/11/243

Signed-off-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/lustre/lustre/llite/dir.c

index 87a042c0433a468711d2f89694040132524b30f0..50d685b0dda0a9a651b975141d2205ba50470850 100644 (file)
@@ -1213,29 +1213,34 @@ out:
        return rc;
 }
 
-static char *
-ll_getname(const char __user *filename)
+/* This function tries to get a single name component,
+ * to send to the server. No actual path traversal involved,
+ * so we limit to NAME_MAX */
+static char *ll_getname(const char __user *filename)
 {
        int ret = 0, len;
-       char *tmp = __getname();
+       char *tmp;
 
+       tmp = kzalloc(NAME_MAX + 1, GFP_KERNEL);
        if (!tmp)
                return ERR_PTR(-ENOMEM);
 
-       len = strncpy_from_user(tmp, filename, PATH_MAX);
-       if (len == 0)
+       len = strncpy_from_user(tmp, filename, NAME_MAX + 1);
+       if (len < 0)
+               ret = len;
+       else if (len == 0)
                ret = -ENOENT;
-       else if (len > PATH_MAX)
+       else if (len > NAME_MAX && tmp[NAME_MAX] != 0)
                ret = -ENAMETOOLONG;
 
        if (ret) {
-               __putname(tmp);
+               kfree(tmp);
                tmp =  ERR_PTR(ret);
        }
        return tmp;
 }
 
-#define ll_putname(filename) __putname(filename)
+#define ll_putname(filename) kfree(filename)
 
 static long ll_dir_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {