From 476d0ddcc55ed5d51539ac6fbec318610e2b6690 Mon Sep 17 00:00:00 2001 From: Alexander Richardson Date: Thu, 22 Aug 2024 14:43:25 -0700 Subject: [PATCH] Introduce a Load Mutable permission (#212) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This permission exists in Morello and CHERIoT and is useful for sharing a recursively read-only version of a data structure: any capability loaded via an authority without Load Mutable permission will have the Write and Load Mutable permissions cleared. While it may look like this new feature limits forwarding of capability loads, the resulting transformation can be deferred until inspection and thus allows forwarding a single "must clear LM+W permission" bit. Compared to CHERIoT and Morello, the 32-bit encoding format introduces one additional restriction to allow for future extensibility: `ACPERM` clearing `LM` also clears the `W` permission. This restriction does not apply to the 64-bit encoding. Co-authored-by: Lawrence Esswood Co-authored-by: Andrés Amaya Garcia --- src/attributes.adoc | 2 +- src/cap-description.adoc | 68 ++++++++++++++++++------------- src/img/acperm_bit_field.edn | 8 ++-- src/img/cap-encoding-xlen64.edn | 6 +-- src/insns/acperm_32bit.adoc | 3 ++ src/insns/atomic_exceptions.adoc | 4 +- src/insns/load_32bit_cap.adoc | 6 +-- src/insns/load_res_cap_32bit.adoc | 2 + src/insns/load_tag_perms.adoc | 10 +++++ 9 files changed, 69 insertions(+), 40 deletions(-) create mode 100644 src/insns/load_tag_perms.adoc diff --git a/src/attributes.adoc b/src/attributes.adoc index c364d0d6..6dbb1952 100644 --- a/src/attributes.adoc +++ b/src/attributes.adoc @@ -79,7 +79,7 @@ endif::[] :cap_rv32_mw_width: 10 :cap_rv64_mw_width: 14 :cap_rv32_perms_width: 5 -:cap_rv64_perms_width: 5 +:cap_rv64_perms_width: 6 :cap_rv32_addr_width: 32 :cap_rv64_addr_width: 64 :cap_rv32_exp_width: 5 diff --git a/src/cap-description.adoc b/src/cap-description.adoc index cfa4d619..69739189 100644 --- a/src/cap-description.adoc +++ b/src/cap-description.adoc @@ -118,6 +118,12 @@ memory if the authorising capability also grants <>. [#x_perm,reftext="X-permission"] Execute Permission (X):: Allow instruction execution. +[#lm_perm,reftext="LM-permission"] +Load Mutable Permission (LM):: Allow preserving the <> of capabilities loaded from memory. +If a capability grants <> and <>, but no <>, then a capability loaded via this authorizing capability will have <> and <> removed provided that the loaded capability has its tag set and is not sealed; loaded capabilities that are sealed or untagged do not have their permissions changed. +The rules specified by <> are followed when <> and <> are removed, so additional permissions may also be removed. +Clearing a capability's <> and <> allows sharing a read-only version of a data structure (e.g. a tree or linked list) without making a copy. + [#asr_perm,reftext="ASR-permission"] Access System Registers Permission (ASR):: Allow read and write access to all privileged (M-mode and S-mode) CSRs. @@ -156,34 +162,37 @@ Quadrant 1 encodes permissions for executable capabilities and the <>. <<< .Encoding of architectural permissions for MXLEN=32 -[#cap_perms_encoding32,width="100%",options=header,cols="^2,^1,^1,^1,^1,^1,^2,4",align="center"] +[#cap_perms_encoding32,width="100%",options=header,cols="^2,^1,^1,^1,^1,^1,^1,^2,4",align="center"] |============================================================================== -| Encoding[2:0] | R | W | C | X | ASR | Mode^1^ | Notes -8+| *Quadrant 0: Non-capability data read/write* -8+| bit[2] - write, bit[1] - reserved (0), bit[0] - read -8+| _Reserved bits for future extensions are 0 so new permissions are not implicitly granted_ -| 0 | | | | | | N/A | No permissions -| 1 | ✔ | | | | | N/A | Data RO -| 2-3 7+| reserved -| 4 | | ✔ | | | | N/A | Data WO -| 5 | ✔ | ✔ | | | | N/A | Data RW -| 6-7 7+| reserved -8+| *Quadrant 1: Executable capabilities* -8+| bit[0] - <> ({CAP_MODE_VALUE}-pass:attributes,quotes[{cheri_cap_mode_name}], {INT_MODE_VALUE}-pass:attributes,quotes[{cheri_int_mode_name}]) -| 0-1 | ✔ | ✔ | ✔ | ✔ | ✔ | Mode^1^ | Execute + ASR (see <>) -| 2-3 | ✔ | | ✔ | ✔ | | Mode^1^ | Execute + Data & Cap RO -| 4-5 | ✔ | ✔ | ✔ | ✔ | | Mode^1^ | Execute + Data & Cap RW -| 6-7 | ✔ | ✔ | | ✔ | | Mode^1^ | Execute + Data RW -8+| *Quadrant 2: Reserved* -8+| _Reserved bits for future extensions must be 1 so they are implicitly granted_ -| 0-7 7+| reserved -8+| *Quadrant 3: Capability data read/write* -8+| [2] - write. R and C implicitly granted. -8+| _Reserved bits for future extensions must be 1 so they are implicitly granted_ -| 0-2 7+| reserved -| 3 | ✔ | | ✔ | | | N/A | Data & Cap RO -| 4-6 7+| reserved -| 7 | ✔ | ✔ | ✔ | | | N/A | Data & Cap RW +| Encoding[2:0] | R | W | C | LM | X | ASR | Mode^1^ | Notes +9+| *Quadrant 0: Non-capability data read/write* +9+| bit[2] - write, bit[1] - reserved (0), bit[0] - read +9+| _Reserved bits for future extensions are 0 so new permissions are not implicitly granted_ +| 0 | | | | | | | N/A | No permissions +| 1 | ✔ | | | | | | N/A | Data RO +| 2-3 8+| reserved +| 4 | | ✔ | | | | | N/A | Data WO +| 5 | ✔ | ✔ | | | | | N/A | Data RW +| 6-7 8+| reserved +9+| *Quadrant 1: Executable capabilities* +9+| bit[0] - <> ({CAP_MODE_VALUE}-pass:attributes,quotes[{cheri_cap_mode_name}], {INT_MODE_VALUE}-pass:attributes,quotes[{cheri_int_mode_name}]) +| 0-1 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | Mode^1^ | Execute + ASR (see <>) +| 2-3 | ✔ | | ✔ | ✔ | ✔ | | Mode^1^ | Execute + Data & Cap RO +| 4-5 | ✔ | ✔ | ✔ | ✔ | ✔ | | Mode^1^ | Execute + Data & Cap RW +| 6-7 | ✔ | ✔ | | | ✔ | | Mode^1^ | Execute + Data RW +9+| *Quadrant 2: Restricted capability data read/write* +9+| bit[2] - write. R and C implicitly granted, LM dependent on W permission. +9+| _Reserved bits for future extensions must be 1 so they are implicitly granted_ +| 0-2 8+| reserved +| 3 | ✔ | | ✔ | | | | N/A | Data & Cap RO (no LM) +| 4-7 8+| reserved +9+| *Quadrant 3: Capability data read/write* +9+| [2] - write. R and C implicitly granted. +9+| _Reserved bits for future extensions must be 1 so they are implicitly granted_ +| 0-2 8+| reserved +| 3 | ✔ | | ✔ | ✔ | | | N/A | Data & Cap RO +| 4-6 8+| reserved +| 7 | ✔ | ✔ | ✔ | ✔ | | | N/A | Data & Cap RW |============================================================================== ^1^ _Mode (<>) can only be set on a tagged capability when {cheri_default_ext_name} @@ -214,7 +223,8 @@ permission. | 2 | <> | 3 | <> | 4 | <> -//| 5 | <> +| 5 | <> +//| 6 | <> |============================================================================== The <> is only assigned meaning when the @@ -596,7 +606,7 @@ or 'root' capability. | SDP | ones | Grants all permissions | AP (MXLEN=32) | 0x8/0x9^1^ (see xref:cap_perms_encoding32[xrefstyle=short]) | Grants all permissions -| AP (MXLEN=64) | 0x1F (see xref:cap_perms_encoding64[xrefstyle=short]) +| AP (MXLEN=64) | 0x3F (see xref:cap_perms_encoding64[xrefstyle=short]) | Grants all permissions | S | zero | Unsealed | EF | zero | Internal exponent format diff --git a/src/img/acperm_bit_field.edn b/src/img/acperm_bit_field.edn index 934f44aa..3ded315e 100644 --- a/src/img/acperm_bit_field.edn +++ b/src/img/acperm_bit_field.edn @@ -6,11 +6,12 @@ (def left-margin 100) (def right-margin 100) (def boxes-per-row 32) -(draw-column-headers {:height 20 :font-size 18 :labels (reverse ["0" "1" "2" "3" "4" "" "" "" "" "" "" "" "" "" "" "" "16" "" "" "SDPLEN+15" "" "" "" "" "" "" "" "" "" "" "" "XLEN-1"])}) +(draw-column-headers {:height 20 :font-size 18 :labels (reverse ["0" "1" "2" "3" "4" "5" "" "" "" "" "" "" "" "" "" "" "16" "" "" "SDPLEN+15" "" "" "" "" "" "" "" "" "" "" "" "XLEN-1"])}) (draw-box "Reserved" {:span 12}) (draw-box "SDP" {:span 4}) -(draw-box "Reserved" {:span 11}) +(draw-box "Reserved" {:span 10}) +(draw-box "LM" {:span 1}) (draw-box "ASR" {:span 1}) (draw-box "X" {:span 1}) (draw-box "R" {:span 1}) @@ -19,7 +20,8 @@ (draw-box "XLEN-SDPLEN-16" {:span 12 :borders {}}) (draw-box "SDPLEN" {:span 4 :borders {}}) -(draw-box "11" {:span 11 :borders {}}) +(draw-box "10" {:span 10 :borders {}}) +(draw-box "1" {:span 1 :borders {}}) (draw-box "1" {:span 1 :borders {}}) (draw-box "1" {:span 1 :borders {}}) (draw-box "1" {:span 1 :borders {}}) diff --git a/src/img/cap-encoding-xlen64.edn b/src/img/cap-encoding-xlen64.edn index d9e3af04..8738236f 100644 --- a/src/img/cap-encoding-xlen64.edn +++ b/src/img/cap-encoding-xlen64.edn @@ -6,13 +6,13 @@ (def left-margin 100) (def right-margin 100) (def boxes-per-row 32) -(draw-column-headers {:height 50 :font-size 26 :labels (reverse ["0" "2" "3" "" "" "" "13" "14" "16" "17" "" "" "25" "26" "27" "28" "" "" "" "" "" "46" "" "47" "51" "52" "53" "56" "57" "" "" "63"])}) +(draw-column-headers {:height 50 :font-size 26 :labels (reverse ["0" "2" "3" "" "" "" "13" "14" "16" "17" "" "" "25" "26" "27" "28" "" "" "" "" "45" "46" "" "" "51" "52" "53" "56" "57" "" "" "63"])}) (draw-box "Reserved" {:span 4}) (draw-box "SDP" {:span 2}) (draw-box "M" {:span 1}) -(draw-box "AP" {:span 3}) -(draw-box "Reserved" {:span 7}) +(draw-box "AP" {:span 4}) +(draw-box "Reserved" {:span 6}) (draw-box "S" {:span 1}) (draw-box "EF" {:span 1}) (draw-box "T[11:3]" {:span 4}) diff --git a/src/insns/acperm_32bit.adoc b/src/insns/acperm_32bit.adoc index 664c43b4..7edab792 100644 --- a/src/insns/acperm_32bit.adoc +++ b/src/insns/acperm_32bit.adoc @@ -51,6 +51,8 @@ The common rules are: .. Clear <> unless <> or <> are set. . <> cannot be set without <> being set .. Clear <> unless <> is set +. <> cannot be set without <> being set +.. Clear <> unless <> is set. NOTE: The combination of <> clear and <> set is reserved for future extensions. @@ -58,6 +60,7 @@ The MXLEN=32 additional rules are: . Clear <> unless _all_ other permissions are set . Clear <> and <> if <> is not set +. Clear <> if <> _is_ set, but <> _is not_ set. . Clear <> if <> and <> _are_ set, but <> and <> _are not_ set. Exceptions:: diff --git a/src/insns/atomic_exceptions.adoc b/src/insns/atomic_exceptions.adoc index 4de741f6..8acb1fad 100644 --- a/src/insns/atomic_exceptions.adoc +++ b/src/insns/atomic_exceptions.adoc @@ -1,11 +1,13 @@ Permissions:: ifdef::cap_atomic[] -Requires the authorising capability to be tagged and not sealed. +Requires the authorizing capability to be tagged and not sealed. + Requires <> and <> in the authorising capability. + If <> is not granted then store the memory tag as zero, and load `cd.tag` as zero. + +If the authorizing capability does not grant <>, and the tag of `cd` is 1 and `cd` is not sealed, then an implicit <> clearing <> and <> is performed to obtain the final permissions on `cd` (see <>). ++ (_This tag clearing behaviour may become a data dependent exception in future._) endif::[] ifndef::cap_atomic[] diff --git a/src/insns/load_32bit_cap.adoc b/src/insns/load_32bit_cap.adoc index ac70ca03..af02ef4e 100644 --- a/src/insns/load_32bit_cap.adoc +++ b/src/insns/load_32bit_cap.adoc @@ -22,14 +22,14 @@ Encoding:: include::wavedrom/loadcap.adoc[] pass:attributes,quotes[{cheri_cap_mode_name}] Description:: -Load a CLEN+1 bit value from memory and writes it to `cd`. The capability in `cs1` authorizes the operation. The effective address of the memory access is obtained by adding the address of `cs1` to the sign-extended 12-bit offset. The tag value written to `cd` is 0 if the tag of the memory location loaded is 0 or `cs1` does not grant <>. +Load a CLEN+1 bit value from memory and writes it to `cd`. The capability in `cs1` authorizes the operation. The effective address of the memory access is obtained by adding the address of `cs1` to the sign-extended 12-bit offset. pass:attributes,quotes[{cheri_int_mode_name}] Description:: Loads a CLEN+1 bit value from memory and writes it to `cd`. The capability authorising the operation is <>. The effective address of the memory access is obtained by adding `rs1` to the sign-extended 12-bit offset. -The tag value written to `cd` is 0 if the tag of the memory location loaded is -0 or <> does not grant <>. + +include::load_tag_perms.adoc[] include::malformed_no_check.adoc[] diff --git a/src/insns/load_res_cap_32bit.adoc b/src/insns/load_res_cap_32bit.adoc index a6c8fa72..3b7a7a91 100644 --- a/src/insns/load_res_cap_32bit.adoc +++ b/src/insns/load_res_cap_32bit.adoc @@ -27,6 +27,8 @@ pass:attributes,quotes[{cheri_int_mode_name}] Description:: Load reserved instructions, authorised by the capability in <>. All misaligned load reservations cause a load address misaligned exception to allow software emulation (Zam extension, see cite:[riscv-unpriv-spec]). +include::load_tag_perms.adoc[] + :cap_load: include::malformed_no_check.adoc[] diff --git a/src/insns/load_tag_perms.adoc b/src/insns/load_tag_perms.adoc new file mode 100644 index 00000000..e89839b0 --- /dev/null +++ b/src/insns/load_tag_perms.adoc @@ -0,0 +1,10 @@ +Resulting value of `cd`:: +The tag value written to `cd` is 0 if the tag of the memory location loaded is +0 or the authorizing capability (<> or `cs1`) does not grant <>. ++ +If the authorizing capability does not grant <>, and the tag of `cd` is 1 and `cd` is not sealed, then an implicit <> clearing <> and <> is performed to obtain the final permissions on `cd`. + +NOTE: Missing <> does not affect untagged values since this could result in surprising bit patterns when copying non-capability data. +Similarly, sealed capabilities are not modified as they are not directly dereferenceable. + +NOTE: While the implicit <> introduces a dependency on the loaded data, microarchitectures can avoid this by deferring the actual masking of permissions until the loaded capability is dereferenced or the metadata bits are inspected using <> or <>.