Hi, everyone, The thing is: The pages that make up a pagetable must be mapped read-only in the guest. This prevents uncontrolled guest updates to the pagetable. Xen strictly enforces this, and will disallow any pagetable update which will end up mapping pagetable page RW, and will disallow using any writable page as a pagetable. Say, the sub-op: MMU_NORMAL_PT_UPDATE, if the page that ptr of struct mmu_update points to is PGT_l2_page_table, then the address part of val of struct mmu_update points to a page, which is PGT_l1_page_table. However, I couldn't find the protections for this PGT_l1_page_table page in the do_mmu_update, is it already set as read-only before launching MMU_UPDATE hypercall? If someone would like to offer me some help, I really appreciate it. Thanks! Best regards, henry _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
>>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: > Say, the sub-op: MMU_NORMAL_PT_UPDATE, > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, > then > the address part of val of struct mmu_update points > to a page, which is PGT_l1_page_table. > However, I couldn't find the protections for this PGT_l1_page_table > page in the do_mmu_update, is it already set as read-only > before launching MMU_UPDATE hypercall?Of course - a page can't be PGT_l1_page_table when there still is some writable mapping around. So for an L2 entry update it is sufficient to verify that all contained L1 entries point to R/O pages (and transition them to PGT_l1_page_table if they aren't already). Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
> Date: Fri, 11 Oct 2013 08:15:43 +0100 > From: JBeulich@suse.com > To: zhangzhi2022@hotmail.com > CC: xen-devel@lists.xenproject.org > Subject: Re: [Xen-devel] pagetable RO > > >>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: > > Say, the sub-op: MMU_NORMAL_PT_UPDATE, > > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, > > then > > the address part of val of struct mmu_update points > > to a page, which is PGT_l1_page_table. > > However, I couldn't find the protections for this PGT_l1_page_table > > page in the do_mmu_update, is it already set as read-only > > before launching MMU_UPDATE hypercall? >> Of course - a page can't be PGT_l1_page_table when there still is > some writable mapping around.Thanks, but when will the page be set as read-only before the MMU_UPDATE hypercall ? is there any hint?> So for an L2 entry update it is sufficient to verify that all contained L1 entries point to R/O > pages (and transition them to PGT_l1_page_table if they aren't > already).Besides, in the function do_mmu_update for an L2 entry update, the new PGT_l1_page_table page, containing all L1 entries, does not have the process of checking whether they are pointing to the pages of page table type. Instead, R/W flag is removed from the L1 entry only because the page that the entry points to is non-sharable or is a I/O page. What's the reason? henry> > Jan_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
>>> On 11.10.13 at 09:37, 张智<zhangzhi2022@hotmail.com> wrote:> >> Date: Fri, 11 Oct 2013 08:15:43 +0100 >> From: JBeulich@suse.com >> To: zhangzhi2022@hotmail.com >> CC: xen-devel@lists.xenproject.org >> Subject: Re: [Xen-devel] pagetable RO >> >> >>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: >> > Say, the sub-op: MMU_NORMAL_PT_UPDATE, >> > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, >> > then >> > the address part of val of struct mmu_update points >> > to a page, which is PGT_l1_page_table. >> > However, I couldn't find the protections for this PGT_l1_page_table >> > page in the do_mmu_update, is it already set as read-only >> > before launching MMU_UPDATE hypercall? >> > >> Of course - a page can't be PGT_l1_page_table when there still is >> some writable mapping around. > Thanks, but when will the page be set as read-only before the MMU_UPDATE > hypercall ? is there any hint?Whenever the guest kernel wants to do that.>> So for an L2 entry update it is sufficient to verify that all contained L1 > entries point to R/O >> pages (and transition them to PGT_l1_page_table if they aren't >> already). > > Besides, in the function do_mmu_update for an L2 entry update, the new > PGT_l1_page_table page, containing all L1 entries, does not have the process > of checking whether they are pointing to the pages of page table type.It surely does: mod_l2_entry() -> get_page_from_l2e() -> get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...).> Instead, R/W flag is removed from the L1 entry only because the page that the > entry points to is non-sharable or is a I/O page. What's the reason?I don't think I understand what you're asking here. Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
> Date: Fri, 11 Oct 2013 09:36:44 +0100 > From: JBeulich@suse.com > To: zhangzhi2022@hotmail.com > CC: xen-devel@lists.xenproject.org > Subject: RE: [Xen-devel] pagetable RO > > >>> On 11.10.13 at 09:37, 张智<zhangzhi2022@hotmail.com> wrote: > > > > >> Date: Fri, 11 Oct 2013 08:15:43 +0100 > >> From: JBeulich@suse.com > >> To: zhangzhi2022@hotmail.com > >> CC: xen-devel@lists.xenproject.org > >> Subject: Re: [Xen-devel] pagetable RO > >> > >> >>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: > >> > Say, the sub-op: MMU_NORMAL_PT_UPDATE, > >> > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, > >> > then > >> > the address part of val of struct mmu_update points > >> > to a page, which is PGT_l1_page_table. > >> > However, I couldn't find the protections for this PGT_l1_page_table > >> > page in the do_mmu_update, is it already set as read-only > >> > before launching MMU_UPDATE hypercall? > >> > > > >> Of course - a page can't be PGT_l1_page_table when there still is > >> some writable mapping around. > > Thanks, but when will the page be set as read-only before the MMU_UPDATE > > hypercall ? is there any hint? > > Whenever the guest kernel wants to do that. > > >> So for an L2 entry update it is sufficient to verify that all contained L1 > > entries point to R/O > >> pages (and transition them to PGT_l1_page_table if they aren't > >> already). > > > > Besides, in the function do_mmu_update for an L2 entry update, the new > > PGT_l1_page_table page, containing all L1 entries, does not have the process > > of checking whether they are pointing to the pages of page table type. > > It surely does: mod_l2_entry() -> get_page_from_l2e() -> > get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...). >Not exactly, get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) -> ...->alloc_page_type(page, PGT_l1_page_table, 0) -> alloc_l1_table(page) See, in the function: alloc_l1_table(page), only when the function: get_page_from_l1e(pl1e[i], ...) returns 1, will the function: l1e_remove_flags(pl1e[i], _PAGE_RW) does execute. This is what I've just said "R/W flag is removed from the L1 entry" . Further, the function: get_page_from_l1e(pl1e[i], ...) will return 1 only when this check: ( !mfn_valid(mfn) || (real_pg_owner = page_get_owner_and_reference(page)) == dom_io ) succeeds. From above, it is concluded that do_mmu_update does not set the L1 entries in the new PGT_l1_page_table , which point to pages of page table type, as read-only. In a nutshell, where does xen hypervisor set the new PGT_l1_page_table as read-only?> > Instead, R/W flag is removed from the L1 entry only because the page that the > > entry points to is non-sharable or is a I/O page. What's the reason? > > I don't think I understand what you're asking here. > > Jan_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
>>> On 11.10.13 at 10:59, 张智<zhangzhi2022@hotmail.com> wrote: >> Date: Fri, 11 Oct 2013 09:36:44 +0100 >> From: JBeulich@suse.com >> >>> On 11.10.13 at 09:37, 张智<zhangzhi2022@hotmail.com> wrote: >> >> Date: Fri, 11 Oct 2013 08:15:43 +0100 >> >> From: JBeulich@suse.com >> >> >>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: >> >> > Say, the sub-op: MMU_NORMAL_PT_UPDATE, >> >> > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, >> >> > then >> >> > the address part of val of struct mmu_update points >> >> > to a page, which is PGT_l1_page_table. >> >> > However, I couldn't find the protections for this PGT_l1_page_table >> >> > page in the do_mmu_update, is it already set as read-only >> >> > before launching MMU_UPDATE hypercall? >> >> >> > >> >> Of course - a page can't be PGT_l1_page_table when there still is >> >> some writable mapping around. >> > Thanks, but when will the page be set as read-only before the MMU_UPDATE >> > hypercall ? is there any hint? >> >> Whenever the guest kernel wants to do that.Did you read this at all? Because it answers ...>> >> So for an L2 entry update it is sufficient to verify that all contained L1 >> > entries point to R/O >> >> pages (and transition them to PGT_l1_page_table if they aren't >> >> already). >> > >> > Besides, in the function do_mmu_update for an L2 entry update, the new >> > PGT_l1_page_table page, containing all L1 entries, does not have the > process >> > of checking whether they are pointing to the pages of page table type. >> >> It surely does: mod_l2_entry() -> get_page_from_l2e() -> >> get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...). >> > > Not exactly, get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) -> > ...->alloc_page_type(page, PGT_l1_page_table, 0) -> alloc_l1_table(page) > See, in the function: alloc_l1_table(page), only when the function: > get_page_from_l1e(pl1e[i], ...) returns 1, will the function: > l1e_remove_flags(pl1e[i], _PAGE_RW) does execute. This is what I've just > said "R/W flag is removed from the L1 entry" . Further, the function: > get_page_from_l1e(pl1e[i], ...) will return 1 only when this check: ( > !mfn_valid(mfn) || (real_pg_owner = page_get_owner_and_reference(page)) == > dom_io ) succeeds. > From above, it is concluded that do_mmu_update does not set the L1 entries > in the new PGT_l1_page_table , which point to pages of page table type, as > read-only. > In a nutshell, where does xen hypervisor set the new PGT_l1_page_table as > read-only?... this question: The hypervisor does not do this at all. It only verifies that the guest kernel did. Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
> Date: Fri, 11 Oct 2013 10:04:15 +0100 > From: JBeulich@suse.com > To: zhangzhi2022@hotmail.com > CC: xen-devel@lists.xen.org > Subject: RE: [Xen-devel] pagetable RO > > >>> On 11.10.13 at 10:59, 张智<zhangzhi2022@hotmail.com> wrote: > >> Date: Fri, 11 Oct 2013 09:36:44 +0100 > >> From: JBeulich@suse.com > >> >>> On 11.10.13 at 09:37, 张智<zhangzhi2022@hotmail.com> wrote: > >> >> Date: Fri, 11 Oct 2013 08:15:43 +0100 > >> >> From: JBeulich@suse.com > >> >> >>> On 11.10.13 at 08:30, 张智<zhangzhi2022@hotmail.com> wrote: > >> >> > Say, the sub-op: MMU_NORMAL_PT_UPDATE, > >> >> > if the page that ptr of struct mmu_update points to is PGT_l2_page_table, > >> >> > then > >> >> > the address part of val of struct mmu_update points > >> >> > to a page, which is PGT_l1_page_table. > >> >> > However, I couldn't find the protections for this PGT_l1_page_table > >> >> > page in the do_mmu_update, is it already set as read-only > >> >> > before launching MMU_UPDATE hypercall? > >> >> > >> > > >> >> Of course - a page can't be PGT_l1_page_table when there still is > >> >> some writable mapping around. > >> > Thanks, but when will the page be set as read-only before the MMU_UPDATE > >> > hypercall ? is there any hint? > >> > >> Whenever the guest kernel wants to do that. > > Did you read this at all? Because it answers ... > > >> >> So for an L2 entry update it is sufficient to verify that all contained L1 > >> > entries point to R/O > >> >> pages (and transition them to PGT_l1_page_table if they aren't > >> >> already). > >> > > >> > Besides, in the function do_mmu_update for an L2 entry update, the new > >> > PGT_l1_page_table page, containing all L1 entries, does not have the > > process > >> > of checking whether they are pointing to the pages of page table type. > >> > >> It surely does: mod_l2_entry() -> get_page_from_l2e() -> > >> get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...). > >> > > > > Not exactly, get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) -> > > ...->alloc_page_type(page, PGT_l1_page_table, 0) -> alloc_l1_table(page) > > See, in the function: alloc_l1_table(page), only when the function: > > get_page_from_l1e(pl1e[i], ...) returns 1, will the function: > > l1e_remove_flags(pl1e[i], _PAGE_RW) does execute. This is what I've just > > said "R/W flag is removed from the L1 entry" . Further, the function: > > get_page_from_l1e(pl1e[i], ...) will return 1 only when this check: ( > > !mfn_valid(mfn) || (real_pg_owner = page_get_owner_and_reference(page)) == > > dom_io ) succeeds. > > From above, it is concluded that do_mmu_update does not set the L1 entries > > in the new PGT_l1_page_table , which point to pages of page table type, as > > read-only. > > In a nutshell, where does xen hypervisor set the new PGT_l1_page_table as > > read-only? > > ... this question: The hypervisor does not do this at all. It only > verifies that the guest kernel did.I've read the source code of do_mmu_update and could only find that macro: define_get_linear_pagetable(l2) checks whether its entry is read-only. However, this function does execute only when get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) returns an invalid value. Is this the point or somewhere else about checking whether the new PGT_l1_page_table as read-only ? I did not find the check points in the function: get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) as well as its sub-branch functions. henry> > Jan_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
>>> On 11.10.13 at 19:27, 张智<zhangzhi2022@hotmail.com> wrote: > I've read the source code of do_mmu_update and could only find that macro: > define_get_linear_pagetable(l2) checks whether its entry is read-only. > However, this function does execute only when > get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) returns an invalid > value. Is this the point or somewhere else about checking whether the new > PGT_l1_page_table as read-only ? I did not find the check points in the > function: get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) as well > as its sub-branch functions.That's not how it works. A page is read-only if it's of one of the types that require it to be and has non-zero type reference count, or if it's of no particular type (i.e. its type reference count is zero). Any mapping with _PAGE_RW set would cause the page to have a non- zero type reference count and be of type PGT_writable, and hence it couldn't be transitioned to any of the other (read-only) types. The core function here is __get_page_type(). Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel
Yes, I see that. Thanks a lot, Jan. Henry> Date: Mon, 14 Oct 2013 07:32:06 +0100 > From: JBeulich@suse.com > To: zhangzhi2022@hotmail.com > CC: xen-devel@lists.xen.org > Subject: RE: [Xen-devel] pagetable RO > > >>> On 11.10.13 at 19:27, 张智<zhangzhi2022@hotmail.com> wrote: > > I've read the source code of do_mmu_update and could only find that macro: > > define_get_linear_pagetable(l2) checks whether its entry is read-only. > > However, this function does execute only when > > get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) returns an invalid > > value. Is this the point or somewhere else about checking whether the new > > PGT_l1_page_table as read-only ? I did not find the check points in the > > function: get_page_and_type_from_pagenr(mfn, PGT_l1_page_table, ...) as well > > as its sub-branch functions. > > That's not how it works. A page is read-only if it's of one of the types > that require it to be and has non-zero type reference count, or if it's > of no particular type (i.e. its type reference count is zero). Any > mapping with _PAGE_RW set would cause the page to have a non- > zero type reference count and be of type PGT_writable, and hence > it couldn't be transitioned to any of the other (read-only) types. The > core function here is __get_page_type(). > > Jan_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel