Skip to content

Commit

Permalink
Introduce a Load Mutable permission (#212)
Browse files Browse the repository at this point in the history
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 <lesswood@google.com>
Co-authored-by: Andrés Amaya Garcia <andres.amaya@codasip.com>
  • Loading branch information
3 people authored Aug 22, 2024
1 parent b95ab88 commit 476d0dd
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 40 deletions.
2 changes: 1 addition & 1 deletion src/attributes.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
68 changes: 39 additions & 29 deletions src/cap-description.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ memory if the authorising capability also grants <<w_perm>>.
[#x_perm,reftext="X-permission"]
Execute Permission (X):: Allow instruction execution.

[#lm_perm,reftext="LM-permission"]
Load Mutable Permission (LM):: Allow preserving the <<w_perm>> of capabilities loaded from memory.
If a capability grants <<r_perm>> and <<c_perm>>, but no <<lm_perm>>, then a capability loaded via this authorizing capability will have <<w_perm>> and <<lm_perm>> 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 <<ACPERM>> are followed when <<w_perm>> and <<lm_perm>> are removed, so additional permissions may also be removed.
Clearing a capability's <<lm_perm>> and <<w_perm>> 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.
Expand Down Expand Up @@ -156,34 +162,37 @@ Quadrant 1 encodes permissions for executable capabilities and the <<m_bit>>.
<<<

.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] - <<m_bit>> ({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 <<infinite-cap>>)
| 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] - <<m_bit>> ({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 <<infinite-cap>>)
| 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 (<<m_bit>>) can only be set on a tagged capability when {cheri_default_ext_name}
Expand Down Expand Up @@ -214,7 +223,8 @@ permission.
| 2 | <<r_perm>>
| 3 | <<x_perm>>
| 4 | <<asr_perm>>
//| 5 | <<m_bit>>
| 5 | <<lm_perm>>
//| 6 | <<m_bit>>
|==============================================================================

The <<m_bit>> is only assigned meaning when the
Expand Down Expand Up @@ -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
Expand Down
8 changes: 5 additions & 3 deletions src/img/acperm_bit_field.edn
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand All @@ -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 {}})
Expand Down
6 changes: 3 additions & 3 deletions src/img/cap-encoding-xlen64.edn
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
3 changes: 3 additions & 0 deletions src/insns/acperm_32bit.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,16 @@ The common rules are:
.. Clear <<c_perm>> unless <<r_perm>> or <<w_perm>> are set.
. <<m_bit>> cannot be set without <<x_perm>> being set
.. Clear <<m_bit>> unless <<x_perm>> is set
. <<lm_perm>> cannot be set without <<c_perm>> being set
.. Clear <<lm_perm>> unless <<c_perm>> is set.

NOTE: The combination of <<x_perm>> clear and <<m_bit>> set is reserved for future extensions.

The MXLEN=32 additional rules are:

. Clear <<asr_perm>> unless _all_ other permissions are set
. Clear <<c_perm>> and <<x_perm>> if <<r_perm>> is not set
. Clear <<w_perm>> if <<c_perm>> _is_ set, but <<lm_perm>> _is not_ set.
. Clear <<x_perm>> if <<x_perm>> and <<r_perm>> _are_ set, but <<c_perm>> and <<w_perm>> _are not_ set.

Exceptions::
Expand Down
4 changes: 3 additions & 1 deletion src/insns/atomic_exceptions.adoc
Original file line number Diff line number Diff line change
@@ -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 <<r_perm>> and <<w_perm>> in the authorising capability.
+
If <<c_perm>> is not granted then store the memory tag as zero, and load `cd.tag` as zero.
+
If the authorizing capability does not grant <<lm_perm>>, and the tag of `cd` is 1 and `cd` is not sealed, then an implicit <<ACPERM>> clearing <<w_perm>> and <<lm_perm>> is performed to obtain the final permissions on `cd` (see <<LC>>).
+
(_This tag clearing behaviour may become a data dependent exception in future._)
endif::[]
ifndef::cap_atomic[]
Expand Down
6 changes: 3 additions & 3 deletions src/insns/load_32bit_cap.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <<c_perm>>.
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 <<ddc>>. 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 <<ddc>> does not grant <<c_perm>>.

include::load_tag_perms.adoc[]

include::malformed_no_check.adoc[]

Expand Down
2 changes: 2 additions & 0 deletions src/insns/load_res_cap_32bit.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pass:attributes,quotes[{cheri_int_mode_name}] Description::
Load reserved instructions, authorised by the capability in <<ddc>>.
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[]
Expand Down
10 changes: 10 additions & 0 deletions src/insns/load_tag_perms.adoc
Original file line number Diff line number Diff line change
@@ -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 (<<ddc>> or `cs1`) does not grant <<c_perm>>.
+
If the authorizing capability does not grant <<lm_perm>>, and the tag of `cd` is 1 and `cd` is not sealed, then an implicit <<ACPERM>> clearing <<w_perm>> and <<lm_perm>> is performed to obtain the final permissions on `cd`.

NOTE: Missing <<lm_perm>> 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 <<ACPERM>> 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 <<GCPERM>> or <<GCHI>>.

0 comments on commit 476d0dd

Please sign in to comment.