Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AArch64 Access Control: initial setup #837

Open
wants to merge 3 commits into
base: aarch64-access
Choose a base branch
from

Conversation

ryybrr
Copy link
Contributor

@ryybrr ryybrr commented Dec 11, 2024

Partial access control proofs for AArch64:

  • Introduce a minimal set of assumption such that the remaining theories build without sorries. These assumptions are defined at the end of AARCH64/ArchAccess.thy and represent new integrity constraints
  • Add FIXME AARCH64 comments for additional proof obligations not captured by the current spec
  • Update ASpec and AInvs to enforce a stricter partitioning of VCPU saves/restores

This PR is structured into 2 commits:

  1. Port existing theories verbatim over to AArch64
  2. Update these theories such that Access builds with quick_and_dirty enabled

To review the fine-grained changes, refer only to the 2nd commit

@ryybrr ryybrr added AC access control proofs Aarch64 AArch64-specific proofs, specs, etc labels Dec 11, 2024
@ryybrr ryybrr self-assigned this Dec 11, 2024
Comment on lines +28 to +33
PagePTE paddr _ _ rights
\<Rightarrow> Some (ptrFromPAddr paddr,
pt_bits_left level,
vspace_cap_rights_to_auth rights)
| PageTablePTE ppn
\<Rightarrow> Some (ptrFromPAddr (paddr_from_ppn ppn), 0, {Control})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style nitpick: the => should go on the same line as the case expression (e.g. PagePTE).

Copy link
Member

@lsf37 lsf37 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! That goes a good deal beyond just setup, it already contains the bulk of the main proof and will allow us to concentrate on the tricky bits in the next part.

I have only some very minor style nitpicks. Otherwise very nice!

-Remove various instances of pspace_aligned, valid_vspace_objs, and
valid_asid_table/valid_arch_state from preconditions
-Relax the is_subject predicate in various Syscall_AC lemmas

Signed-off-by: Ryan Barry <[email protected]>
@@ -177,7 +176,7 @@ lemma (in is_extended') cte_wp_at[wp]: "I (cte_wp_at P a)"
by (rule lift_inv, simp)

lemma checked_insert_pas_refined:
"\<lbrace>pas_refined aag and pspace_aligned and valid_vspace_objs and valid_arch_state and valid_mdb and
"\<lbrace>pas_refined aag and valid_mdb and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is very cheerful to see, I'm glad you're spotting these overly-strong preconditions

@@ -241,7 +240,7 @@ global_interpretation Finalise_AC_1?: Finalise_AC_1
proof goal_cases
interpret Arch .
case 1 show ?case
by (unfold_locales; (fact Finalise_AC_assms | wp finalise_cap_replaceable))
by (unfold_locales; wpsimp wp: Finalise_AC_assms)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a strange formulation, it implies that Finalise_AC_assms is only wp rules. The previous formulation said: "if it isn't a fact then it's a wp rule".

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This formulation lets wp use the ones that are rules and will apply them as rule otherwise. I don't really mind, but it is true that the old version showed slightly more intention. Then again, it would also use fact with Finalise_AC_assms rules that are wp rules. So it didn't really make that distinction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what this is doing is making use of rules declared [wp] in Arch in order to discharge locale assumptions without having to mark the relevant rules [whatever_assms]? I guess that makes sense; in theory if you put all the assms into the wp set, then wpsimp would solve all subgoals without further arguments?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It definitely was not obvious at first glance though, and even now I seek confirmation. If we want to go down this route, we might want to say something in the arch-split docs.

declare finalise_cap_valid_list[Finalise_AC_assms]
declare arch_finalise_cap_pas_refined[Finalise_AC_assms]
declare prepare_thread_delete_pas_refined[Finalise_AC_assms]
declare finalise_cap_replaceable[Finalise_AC_assms]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happened here? previously there was a crunch, and then we picked out the Finalise_AC_assms... did the crunch move elsewhere?

@ryybrr ryybrr force-pushed the aarch64-access-setup branch from 5ab11b7 to 2048660 Compare December 12, 2024 03:23
@@ -168,7 +169,7 @@ global_interpretation Syscall_AC_1?: Syscall_AC_1
proof goal_cases
interpret Arch .
case 1 show ?case
by (unfold_locales; (fact Syscall_AC_assms | wp init_arch_objects_inv))
by (unfold_locales; wpsimp wp: Syscall_AC_assms)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as my other comment, is it only wp rules in the assms? surprised it doesn't work with fact

\<longrightarrow> vspace_for_pool pool_ptr asid (asid_pools_of s') =
vspace_for_pool pool_ptr asid (asid_pools_of s);
bot_level < max_pt_level \<longrightarrow> pts_of s' = pts_of s \<rbrakk>
\<Longrightarrow> vs_lookup_table bot_level asid vref s' = vs_lookup_table bot_level asid vref s"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation:

  • ⟹ vs_lookup_table should be under
  • vspace_for_pool indent should be by 2 instead of 1

(* similarly, the preconditions here tend to contradict one another *)
lemma invoke_control_domain_sep_inv:
"\<lbrace>domain_sep_inv irqs st and irq_control_inv_valid i\<rbrace>
invoke_irq_control i
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

"\<lbrace>pspace_aligned and valid_vspace_objs and valid_arch_state and pas_refined aag\<rbrace>
set_mrs thread buf msgs
\<lbrace>\<lambda>_. pas_refined aag\<rbrace>"
"set_mrs thread buf msgs \<lbrace>pas_refined aag\<rbrace>"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really appreciate the style overhaul you've included in this PR

@@ -75,7 +74,7 @@ global_interpretation Interrupt_AC_1?: Interrupt_AC_1 "arch_authorised_irq_ctl_i
proof goal_cases
interpret Arch .
case 1 show ?case
by (unfold_locales; (fact Interrupt_AC_assms)?)
by (unfold_locales; fact Interrupt_AC_assms)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can keep this change, but should know the reason for (fact Interrupt_AC_assms)?. The reason that's useful is while developing, when this instantiation errors, you can see which fact you're missing from your assumption; with the non-? one, you get "proof command failed".

@@ -179,7 +179,7 @@ global_interpretation Syscall_AC_1?: Syscall_AC_1
proof goal_cases
interpret Arch .
case 1 show ?case
by (unfold_locales; (fact Syscall_AC_assms)?)
by (unfold_locales; wpsimp wp: Syscall_AC_assms)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really see why the change to instantiating locale assumptions using wpsimp is an improvement. You're very consistent with it, so I'd like to hear your thoughts.

by wpsimp

lemma arch_post_modify_registers_domain_sep_inv[DomainSepInv_assms, wp]:
"arch_post_modify_registers cur x31 \<lbrace>domain_sep_inv irqs st\<rbrace>"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x31, haha


context begin interpretation Arch .

requalify_consts arch_authorised_irq_ctl_inv
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for this PR, but there's tech to do this more efficiently, documented in docs/arch-split.md (arch_requalify_facts)


lemma integrity_asids_update_autarch[Access_AC_assms]:
"\<lbrakk> \<forall>x a. integrity_asids aag {pasSubject aag} x a st s; is_subject aag ptr \<rbrakk>
\<Longrightarrow> \<forall>x a. integrity_asids aag {pasSubject aag} x a st (s\<lparr>kheap := (kheap s)(ptr \<mapsto> obj)\<rparr>)"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing all of these lemmas with old-style ==> indents are only moved from elsewhere?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are Tom-style indents, not old style indents. I don't think anybody else has used them :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, those are not new then, fine to leave as is

| PageTable pt \<Rightarrow> (case pt of
VSRootPT pt \<Rightarrow> \<Union>(r,(p, sz, auth)) \<in> graph_of (pte_ref2 level o pt).
(\<lambda>(p, a). (p, ucast r, APageTable VSRootPT_T, a)) ` (ptr_range p sz \<times> auth)
| NormalPT pt \<Rightarrow> \<Union>(r,(p, sz, auth)) \<in> graph_of (pte_ref2 level o pt).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the | should line up

| "aobj_ref' (PageTableCap ref _ _) = {ref}"
| "aobj_ref' (VCPUCap ref) = {ref}"

fun acap_asid' :: "arch_cap \<Rightarrow> asid set" where
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand the role of aobj_ref' and acap_asid'. Are there non-' versions? Why are they not what we want in access?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ASpec versions don't return sets, which we do want here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe _set instead of ' or a comment then?

"'a PAS \<Rightarrow> 'a set \<Rightarrow> obj_ref \<Rightarrow> asid \<Rightarrow> 'y::state_ext state \<Rightarrow> 'z::state_ext state \<Rightarrow> bool" where
"integrity_asids aag subjects x asid s s' \<equiv>
integrity_asids_aux aag subjects x asid (asid_table s) (asid_table s')
(asid_pools_of s) (asid_pools_of s')"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is interestingly the other way round to the _2 setup we use in AInvs/Refine. There we want the abbreviation to expose the state projections, and the definition to hide the complicated bits and pieces. Here you get no benefit from the definition (need to unfold to benefit from the fact that the state projections don't change), and you don't get a real benefit from the abbreviation, because it doesn't hide the complexity ... thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth trying out what happens if we do it the "right" way around. It might conflict with old style in the Access session, but it'd be good to see if that is true.

get_page_info (aobjs_of s)
(get_vspace_of_thread (kheap s) (arch_state s) tcb) x = Some (base, sz, attr, r) \<rbrakk>
(get_vspace_of_thread (kheap s) (arch_state s) tcb) x = Some (base, sz, attr, r) \<rbrakk>
\<Longrightarrow> ptrFromPAddr base + (x && mask sz) \<in> ptr_range (ptrFromPAddr base) sz"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit surprised this lemma is in Access and not in AInvs, but I guess it's only needed up here.

Copy link
Member

@Xaphiosis Xaphiosis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is very good work. Sometimes it's hard to tell what got moved/copied, and my comments may be related to something that's just being consistent with other arches, in which case ignore those. Mostly I have nitpicks/style and some questions to try bridge gaps in my knowledge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Aarch64 AArch64-specific proofs, specs, etc AC access control proofs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants