{"id":809643,"url":"http://patchwork.ozlabs.org/api/patches/809643/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/1504527967-29248-17-git-send-email-peter.maydell@linaro.org/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<1504527967-29248-17-git-send-email-peter.maydell@linaro.org>","list_archive_url":null,"date":"2017-09-04T12:25:47","name":"[PULL,16/36] loader: Handle ELF files with overlapping zero-initialized data","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"6e819580bde56e65b7d35cb9cfff6bf32cafcf6c","submitter":{"id":5111,"url":"http://patchwork.ozlabs.org/api/people/5111/?format=json","name":"Peter Maydell","email":"peter.maydell@linaro.org"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/1504527967-29248-17-git-send-email-peter.maydell@linaro.org/mbox/","series":[{"id":1366,"url":"http://patchwork.ozlabs.org/api/series/1366/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=1366","date":"2017-09-04T12:25:36","name":"[PULL,01/36] target/arm: Use MMUAccessType enum rather than int","version":1,"mbox":"http://patchwork.ozlabs.org/series/1366/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/809643/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/809643/checks/","tags":{},"related":[],"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":"ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xm8Z04S3wz9t2R\n\tfor <incoming@patchwork.ozlabs.org>;\n\tMon,  4 Sep 2017 22:39:52 +1000 (AEST)","from localhost ([::1]:59607 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1doqfO-0006JR-68\n\tfor incoming@patchwork.ozlabs.org; Mon, 04 Sep 2017 08:39:50 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:52602)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <pm215@archaic.org.uk>) id 1doqST-00051b-1j\n\tfor qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:44 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <pm215@archaic.org.uk>) id 1doqSD-0004n2-Rs\n\tfor qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:29 -0400","from orth.archaic.org.uk ([2001:8b0:1d0::2]:37118)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32)\n\t(Exim 4.71) (envelope-from <pm215@archaic.org.uk>)\n\tid 1doqSD-0004ma-KI\n\tfor qemu-devel@nongnu.org; Mon, 04 Sep 2017 08:26:13 -0400","from pm215 by orth.archaic.org.uk with local (Exim 4.89)\n\t(envelope-from <pm215@archaic.org.uk>) id 1doqSC-0005W7-Lg\n\tfor qemu-devel@nongnu.org; Mon, 04 Sep 2017 13:26:12 +0100"],"From":"Peter Maydell <peter.maydell@linaro.org>","To":"qemu-devel@nongnu.org","Date":"Mon,  4 Sep 2017 13:25:47 +0100","Message-Id":"<1504527967-29248-17-git-send-email-peter.maydell@linaro.org>","X-Mailer":"git-send-email 2.7.4","In-Reply-To":"<1504527967-29248-1-git-send-email-peter.maydell@linaro.org>","References":"<1504527967-29248-1-git-send-email-peter.maydell@linaro.org>","X-detected-operating-system":"by eggs.gnu.org: Genre and OS details not\n\trecognized.","X-Received-From":"2001:8b0:1d0::2","Subject":"[Qemu-devel] [PULL 16/36] loader: Handle ELF files with overlapping\n\tzero-initialized data","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"},"content":"For embedded systems, notably ARM, one common use of ELF\nfile segments is that the 'physical addresses' represent load addresses\nand the 'virtual addresses' execution addresses, such that\nthe load addresses are packed into ROM or flash, and the\nrelocation and zero-initialization of data is done at runtime.\nThis means that the 'memsz' in the segment header represents\nthe runtime size of the segment, but the size that needs to\nbe loaded is only the 'filesz'. In particular, paddr+memsz\nmay overlap with the next segment to be loaded, as in this\nexample:\n\n0x70000001 off    0x00007f68 vaddr 0x00008150 paddr 0x00008150 align 2**2\n         filesz 0x00000008 memsz 0x00000008 flags r--\n    LOAD off    0x000000f4 vaddr 0x00000000 paddr 0x00000000 align 2**2\n         filesz 0x00000124 memsz 0x00000124 flags r--\n    LOAD off    0x00000218 vaddr 0x00000400 paddr 0x00000400 align 2**3\n         filesz 0x00007d58 memsz 0x00007d58 flags r-x\n    LOAD off    0x00007f70 vaddr 0x20000140 paddr 0x00008158 align 2**3\n         filesz 0x00000a80 memsz 0x000022f8 flags rw-\n    LOAD off    0x000089f0 vaddr 0x20002438 paddr 0x00008bd8 align 2**0\n         filesz 0x00000000 memsz 0x00004000 flags rw-\n    LOAD off    0x000089f0 vaddr 0x20000000 paddr 0x20000000 align 2**0\n         filesz 0x00000000 memsz 0x00000140 flags rw-\n\nwhere the segment at paddr 0x8158 has a memsz of 0x2258 and\nwould overlap with the segment at paddr 0x8bd8 if QEMU's loader\ntried to honour it. (At runtime the segments will not overlap\nsince their vaddrs are more widely spaced than their paddrs.)\n\nCurrently if you try to load an ELF file like this with QEMU then\nit will fail with an error \"rom: requested regions overlap\",\nbecause we create a ROM image for each segment using the memsz\nas the size.\n\nSupport ELF files using this scheme, by truncating the\nzero-initialized part of the segment if it would overlap another\nsegment. This will retain the existing loader behaviour for\nall ELF files we currently accept, and also accept ELF files\nwhich only need 'filesz' bytes to be loaded.\n\nSigned-off-by: Peter Maydell <peter.maydell@linaro.org>\nReviewed-by: Richard Henderson <richard.henderson@linaro.org>\nMessage-id: 1502116754-18867-2-git-send-email-peter.maydell@linaro.org\n---\n include/hw/elf_ops.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++\n 1 file changed, 48 insertions(+)","diff":"diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h\nindex a172a60..2e526d3 100644\n--- a/include/hw/elf_ops.h\n+++ b/include/hw/elf_ops.h\n@@ -362,6 +362,54 @@ static int glue(load_elf, SZ)(const char *name, int fd,\n                     goto fail;\n                 }\n             }\n+\n+            /* The ELF spec is somewhat vague about the purpose of the\n+             * physical address field. One common use in the embedded world\n+             * is that physical address field specifies the load address\n+             * and the virtual address field specifies the execution address.\n+             * Segments are packed into ROM or flash, and the relocation\n+             * and zero-initialization of data is done at runtime. This\n+             * means that the memsz header represents the runtime size of the\n+             * segment, but the filesz represents the loadtime size. If\n+             * we try to honour the memsz value for an ELF file like this\n+             * we will end up with overlapping segments (which the\n+             * loader.c code will later reject).\n+             * We support ELF files using this scheme by by checking whether\n+             * paddr + memsz for this segment would overlap with any other\n+             * segment. If so, then we assume it's using this scheme and\n+             * truncate the loaded segment to the filesz size.\n+             * If the segment considered as being memsz size doesn't overlap\n+             * then we use memsz for the segment length, to handle ELF files\n+             * which assume that the loader will do the zero-initialization.\n+             */\n+            if (mem_size > file_size) {\n+                /* If this segment's zero-init portion overlaps another\n+                 * segment's data or zero-init portion, then truncate this one.\n+                 * Invalid ELF files where the segments overlap even when\n+                 * only file_size bytes are loaded will be rejected by\n+                 * the ROM overlap check in loader.c, so we don't try to\n+                 * explicitly detect those here.\n+                 */\n+                int j;\n+                elf_word zero_start = ph->p_paddr + file_size;\n+                elf_word zero_end = ph->p_paddr + mem_size;\n+\n+                for (j = 0; j < ehdr.e_phnum; j++) {\n+                    struct elf_phdr *jph = &phdr[j];\n+\n+                    if (i != j && jph->p_type == PT_LOAD) {\n+                        elf_word other_start = jph->p_paddr;\n+                        elf_word other_end = jph->p_paddr + jph->p_memsz;\n+\n+                        if (!(other_start >= zero_end ||\n+                              zero_start >= other_end)) {\n+                            mem_size = file_size;\n+                            break;\n+                        }\n+                    }\n+                }\n+            }\n+\n             /* address_offset is hack for kernel images that are\n                linked at the wrong physical address.  */\n             if (translate_fn) {\n","prefixes":["PULL","16/36"]}