befs: Validate length of long symbolic links, CVE-2011-2928
authorTimo Warns <Warns@pre-sense.de>
Tue, 13 Sep 2011 15:21:26 +0000 (16:21 +0100)
committerHerton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
Tue, 27 Sep 2011 19:13:54 +0000 (16:13 -0300)
Signed-off-by: Timo Warns <warns@pre-sense.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

(cherry picked from commit 338d0f0a6fbc82407864606f5b64b75aeb3c70f2)
CVE-2011-2928
BugLink: http://bugs.launchpad.net/bugs/834124
Signed-off-by: Andy Whitcroft <apw@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>

fs/befs/linuxvfs.c

index b1d0c79..e8ff0d7 100644 (file)
@@ -475,17 +475,22 @@ befs_follow_link(struct dentry *dentry, struct nameidata *nd)
                befs_data_stream *data = &befs_ino->i_data.ds;
                befs_off_t len = data->size;
 
                befs_data_stream *data = &befs_ino->i_data.ds;
                befs_off_t len = data->size;
 
-               befs_debug(sb, "Follow long symlink");
-
-               link = kmalloc(len, GFP_NOFS);
-               if (!link) {
-                       link = ERR_PTR(-ENOMEM);
-               } else if (befs_read_lsymlink(sb, data, link, len) != len) {
-                       kfree(link);
-                       befs_error(sb, "Failed to read entire long symlink");
+               if (len == 0) {
+                       befs_error(sb, "Long symlink with illegal length");
                        link = ERR_PTR(-EIO);
                } else {
                        link = ERR_PTR(-EIO);
                } else {
-                       link[len - 1] = '\0';
+                       befs_debug(sb, "Follow long symlink");
+
+                       link = kmalloc(len, GFP_NOFS);
+                       if (!link) {
+                               link = ERR_PTR(-ENOMEM);
+                       } else if (befs_read_lsymlink(sb, data, link, len) != len) {
+                               kfree(link);
+                               befs_error(sb, "Failed to read entire long symlink");
+                               link = ERR_PTR(-EIO);
+                       } else {
+                               link[len - 1] = '\0';
+                       }
                }
        } else {
                link = befs_ino->i_data.symlink;
                }
        } else {
                link = befs_ino->i_data.symlink;