media: video: tegra: sh532u: fix out-of-bounds read
[linux-2.6.git] / init / initramfs.c
index 619c1ba..2531811 100644 (file)
@@ -310,7 +310,8 @@ static int __init do_name(void)
                        if (wfd >= 0) {
                                sys_fchown(wfd, uid, gid);
                                sys_fchmod(wfd, mode);
-                               sys_ftruncate(wfd, body_len);
+                               if (body_len)
+                                       sys_ftruncate(wfd, body_len);
                                vcollected = kstrdup(collected, GFP_KERNEL);
                                state = CopyFile;
                        }
@@ -412,7 +413,7 @@ static unsigned my_inptr;   /* index of next byte to be processed in inbuf */
 
 static char * __init unpack_to_rootfs(char *buf, unsigned len)
 {
-       int written;
+       int written, res;
        decompress_fn decompress;
        const char *compress_name;
        static __initdata char msg_buf[64];
@@ -444,17 +445,20 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len)
                }
                this_header = 0;
                decompress = decompress_method(buf, len, &compress_name);
-               if (decompress)
-                       decompress(buf, len, NULL, flush_buffer, NULL,
+               if (decompress) {
+                       res = decompress(buf, len, NULL, flush_buffer, NULL,
                                   &my_inptr, error);
-               else if (compress_name) {
+                       if (res)
+                               error("decompressor failed");
+               } else if (compress_name) {
                        if (!message) {
                                snprintf(msg_buf, sizeof msg_buf,
                                         "compression method %s not configured",
                                         compress_name);
                                message = msg_buf;
                        }
-               }
+               } else
+                       error("junk in compressed archive");
                if (state != Reset)
                        error("junk in compressed archive");
                this_header = saved_offset + my_inptr;
@@ -479,7 +483,8 @@ static int __init retain_initrd_param(char *str)
 }
 __setup("retain_initrd", retain_initrd_param);
 
-extern char __initramfs_start[], __initramfs_end[];
+extern char __initramfs_start[];
+extern unsigned long __initramfs_size;
 #include <linux/initrd.h>
 #include <linux/kexec.h>
 
@@ -515,15 +520,16 @@ skip:
        initrd_end = 0;
 }
 
+#ifdef CONFIG_BLK_DEV_RAM
 #define BUF_SIZE 1024
 static void __init clean_rootfs(void)
 {
        int fd;
        void *buf;
        struct linux_dirent64 *dirp;
-       int count;
+       int num;
 
-       fd = sys_open("/", O_RDONLY, 0);
+       fd = sys_open((const char __user __force *) "/", O_RDONLY, 0);
        WARN_ON(fd < 0);
        if (fd < 0)
                return;
@@ -535,9 +541,9 @@ static void __init clean_rootfs(void)
        }
 
        dirp = buf;
-       count = sys_getdents64(fd, dirp, BUF_SIZE);
-       while (count > 0) {
-               while (count > 0) {
+       num = sys_getdents64(fd, dirp, BUF_SIZE);
+       while (num > 0) {
+               while (num > 0) {
                        struct stat st;
                        int ret;
 
@@ -550,41 +556,41 @@ static void __init clean_rootfs(void)
                                        sys_unlink(dirp->d_name);
                        }
 
-                       count -= dirp->d_reclen;
+                       num -= dirp->d_reclen;
                        dirp = (void *)dirp + dirp->d_reclen;
                }
                dirp = buf;
                memset(buf, 0, BUF_SIZE);
-               count = sys_getdents64(fd, dirp, BUF_SIZE);
+               num = sys_getdents64(fd, dirp, BUF_SIZE);
        }
 
        sys_close(fd);
        kfree(buf);
 }
+#endif
 
 static int __init populate_rootfs(void)
 {
-       char *err = unpack_to_rootfs(__initramfs_start,
-                        __initramfs_end - __initramfs_start);
+       char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
        if (err)
                panic(err);     /* Failed to decompress INTERNAL initramfs */
        if (initrd_start) {
 #ifdef CONFIG_BLK_DEV_RAM
                int fd;
-               printk(KERN_INFO "checking if image is initramfs...");
+               printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
                err = unpack_to_rootfs((char *)initrd_start,
                        initrd_end - initrd_start);
                if (!err) {
-                       printk(" it is\n");
                        free_initrd();
                        return 0;
                } else {
                        clean_rootfs();
-                       unpack_to_rootfs(__initramfs_start,
-                                __initramfs_end - __initramfs_start);
+                       unpack_to_rootfs(__initramfs_start, __initramfs_size);
                }
-               printk("it isn't (%s); looks like an initrd\n", err);
-               fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
+               printk(KERN_INFO "rootfs image is not initramfs (%s)"
+                               "; looks like an initrd\n", err);
+               fd = sys_open((const char __user __force *) "/initrd.image",
+                             O_WRONLY|O_CREAT, 0700);
                if (fd >= 0) {
                        sys_write(fd, (char *)initrd_start,
                                        initrd_end - initrd_start);
@@ -592,15 +598,11 @@ static int __init populate_rootfs(void)
                        free_initrd();
                }
 #else
-               printk(KERN_INFO "Unpacking initramfs...");
+               printk(KERN_INFO "Unpacking initramfs...\n");
                err = unpack_to_rootfs((char *)initrd_start,
                        initrd_end - initrd_start);
-               if (err) {
-                       printk(" failed!\n");
-                       printk(KERN_EMERG "%s\n", err);
-               } else {
-                       printk(" done\n");
-               }
+               if (err)
+                       printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
                free_initrd();
 #endif
        }