From: Gleb Natapov <gleb@redhat.com>
To: Zhouyi Zhou <zhouzhouyi@gmail.com>
Cc: kvm@vger.kernel.org, Zhouyi Zhou <yizhouzhou@ict.ac.cn>
Subject: Re: [PATCH 1/1] Check emulator_read_write_onepage will not access beyond one page size
Date: Tue, 2 Jul 2013 13:11:24 +0300 [thread overview]
Message-ID: <20130702101124.GA25522@redhat.com> (raw)
In-Reply-To: <CAABZP2wJ=AaU689W4oYbFSGK1S1=hZL+jqFQO=OBVRPNaHEYVg@mail.gmail.com>
On Tue, Jul 02, 2013 at 05:31:09PM +0800, Zhouyi Zhou wrote:
> Thanks for reviewing
>
> On Tue, Jul 2, 2013 at 4:30 PM, Gleb Natapov <gleb@redhat.com> wrote:
> >
> > On Tue, Jul 02, 2013 at 11:31:31AM +0800, Zhouyi Zhou wrote:
> > > From: Zhouyi Zhou <yizhouzhou@ict.ac.cn>
> > >
> > > Currently the callers of emulator_read_write_onepage do not check the value range
> > > of the argument "bytes". If bytes is greater than the guest page size, many
> > > unexpected things will happen.
> > >
> > The caller of emulator_read_write_onepage() explicitly checks that bytes
> > do not cross page boundaries. Since emulator_read_write() should not
> > be called to write more then 4k at a time this is enough. But even if
> Yes, current Linux kernel will not trigger this marginal condition, so my patch
> is just a suggestion :-)
It is not just by chance it does not trigger it, this is how it suppose
to work, even if we want to protect API from been abused your patch is
incorrect. Just put BUG_ON(bytes > PAGE_SIZE) in emulator_read_write(),
as simple as that.
> > it is kvm_write_guest() makes sure that each write does not cross page
> > boundary too.
> kvm_write_guest increase the guest physical page number but not guest virtual
> page, gfn++ will point to else where in guest.
>
The important point is that guest will not be able to overwrite random
host memory.
> >
> > > This patch performs a check on the access size.
> > >
> > > Tested on my x86_64 machine
> > What is tested? The patch fixes nothing. Can you trigger this WARN_ON()?
> > How?
> My research kernel originally use emulator_read_write to read write
> lot of bytes,(now
> I replace emulator_read_write with kvm_read_guest_virt)
> official linux kernel has nowhere to trigger this WARN_ON. Can this patch
> serves as a future safeguard?
emulator_read_write() should be used by emulator only. Even then if you
wanted it to handle bigger writes you should have fixed
emulator_read_write() to call emulator_read_write_onepage() in a loop.
> >
> > > Signed-off-by: Zhouyi Zhou <yizhouzhou@ict.ac.cn>
> > > ---
> > > arch/x86/include/asm/kvm_host.h | 6 ++++++
> > > arch/x86/kvm/paging_tmpl.h | 4 ++++
> > > arch/x86/kvm/x86.c | 8 ++++++++
> > > 3 files changed, 18 insertions(+)
> > >
> > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> > > index 3741c65..e28e6fe 100644
> > > --- a/arch/x86/include/asm/kvm_host.h
> > > +++ b/arch/x86/include/asm/kvm_host.h
> > > @@ -239,6 +239,11 @@ struct kvm_pio_request {
> > > int size;
> > > };
> > >
> > > +enum guest_page_size {
> > > + GUEST_PGSZ_4K = 0x0,
> > > + GUEST_PGSZ_2M = 0x1,
> > > + GUEST_PGSZ_4M = 0x2,
> > > +};
> > > /*
> > > * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level
> > > * 32-bit). The kvm_mmu structure abstracts the details of the current mmu
> > > @@ -289,6 +294,7 @@ struct kvm_mmu {
> > > bool nx;
> > >
> > > u64 pdptrs[4]; /* pae */
> > > + enum guest_page_size last_guest_page_size; /* last guest page size in walk*/
> > > };
> > >
> > > enum pmc_type {
> > > diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> > > index da20860..6eb0471 100644
> > > --- a/arch/x86/kvm/paging_tmpl.h
> > > +++ b/arch/x86/kvm/paging_tmpl.h
> > > @@ -244,6 +244,10 @@ retry_walk:
> > > real_gpa = mmu->translate_gpa(vcpu, gfn_to_gpa(gfn), access);
> > > if (real_gpa == UNMAPPED_GVA)
> > > return 0;
> > > +
> > > + vcpu->arch.walk_mmu->last_guest_page_size
> > > + = !is_large_pte(pte) ? GUEST_PGSZ_4K :
> > > + ((!is_long_mode(vcpu) && !is_pae(vcpu)) ? GUEST_PGSZ_4M : GUEST_PGSZ_2M);
> > >
> > > walker->gfn = real_gpa >> PAGE_SHIFT;
> > >
> > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > index e8ba99c..de196f7 100644
> > > --- a/arch/x86/kvm/x86.c
> > > +++ b/arch/x86/kvm/x86.c
> > > @@ -4130,6 +4130,8 @@ static int emulator_read_write_onepage(unsigned long addr, void *val,
> > > bool write = ops->write;
> > > struct kvm_mmio_fragment *frag;
> > >
> > > + vcpu->arch.walk_mmu->last_guest_page_size = GUEST_PGSZ_4K;
> > > +
> > > ret = vcpu_mmio_gva_to_gpa(vcpu, addr, &gpa, exception, write);
> > >
> > > if (ret < 0)
> > > @@ -4139,7 +4141,12 @@ static int emulator_read_write_onepage(unsigned long addr, void *val,
> > > if (ret)
> > > goto mmio;
> > >
> > > + WARN_ON((vcpu->arch.walk_mmu->last_guest_page_size == GUEST_PGSZ_4K) ?
> > > + (((gpa&(PAGE_SIZE-1)) + bytes) > PAGE_SIZE) :
> > > + (vcpu->arch.walk_mmu->last_guest_page_size == GUEST_PGSZ_2M) ?
> > > + (((gpa&(PAGE_SIZE-1)) + bytes) > HPAGE_SIZE) :
> > > + (((gpa&(PAGE_SIZE-1)) + bytes) > HPAGE_SIZE*2));
> > > +
> > > if (ops->read_write_emulate(vcpu, gpa, val, bytes))
> > > return X86EMUL_CONTINUE;
> > >
> > > --
> > > 1.7.10.4
> >
> > --
> > Gleb.
> Thanks again
> Zhouyi
--
Gleb.
prev parent reply other threads:[~2013-07-02 10:12 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-02 3:31 [PATCH 1/1] Check emulator_read_write_onepage will not access beyond one page size Zhouyi Zhou
2013-07-02 8:30 ` Gleb Natapov
2013-07-02 9:31 ` Zhouyi Zhou
2013-07-02 10:11 ` Gleb Natapov [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130702101124.GA25522@redhat.com \
--to=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=yizhouzhou@ict.ac.cn \
--cc=zhouzhouyi@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox