From patchwork Sun Jul 11 22:56:10 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mohammed Gamal X-Patchwork-Id: 111357 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o6BMuRhA026044 for ; Sun, 11 Jul 2010 22:57:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755092Ab0GKW4v (ORCPT ); Sun, 11 Jul 2010 18:56:51 -0400 Received: from mail-ww0-f44.google.com ([74.125.82.44]:38377 "EHLO mail-ww0-f44.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754979Ab0GKW4u (ORCPT ); Sun, 11 Jul 2010 18:56:50 -0400 Received: by mail-ww0-f44.google.com with SMTP id 17so256031wwi.1 for ; Sun, 11 Jul 2010 15:56:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references; bh=jt9MChX0agfHXuG97ELKTWaURtOrC+x/VltlBLSeqUM=; b=TzksyO65vUiJu0K+AjGKxjM36AXTIcqhzb1IzOh55N5n6W+6H6LfUlRQdEAeTb9roo h81+hjMCyRKYocyqNJmQYJrl174qUWGnOutY/jD35jUyS2xvz5RsZA8BT6bXwSM8vZxM d4L7eCUoQo1SIpujdxF2+qdeFaBuOBDnTajKs= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=ZhDUJoeEeP3O7XF2j53a1dj8CTOcS2fcY8o0TQGIRHPfSEikhTtYGSrBAzBwV1aAV2 PyXHSpasSXpbm3rMXuU29iI7cS+9XXzOrcRKKwkKK81FENXaByhurEuqkHYQM37Vtxcv 1KeQceTUK8iSynwuLhc9xxbFju+Lj7ydVz3SE= Received: by 10.227.156.143 with SMTP id x15mr9517769wbw.147.1278889009442; Sun, 11 Jul 2010 15:56:49 -0700 (PDT) Received: from localhost ([41.238.118.224]) by mx.google.com with ESMTPS id e31sm25903946wbe.5.2010.07.11.15.56.46 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sun, 11 Jul 2010 15:56:48 -0700 (PDT) From: Mohammed Gamal To: avi@redhat.com Cc: mtosatti@redhat.com, kvm@vger.kernel.org, Mohammed Gamal Subject: [RFC PATCH v3 3/3] x86 emulator: Add segment limit checks to emulator functions Date: Mon, 12 Jul 2010 01:56:10 +0300 Message-Id: <1278888970-2936-4-git-send-email-m.gamal005@gmail.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1278888970-2936-1-git-send-email-m.gamal005@gmail.com> References: <1278888970-2936-1-git-send-email-m.gamal005@gmail.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Sun, 11 Jul 2010 22:57:27 +0000 (UTC) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 07ca28e..6cf6bee 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -728,6 +728,10 @@ static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt, if (eip == fc->end) { cur_size = fc->end - fc->start; size = min(15UL - cur_size, PAGE_SIZE - offset_in_page(eip)); + rc = seg_limit_check(ctxt, ops, VCPU_SREGS_CS, ctxt->cs_base + eip, + size, GP_VECTOR, 0); + if (rc != X86EMUL_CONTINUE) + return rc; rc = ops->fetch(ctxt->cs_base + eip, fc->data + cur_size, size, ctxt->vcpu, NULL); if (rc != X86EMUL_CONTINUE) @@ -1248,6 +1252,8 @@ done_prefixes: register_address(c, seg_override_base(ctxt, ops, c), c->regs[VCPU_REGS_RSI]); c->src.val = 0; + rc = seg_limit_check(ctxt, ops, c->seg_override, c->src.ptr, + c->src.bytes, GP_VECTOR, 0); break; case SrcImmFAddr: c->src.type = OP_IMM; @@ -1344,6 +1350,8 @@ done_prefixes: register_address(c, es_base(ctxt, ops), c->regs[VCPU_REGS_RDI]); c->dst.val = 0; + rc = seg_limit_check(ctxt, ops, VCPU_SREGS_ES, c->dst.ptr, + c->dst.bytes, GP_VECTOR, 0); break; } @@ -1662,7 +1670,7 @@ static inline int writeback(struct x86_emulate_ctxt *ctxt, return X86EMUL_CONTINUE; } -static inline void emulate_push(struct x86_emulate_ctxt *ctxt, +static inline int emulate_push(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops) { struct decode_cache *c = &ctxt->decode; @@ -1673,6 +1681,8 @@ static inline void emulate_push(struct x86_emulate_ctxt *ctxt, register_address_increment(c, &c->regs[VCPU_REGS_RSP], -c->op_bytes); c->dst.ptr = (void *) register_address(c, ss_base(ctxt, ops), c->regs[VCPU_REGS_RSP]); + return seg_limit_check(ctxt, ops, VCPU_SREGS_SS, c->dst.ptr, c->dst.bytes, + SS_VECTOR, 0); } static int emulate_pop(struct x86_emulate_ctxt *ctxt, @@ -1680,11 +1690,16 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt, void *dest, int len) { struct decode_cache *c = &ctxt->decode; + unsigned long reg_addr = register_address(c, ss_base(ctxt, ops), + c->regs[VCPU_REGS_RSP]); int rc; - rc = read_emulated(ctxt, ops, register_address(c, ss_base(ctxt, ops), - c->regs[VCPU_REGS_RSP]), - dest, len); + + rc = read_emulated(ctxt, ops, reg_addr, dest, len); + if (rc != X86EMUL_CONTINUE) + return rc; + rc = seg_limit_check(ctxt, ops, VCPU_SREGS_SS, reg_addr, len, + SS_VECTOR, 0); if (rc != X86EMUL_CONTINUE) return rc; @@ -1735,14 +1750,14 @@ static int emulate_popf(struct x86_emulate_ctxt *ctxt, return rc; } -static void emulate_push_sreg(struct x86_emulate_ctxt *ctxt, +static int emulate_push_sreg(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops, int seg) { struct decode_cache *c = &ctxt->decode; c->src.val = ops->get_segment_selector(seg, ctxt->vcpu); - emulate_push(ctxt, ops); + return emulate_push(ctxt, ops); } static int emulate_pop_sreg(struct x86_emulate_ctxt *ctxt, @@ -1772,7 +1787,9 @@ static int emulate_pusha(struct x86_emulate_ctxt *ctxt, (reg == VCPU_REGS_RSP) ? (c->src.val = old_esp) : (c->src.val = c->regs[reg]); - emulate_push(ctxt, ops); + rc = emulate_push(ctxt, ops); + if (rc != X86EMUL_CONTINUE) + return rc; rc = writeback(ctxt, ops); if (rc != X86EMUL_CONTINUE) @@ -1884,15 +1901,13 @@ static inline int emulate_grp45(struct x86_emulate_ctxt *ctxt, old_eip = c->eip; c->eip = c->src.val; c->src.val = old_eip; - emulate_push(ctxt, ops); - break; + return emulate_push(ctxt, ops); } case 4: /* jmp abs */ c->eip = c->src.val; break; case 6: /* push */ - emulate_push(ctxt, ops); - break; + return emulate_push(ctxt, ops); } return X86EMUL_CONTINUE; } @@ -2548,7 +2563,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, c->op_bytes = c->ad_bytes = (next_tss_desc.type & 8) ? 4 : 2; c->lock_prefix = 0; c->src.val = (unsigned long) error_code; - emulate_push(ctxt, ops); + return emulate_push(ctxt, ops); } return ret; @@ -2681,7 +2696,9 @@ special_insn: emulate_2op_SrcV("add", c->src, c->dst, ctxt->eflags); break; case 0x06: /* push es */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_ES); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_ES); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x07: /* pop es */ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_ES); @@ -2693,14 +2710,18 @@ special_insn: emulate_2op_SrcV("or", c->src, c->dst, ctxt->eflags); break; case 0x0e: /* push cs */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_CS); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_CS); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x10 ... 0x15: adc: /* adc */ emulate_2op_SrcV("adc", c->src, c->dst, ctxt->eflags); break; case 0x16: /* push ss */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_SS); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_SS); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x17: /* pop ss */ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_SS); @@ -2712,7 +2733,9 @@ special_insn: emulate_2op_SrcV("sbb", c->src, c->dst, ctxt->eflags); break; case 0x1e: /* push ds */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_DS); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_DS); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x1f: /* pop ds */ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_DS); @@ -2742,7 +2765,9 @@ special_insn: emulate_1op("dec", c->dst, ctxt->eflags); break; case 0x50 ... 0x57: /* push reg */ - emulate_push(ctxt, ops); + rc = emulate_push(ctxt, ops); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x58 ... 0x5f: /* pop reg */ pop_instruction: @@ -2767,7 +2792,9 @@ special_insn: break; case 0x68: /* push imm */ case 0x6a: /* push imm8 */ - emulate_push(ctxt, ops); + rc = emulate_push(ctxt, ops); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x6c: /* insb */ case 0x6d: /* insw/insd */ @@ -2895,7 +2922,9 @@ special_insn: goto xchg; case 0x9c: /* pushf */ c->src.val = (unsigned long) ctxt->eflags; - emulate_push(ctxt, ops); + rc = emulate_push(ctxt, ops); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0x9d: /* popf */ c->dst.type = OP_REG; @@ -2959,7 +2988,9 @@ special_insn: long int rel = c->src.val; c->src.val = (unsigned long) c->eip; jmp_rel(c, rel); - emulate_push(ctxt, ops); + rc = emulate_push(ctxt, ops); + if (rc != X86EMUL_CONTINUE) + goto done; break; } case 0xe9: /* jmp rel */ @@ -3286,7 +3317,9 @@ twobyte_insn: c->dst.type = OP_NONE; break; case 0xa0: /* push fs */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_FS); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_FS); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0xa1: /* pop fs */ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_FS); @@ -3305,7 +3338,9 @@ twobyte_insn: emulate_2op_cl("shld", c->src2, c->src, c->dst, ctxt->eflags); break; case 0xa8: /* push gs */ - emulate_push_sreg(ctxt, ops, VCPU_SREG_GS); + rc = emulate_push_sreg(ctxt, ops, VCPU_SREG_GS); + if (rc != X86EMUL_CONTINUE) + goto done; break; case 0xa9: /* pop gs */ rc = emulate_pop_sreg(ctxt, ops, VCPU_SREG_GS);