From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48227) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YOB8R-00014l-KL for qemu-devel@nongnu.org; Wed, 18 Feb 2015 15:22:21 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YOB8P-0001t0-Np for qemu-devel@nongnu.org; Wed, 18 Feb 2015 15:22:15 -0500 Received: from e06smtp17.uk.ibm.com ([195.75.94.113]:57547) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YOB8P-0001sT-Dm for qemu-devel@nongnu.org; Wed, 18 Feb 2015 15:22:13 -0500 Received: from /spool/local by e06smtp17.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 18 Feb 2015 20:22:12 -0000 Received: from b06cxnps3075.portsmouth.uk.ibm.com (d06relay10.portsmouth.uk.ibm.com [9.149.109.195]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id 98EA717D8059 for ; Wed, 18 Feb 2015 20:22:22 +0000 (GMT) Received: from d06av02.portsmouth.uk.ibm.com (d06av02.portsmouth.uk.ibm.com [9.149.37.228]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t1IKM89g57475196 for ; Wed, 18 Feb 2015 20:22:08 GMT Received: from d06av02.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av02.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t1IKM5X0019159 for ; Wed, 18 Feb 2015 13:22:07 -0700 From: Christian Borntraeger Date: Wed, 18 Feb 2015 21:22:02 +0100 Message-Id: <1424290943-22480-9-git-send-email-borntraeger@de.ibm.com> In-Reply-To: <1424290943-22480-1-git-send-email-borntraeger@de.ibm.com> References: <1424290943-22480-1-git-send-email-borntraeger@de.ibm.com> Subject: [Qemu-devel] [PULL 08/29] s390x/mmu: Check table length and offset fields List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Peter Maydell Cc: Thomas Huth , qemu-devel , Alexander Graf , Christian Borntraeger , Jens Freimann , Cornelia Huck , Richard Henderson From: Thomas Huth The ACSEs have a table length field and the region entries have table length and offset fields which must be checked during translation to see whether the given virtual address is really covered by the translation table. Signed-off-by: Thomas Huth Signed-off-by: Jens Freimann Signed-off-by: Christian Borntraeger --- target-s390x/cpu.h | 1 + target-s390x/mmu_helper.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 95d0f3b..5563042 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -837,6 +837,7 @@ struct sysib_322 { #define _ASCE_TABLE_LENGTH 0x03 /* region table length */ #define _REGION_ENTRY_ORIGIN ~0xfffULL /* region/segment table origin */ +#define _REGION_ENTRY_TF 0xc0 /* region/segment table offset */ #define _REGION_ENTRY_INV 0x20 /* invalid region table entry */ #define _REGION_ENTRY_TYPE_MASK 0x0c /* region/segment table type mask */ #define _REGION_ENTRY_TYPE_R1 0x0c /* region first table type */ diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c index 01d819e..d4087ba 100644 --- a/target-s390x/mmu_helper.c +++ b/target-s390x/mmu_helper.c @@ -171,6 +171,10 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr, { CPUState *cs = CPU(s390_env_get_cpu(env)); uint64_t origin, offs, new_entry; + const int pchks[4] = { + PGM_SEGMENT_TRANS, PGM_REG_THIRD_TRANS, + PGM_REG_SEC_TRANS, PGM_REG_FIRST_TRANS + }; PTE_DPRINTF("%s: 0x%" PRIx64 "\n", __func__, entry); @@ -201,6 +205,15 @@ static int mmu_translate_region(CPUS390XState *env, target_ulong vaddr, rw); } + /* Check region table offset and length */ + offs = (vaddr >> (28 + 11 * (level - 4) / 4)) & 3; + if (offs < ((new_entry & _REGION_ENTRY_TF) >> 6) + || offs > (new_entry & _REGION_ENTRY_LENGTH)) { + DPRINTF("%s: invalid offset or len (%lx)\n", __func__, new_entry); + trigger_page_fault(env, vaddr, pchks[level / 4 - 1], asc, rw); + return -1; + } + /* yet another region */ return mmu_translate_region(env, vaddr, asc, new_entry, level - 4, raddr, flags, rw); @@ -238,6 +251,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, level = asce & _ASCE_TYPE_MASK; switch (level) { case _ASCE_TYPE_REGION1: + if ((vaddr >> 62) > (asce & _ASCE_TABLE_LENGTH)) { + trigger_page_fault(env, vaddr, PGM_REG_FIRST_TRANS, asc, rw); + return -1; + } break; case _ASCE_TYPE_REGION2: if (vaddr & 0xffe0000000000000ULL) { @@ -246,6 +263,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } + if ((vaddr >> 51 & 3) > (asce & _ASCE_TABLE_LENGTH)) { + trigger_page_fault(env, vaddr, PGM_REG_SEC_TRANS, asc, rw); + return -1; + } break; case _ASCE_TYPE_REGION3: if (vaddr & 0xfffffc0000000000ULL) { @@ -254,6 +275,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } + if ((vaddr >> 40 & 3) > (asce & _ASCE_TABLE_LENGTH)) { + trigger_page_fault(env, vaddr, PGM_REG_THIRD_TRANS, asc, rw); + return -1; + } break; case _ASCE_TYPE_SEGMENT: if (vaddr & 0xffffffff80000000ULL) { @@ -262,6 +287,10 @@ static int mmu_translate_asc(CPUS390XState *env, target_ulong vaddr, trigger_page_fault(env, vaddr, PGM_TRANS_SPEC, asc, rw); return -1; } + if ((vaddr >> 29 & 3) > (asce & _ASCE_TABLE_LENGTH)) { + trigger_page_fault(env, vaddr, PGM_SEGMENT_TRANS, asc, rw); + return -1; + } break; } -- 1.9.3