-
Notifications
You must be signed in to change notification settings - Fork 7
/
chap-architecture.tex
3269 lines (2874 loc) · 168 KB
/
chap-architecture.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\chapter{Mapping CHERI Protection into Architecture}
\label{chap:architecture}
%\rwnote{This chapter has been largely rearranged, but requires substantial
% editing to tidy up the results, shift some contents to/from
% architecture-specific chapters, and to update the introduction and first few
% sections. It would be nice to add a section on ensuring that both the base
% ISA and our extensions consistently enforce CHERI's invariants/safety
% properties -- e.g., provenance validity, monotonicity, etc.}
In this chapter, we explore architecture-neutral aspects of the mapping from
the abstract CHERI protection model into Instruction-Set Architectures (ISAs).
We consider the high-level architectural goals in mappings and the
implications of our specific capability-system model before turning to the
concrete definitions associated with CHERI's architectural capabilities,
register files, tagged memory, and its composition with various existing
architectural features such as exception handling and virtual memory.
We conclude with a consideration of ``deep'' versus ``surface'' design
choices: where there is freedom to make different choices in instantiating
the CHERI model in a specific ISA, with an eye towards both the adaptation
design space and also applications to further non-MIPS ISAs, and where
divergence might lead to protection inconsistency across architectures.
\section{Architectural Instantiations of CHERI Protection}
Our current instantiations within concrete ISAs are:
\begin{description}
\item[CHERI-RISC-V] is our mature reference instantiation.
It is an instantiation of the CHERI protection model against 32-bit and
64-bit RISC-V (Chapter~\ref{chap:cheri-riscv}).
CHERI-RISC-V has been validated with a complete end-to-end hardware-software
stack including a formal ISA model, ISA-level simulations, three FPGA
implementations, adaptations of our CheriBSD and CheriFreeRTOS operating
systems, Clang/LLVM/LLD toolchain, GDB debugger, and application suite.
We aim to propose 64-bit CHERI-RISC-V as a RISC-V extension with
minimal adjustments. We consider 32-bit CHERI-RISC-V less mature
and expect future disruptive modifications as it transitions to a more mature
status.
\item[Arm Morello] is an experimental instantiation created by Arm
in collaboration with the CHERI team~\cite{arm-morello}.
It is an instantiation of the CHERI protection model against the 64-bit
ARMv8-A ISA.
% (Chapter~\ref{chap:morello}).
\rwnote{Need a Morello chapter.}
Morello is the target of an in-progress CPU, SoC, and board design based on
Arm's Neoverse N1 system architecture, and has been validated for much of
the end-to-end- hardware-stack including a formal ISA model, ISA-level
simulations, an adaptation of our CheriBSD operating system, Clang/LLVM/LLD
toolchain, GDB debugger, and application suite.
\item[CHERI-x86-64] is a sketch instantiation intended to describe
a potential approach to applying the CHERI protection model to the x86-64
ISA -- the dominant non-RISC architecture (Chapter~\ref{chap:cheri-x86-64}).
\end{description}
\section{High-Level Architectural Goals}
In addition to the broad abstract goal of supporting pointer-centric
protection with strong compatibility and performance objectives, we have
pursued the following architectural goals in integrating CHERI into
contemporary instruction-set architectures:
\begin{enumerate}
\item When mapping the CHERI model into RISC architectures, CHERI's extensions
should subscribe to the RISC design philosophy: a load-store instruction set
intended to be targeted by compilers, with more complex instructions
motivated by quantitative analysis.
While current page-table structures
are retained for functionality and compatibility, new
table-oriented structures are avoided in describing new security primitives.
In general, instructions that do not access memory or trigger an exception
should be single-cycle register-to-register operations.
\item New primitives, such as tagged memory and capabilities, are aligned
closely with current microarchitectural designs (e.g., as relates to
register files, pipelined and superscalar processors, memory subsystems, and
buses), offering minimal disruption necessary to offer substantial semantic
and performance improvements that would be difficult to support with
current architectures.
Where current de-facto approaches to microarchitecture must be changed to
support CHERI -- such as through the adoption of architectural tagged memory
-- there are efficient implementations.
\item CHERI composes sensibly with MMU-based memory protection: current
MMU-based operating systems should run unmodified on CHERI designs, and as
CHERI support is introduced in an MMU-based operating system, it should
compose naturally while allowing both capability-aware and legacy programs
to run side-by-side.
This allows software designers to view the system as a set of more
conventional virtual address spaces within which CHERI offers protection --
or as a single-address-space system environment as use of the MMU is
minimized.
\item As protection pressure shifts from conventional MMU-based techniques to
reference-oriented protection using CHERI capabilities, page-table
efficiency increases as larger page sizes cease to penalize protection.
\item Protection primitive use is common-case, not exceptional, and occurs
in performance-centric code paths such as stack and heap
allocation, on pointer arithmetic, and on pointer-relative load and store,
rather than being an infrequent higher-cost activity that can be amortized.
\item The principles of least privilege and intentional use dictate a number
of aspects of CHERI ISA design, including requiring that no confusion arise
between the use of capabilities as pointers versus integers as pointers.
Load, store, and jump instructions will never automatically select
semantics based on presence of a tag -- for example, to avoid opportunities
accidental use of the wrong right (e.g., by virtue of a capability tag being
cleared due to an exploitable software vulnerability leading to its
interpretation as an integer virtual address).
Similarly, associative lookups of capabilities are entirely avoided.
Trade-offs around this design goal inevitably exist.
For example, to run unmodified software, CHERI provides a Default Data
Capability that is transparently dereferenced when legacy
integer-pointer-based code accesses memory, which we deem necessary for
compatibility reasons.
Similarly, we do not currently choose to provide granular control over the
use of ring-based processor privilege, in order to avoid the complexity and
disruption of implementing entirely new interfaces for interrupt and MMU
management, using a single permission on code capabilities rather than a
broad set of possible capabilities representing different privileges.
A purer (non-hybridized) capability-system design would avoid these
design choices.
\item Just as C-language pointers map cleanly and efficiently into integers
today, pointers must similarly map cleanly, efficiently, and vastly more
robustly, into capabilities.
This should apply both to language-visible data and code pointers, but also
pointers used in implementing language features, such as references to
C++ vtables, return addresses, etc.
\item Flexibility exists to employ only legacy integer pointers or
capabilities as dictated by software design and code generation, trading off
compatibility, protection, and performance -- while ensuring that security
properties are consistently enforced and can be reasoned about cleanly.
\item When used to implement isolation and controlled communication in support
of compartmentalization, CHERI's communication primitives scale with the
actual data footprint (i.e., the working set of the application).
Among other things, this implies that communication should not require
memory copying costs that grow with data size, nor trigger TLB aliasing
that increases costs as the degree of sharing increases.
Our performance goal is to support at least two orders of magnitude more
active protection domains per core than current MMU-based systems support
(going from tens or hundreds to at least tens of thousands of domains), and
similarly to reduce effective domain-crossing cost by at least two orders of
magnitude.
\item When sharing memory or object references between protection domains,
programmers should see a unified namespace connoting efficient and
comprehensible delegation.
\item When implementing efficient protection-domain switching, the
architecture supports a broad range of software-defined policies, calling
conventions, and memory models.
Where possible, software TCB paths should be avoided -- but where necessary
for semantic flexibility, they should be supported safely and efficiently.
As with MMU-based protection-domain representation and crossing, CHERI
supports both synchronous and asynchronous communication patterns.
\item Where possible, we make use of provable, deterministic protection,
avoiding probabilistic techniques or the use of architectural or
microarchitectural secrets subject to leaking or side-channel attacks.
For example, we avoid the use of cryptographic hashes, random address-space
bits, and version numbers that must be truncated to small numbers of bits
within a pointer or capability, instead making use of tagging.
This offers resistance to attacks at stastical scale (e.g., millions of
devices), and also protects software structures that might otherwise reuse
secrets allowing multiple attempts (e.g., forked daemon or zygote
processes).
Tags allow strong non-reinjection properties: pointers leaked via network
communications or IPC cannot be reinjected, despite having previously been
valid.
This in turn allows stronger temporal safety properties to be enforced by
software, due to having stronger guarantees.
Provability is an essential aspect to our work: CHERI's architectural
safety properties must be formally expressible, deterministically true, and
mechanically provable from that expression.
\item More generally, we seek to exploit hardware performance gains wherever
possible: in eliminating repeated software-generated checks by providing
richer semantics, in providing stronger underlying atomicity for pointer
integrity protection that would be very difficult to provide on current
architectures, and in providing more scalable models for memory sharing
between mutually distrusting software components.
By making these operations more efficient, we encourage their more extensive
use.
\end{enumerate}
These and other design goals permeate CHERI's abstract architecture-neutral
design as well as its architecture-specific instantiations.
\section{Capability-System Model}
In CHERI, capabilities are unforgeable tokens of authority through which
programs access all memory and services within an address space.
Capabilities are a fundamental hardware type that may be held in registers
(where they can be inspected, manipulated, and dereferenced using capability
instructions), or in memory (where their integrity is protected).
They include an integer virtual address, bounds, permissions, and other
protective metadata including an object type and one-bit tag.
\textit{Capability permissions} determine what operations (if any) are
available via the architecture.
Commonly used permissions include those authorizing memory loads, memory
stores, and instruction fetches.
Where permissions authorize memory access, \textit{capability bounds} limit
the range of addresses that may be accessed; for other permissions, bounds
constrain other forms of access (e.g., use of the object-type space).
Memory capabilities (those authorizing memory access) may be used to load
other capabilities into registers for use.
Capabilities may also be sealed in order to make their fields immutable and
the capability non-dereferenceable.
While motivated by the goal of representing pointers (protected virtual
addresses), they are also able to protect non-pointer values.
For example, \textit{sealed capabilities} without memory-access permissions
may be used to represent references to protection domains that can be
transitioned to via software-defined object invocation.
\textit{Unforgeability} is implemented by two means: tag bits and guarded
manipulation.
Each capability register (and each capability-aligned physical memory
location) is associated with a tag bit indicating that a capability is valid.
Attempts to directly overwrite a capability in memory using data (rather than
capability) stores automatically clears the tag bit.
When data is loaded into a register, its tag bit is also loaded; while data
without a valid tag can be loaded into a register, attempts to dereference or
invoke such a register will trigger an exception.
\textit{Guarded manipulation} is enforced by virtue of the ISA: instructions
that manipulate capability register fields (e.g., base, offset, length,
permissions, type) are not able to increase the rights associated with a
capability.
Similarly, sealed capabilities can be unsealed only via the invocation
mechanism, or via the unseal instruction subject to similar monotonicity
rules.
This enforces encapsulation, and prevents unauthorized access to the internal
state of objects.
Collectively, unforgeability and guarded manipulation ensure that
dereferenceable capabilities (those with their tag set) have \textit{valid
provenance}: they are derived only from other valid capabilities, and only
through valid manipulations.
All other capabilities will not have their tag set, hence cannot be
dereferenced.
\textit{Intentionality} avoids the automatic selection of a capability from
among a set in order to locate rights to authorize a requested operation.
It is always clear for every instruction what capability will authorize its
action,
e.g.,
whether
for the executing code capability (to authorize privileged ISA
operations such as MMU management), explicit operand capabilities (to query,
modify, or dereference), or implicit use of the Default Data Capability (e.g.,
when constraining legacy load and store instructions).
There are no associative lookups of capabilities to select from among several
options, and instructions are always clearly defined as expecting an integer
or a tagged capability as an operand, failing if that expectation is not met.
We anticipate that many languages will expose capabilities to the programmer
via pointers or references -- e.g., as qualified pointers in C, or mapped from
object references in Java.
Similarly, capabilities may be used to bridge communication between different
languages more safely -- for example, by imposing Java memory-protection and
security properties on native code compiled against the Java Native Interface
(JNI).
In general, we expect that languages will not expose registers directly for
management by programmers, instead using them for instruction operands and as
a cache of active values, as is the case for integer pointers today.
On the other hand, we expect that there will be some programmers using the
equivalent of assembly-language operations, and the CHERI compartmentalization
model does not place trust in compiler correctness for non-TCB code.
\section{Architectural Capabilities}
\label{section:architectural-capabilities}
\textit{CHERI capabilities} are an architectural data type, directly
implemented by the CPU hardware in a manner similar to integers or
floating-point values.
Capabilities may be held in registers or in tagged memory.
On RISC (``load-store'') architectures, CHERI-aware code can use new
capability instructions to inspect, manipulate, and dereference capabilities
held in registers.
On CISC architectures, direct use of capabilities in memory may also be
possible.
In-register modification of capability values is subject to guarded
manipulation (e.g., to enforce monotonicity), and dereference is subject to
appropriate checks (e.g., for a valid tag, sealing, appropriate permissions,
and suitable bounds).
In-memory modification of capability values is protected by tagged memory.
\subsection{Address Size and Capability Size}
Architectural capabilities are sized with respect to the address size of the
architecture.
As we define CHERI capability variants for both 32-bit architectures and
64-bit architectures, we parameterize the definitions in this chapter as
follows:
\begin{description}
\item[XLEN] is the architectural address size in bits.
For 32-bit architectures, \xlen{} is 32.
For 64-bit architectures, \xlen{} is 64.
\item[CLEN] is the architectural capability size in bits, which is 2$\times$
the architectural address size (and does not include the tag bit).
For 32-bit architectures, \clen{} is 64.
For 64-bit architectures, \clen{} is 128.
\end{description}
\subsection{Capability Contents}
Capabilities contain a number of software-accessible architectural fields,
which may differ in content and size from the microarchitectural
implementation or that is apparent from its in-memory representation:
\begin{itemize}
\item
Tag bit (``\ctag{}'', 1 bit ``out of band'' from addressable memory)
\item
Permissions mask (``\cperms{}'', parameterizable size)
\item
Software-defined permissions mask (``\cuperms{}'', parameterizable size)
\item
Flags (``\cflags{}'', parameterizable size)
\item
Object type (``\cotype{}'', 4 bits for 64-bit capabilities or 18 bits for
128-bit capabilities)
\item
Offset (``\coffset{}'', \xlen{})
\item
Base virtual address (``\cbase{}'', \xlen{})
\item
Length in bytes (``\clength{}'', \xlen{})
\end{itemize}
\subsubsection{Tag Bit}
The \ctag{} bit indicates whether an in-register capability or a
capability-sized, capability-aligned location in physical memory contains a
valid capability.
If \ctag{} is set, the capability is valid and can be dereferenced (subject to
other checks).
If \ctag{} is clear, the capability is invalid, and cannot be dereferenced.
Section~\ref{sec:tagged-memory} describes the behavior of tagged memory.
% \subsubsection{Sealed Bit}
%
% The \csealed{} flag indicates whether a capability is usable for
% general-purpose capability operations.
% If this flag is set, the capability is sealed, causing it to become
% non-dereferenceable (i.e., cannot be used for load, store, or instruction
% fetch) and immutable (i.e., whose fields cannot be manipulated).
% Capabilities are sealed with an object type (see
% Section~\ref{section:object-type}); the sealed bit may be removed using only
% the \insnref{CUnseal} or \insnref{Cinvoke} instructions (see
% Section~\ref{section:protection-domain-transition-with-cinvoke}).
% One potential application of sealed capabilities is for use as
% object-capability references -- i.e., as references to software-defined
% objects with architecturally enforced encapsulation.
% However, they are available to software for more general use in constructing
% architecturally protected references.
\subsubsection{Permission Bits}
\label{sect:capability-permission-bits}
The \cperms{} bit vector governs the architecturally defined permissions of
the capability including read, write, and execute
permissions.\footnote{Although these values are used in
CHERI-RISC-V, the specific integer constants -- and in some cases the named
permissions -- differ in Arm's Morello.}
Bits 0--11 of this field, which control use and propagation of the
capability, and also limit access to privileged instructions, are defined in
Table~\ref{table:capability-permission-bits}.
Permissions grant access only subject to constraints imposed by the current
architectural ring -- that is, they always restrict relative to the existing
architectural security model.
Permissions are also contingent on the capability \ctag{} bit being set, and
specific permissions may depend on the capability being sealed (or unsealed), or
bounds checks against \cbase{} and \clength{}, when used:
\begin{table}
\begin{center}
\begin{tabular}{llcll}
\toprule
Bit & Name & Tag? & Seal? & Bounds? \\
\midrule
0 & \cappermG & \checkmark & - & - \\
1 & \cappermX & \checkmark & Unsealed & Address\\
2 & \cappermL & \checkmark & Unsealed & Address\\
3 & \cappermS & \checkmark & Unsealed & Address\\
4 & \cappermLC & \checkmark & Unsealed & - \\
5 & \cappermSC & \checkmark & Unsealed & - \\
6 & \cappermSLC & \checkmark & Unsealed & - \\
7 & \cappermSeal & \checkmark & Unsealed & Object Type \\
8 & \cappermInvoke & \checkmark & Sealed & - \\
9 & \cappermUnseal & \checkmark & Unsealed & Object Type \\
10 & \cappermASR & \checkmark & Unsealed & - \\
11 & \cappermCid & \checkmark & Unsealed & CID \\
\bottomrule
\end{tabular}
\end{center}
\caption{Architectural permission bits for the \cperms{} capability field,
along with checks usually used alongside that permission: \textit{Tag?}
Require a valid tag; \textit{Seal?} Require the capability to be sealed or
unsealed; \textit{Bounds?} Perform a bounds check authorizing access to
the listed namespace.
See the instruction-set reference for detailed per-instruction
requirements.}
\label{table:capability-permission-bits}
\end{table}
\begin{description}
\item[\cappermG] Allow this capability to be stored via capabilities that do not themselves have \\ \cappermSLC set.
\item[\cappermX] Allow this capability to be used in the \PCC{} register as a capability for the program counter, constraining control flow.
\item[\cappermL] Allow this capability to be used to load untagged data; also requires \\ \cappermLC to permit loading a tagged value.
\item[\cappermS] Allow this capability to be used to store untagged data; also requires \\ \cappermSC to permit storing a tagged value.
\item[\cappermLC] Allow this capability to be used to load capabilities with valid tags; \cappermL is also required.
\item[\cappermSC] Allow this capability to be used to store capabilities with valid tags; the permission \cappermS is also required.
\item[\cappermSLC] Allow this capability to be used to store non-global capabilities; also requires \cappermS and \cappermSC.
\item[\cappermSeal] Allow this capability to authorize the sealing of another capability with a \cotype{} equal to this capability's \cbase{} $+$ \coffset{}.
\item[\cappermInvoke] Allow this sealed capability to be used with \insnref{CInvoke}.
\item[\cappermUnseal] Allow this capability to be used to unseal another capability with a \cotype{} equal to this capability's \cbase{} $+$ \coffset{}.
\item[\cappermCid] Allow the architectural compartment ID to be set to this capability's \cbase{} $+$ \coffset{} using \insnref{CSetCID}.
\end{description}
In general, permissions on a capability relate to its implicit or explicit
use in authorizing an operation that uses the capability -- e.g., in fetching
an instruction via \PCC{}, branching to a code capability, loading or storing
data via a capability, loading or storing a capability via a capability,
performing sealing or unsealing operations, or controlling capability
propagation.
In addition, a further \textit{privileged permission} controls access to
privileged aspects of the instruction set such as exception-handling, which
are key to the security of the model and yet do not fit the ``capability as an
operand'' model:
\begin{description}
\item[\cappermASR*] Allows access to privileged processor
permitted by the architecture (e.g., by virtue of being in supervisor mode),
with architecture-specific implications.
This bit limits access to features such as MMU manipulation, interrupt
management, processor reset, and so on.
The operating system can remove this permission to implement constrained
compartments within the kernel.
\end{description}
A richer conversion to a capability architecture might replace existing
privileged instructions (e.g., to flush the TLB) with new instructions that
accept an authorizing capability as an operand, and adopt a more granular
model for authorizing architectural privileges using capabilities than this
all-or-nothing approach.
The \cappermSLC permission bit is used to limit
capability propagation via software-defined policies: local capabilities
(i.e., those without the \cappermG permission set) can be stored only via
capabilities that have \cappermSLC set.
Normally, this permission will be set only on capabilities that, themselves,
have the \cappermG bit cleared.
This allows higher-level, software-defined policies, such as ``Disallow storing stack references to heap memory'' or ``Disallow passing local capabilities via cross-domain procedure calls,'' to be implemented.
We anticipate both generalizing and extending this model in the future in
order to support more complex policies -- e.g., relating to the propagation of
garbage-collected pointers, or pointers to volatile vs. non-volatile memory.
\subsubsection{Software-Defined Permission Bits}
The \cuperms{} bit vector may be used by the kernel or application programs
for software-defined permissions.
They can be masked and retrieved using the same \insnref{CAndPerm} and
\insnref{CGetPerm} instructions that operate on hardware-defined
permissions.
We define 0 software-defined permission bits for 64-bit capabilities, and 4
software-defined permission bits for 128-bit capabilities.
Software-defined permission bits can be used in combination with existing
hardware-defined permissions (e.g., to annotate code or data capabilities
with further software-defined rights), or in isolation of them (with all
hardware-defined permissions cleared, giving the capability only
software-defined functionality).
For example, software-defined permissions on code capabilities could be
employed by a userspace runtime to allow the kernel to determine whether a
particular piece of user code is authorized to perform system calls.
Similarly, user permissions on sealed data capabilities might authorize use of
specific methods (or sets of methods) on object capabilities, allowing
different references to objects to authorize different software-defined
behaviors.
Capabilities with all hardware-defined permission bits cleared have only
software-defined interpretations, making them suitable for potential use as
unforgeable tokens of authority authorizing use of in-application or kernel
services.
\subsubsection{Flags}
\label{sec:arch-flags}
The \cflags{} field can be read with the \insnref{CGetFlags} instruction
and written with the \insnref{CSetFlags} instruction.
There are no architecture-neutral flags currently defined, therefore the size and
interpretation of this field are entirely architecture specific.
\subsubsection{Object Type}
\label{section:object-type}
\begin{table}
\begin{center}\begin{tabular}{r|l}
\cotype{} value & Interpretation \\
\hline\hline
$2^{\xlen{}} - 1$ & Unsealed capability \\
\hline
$2^{\xlen{}} - 2$ & Sealed entry (``sentry'') capabilities; see \cref{sec:arch-sentry} \\
\hline
$2^{\xlen{}} - 3$ & Reserved (experimental ``memory type tokens''; see \cref{app:exp:typetoken}) \\
\hline
$2^{\xlen{}} - 4$ & Reserved (experimental ``indirect enter capabilities''; see \cref{app:exp:indsentry}) \\
\hline
$2^{\xlen{}} - 5$ & Reserved \\
through & \\
$2^{\xlen{}} - 16$ & \\
\hline
other & Capability sealed by \insnref{CSeal} \\
\end{tabular}\end{center}
%
\caption{Object types and their architecture-specified roles.}
\label{tab:archotypes}
%
\end{table}
The \cotype{} field is 4 bits for 64-bit capabilities, and 18 bits for 128-bit
capabilities.
The field indicates whether a capability is sealed and, if so,
what ``type'' it has; see \cref{tab:archotypes} for defined values.
CHERI uses multiple object types to allow software to create unforgeable
associations between sealed capabilities.
The implementation values in \cotype{} fields are translated to the abstract
space as if by sign extension. Attempts to seal capabilities to types that
cannot be expressed by the implementation will fail in an
implementation-specified way, but generally similarly to any other
representability failure.
%
If a capability is sealed, it becomes non-dereferenceable (i.e., cannot be used
for load, store, or instruction fetch) and immutable (i.e., whose fields cannot
be manipulated). Capability unsealing is mediated either by capabilities (via
the \insnref{CUnseal} instruction) or by control transfers (via
the \insnref{CInvoke} instruction, as in
\cref{section:protection-domain-transition-with-cinvoke}, or
\insnref{CJALR} instructions, as in \cref{sec:arch-sentry}).
%
One potential application of sealed capabilities is for use as
object-capability references -- i.e., as references to software-defined objects
with architecturally enforced encapsulation. However, they are available to
software for more general use in constructing architecturally protected
references.
\pmnote{There is inconsistency in various places where a 18-bit
\cotype{} is supposed to hold a 64-bit value like $2^{64}-1$. I've
marked the places I've found; there might be others.}
\subsubsection{Base}
The \xlen{}-bit \cbase{} field is the base address of the segment described
by a capability.
The \cbase{} field is the \textit{lower bound} of the capability:
dereferencing an effective virtual address below \cbase{} will throw an
exception.
In the presence of compressed capabilities, not all possible \xlen{}-bit
values of
\cbase{} will be representable (see Section~\ref{compression}).
\subsubsection{Offset}
The \xlen{}-bit \coffset{} field holds a free-floating pointer that will be
added to the base when dereferencing a capability.
The value can float outside of the range described by the capability -- e.g.,
as a result of using \insnref{CSetOffset} to set the offset to a negative
value, or to a value greater than \clength{} -- but an exception will be
thrown if a requested dereference is out of range.
A non-zero offset may be used when a language-level pointer refers to a
location within a memory allocation or data structure; for example, to point
into the middle of a string, or at a non-zero index within an array.
A non-zero offset may also be used when the lower bound of a memory allocation
is insufficiently aligned to permit precise description with the \cbase{}
field of a compressed capability (see Section~\ref{compression}).
\subsubsection{Address}
The address, or \ccursor{}, of a capability is the sum of its
\cbase{} and \coffset{} fields.
The components of the virtual address may be accessed separately (e.g., via
\insnref{CGetOffset}), or as a single combined entity (e.g., via
\insnref{CSetAddr}) depending on the software
use case.
\nwfnote{As presently defined, CGetOffset appears not to carry out
bounds checks, which means that software really should get the length (and
base) and do the math as well if the bound(s) matter(s). Could there be
utility to additional instructions for checked access when the intent is to
extract only in-bound offsets and addresses? Or, to dodge the question
about what such a checked accessor returns when the cursor is out of bounds,
a CBTS/CBTU-like pair of tests for the cursor being in-bounds? While a
CIncOffset by zero would clear the tag of an out of bounds capability, this
seems too fragile, too prone to optimization, to depend on from C.}
\subsubsection{Length}
The \xlen{}-bit \clength{} field is the length of the segment described by a
capability.
The sum of \cbase{} and \clength{} is the \textit{upper bound} of the
capability: accessing at or above \cbase{} $+$ \clength{} will throw an
exception.
In the presence of compressed capabilities, not all possible \xlen{}-bit
values of \clength{} will be representable (see Section~\ref{compression}).
\subsection{Capability Values}
\subsubsection{Pointer Values in Capabilities}
In general, C and C++-language pointers are suitable to be represented as
memory capabilities (i.e., those that are unsealed and have a memory
interpretation by virtue of memory-related permissions).
This includes both data pointers, which may have enabled permissions that
include \cappermL, \cappermS, \cappermLC, and
\cappermSC, and code pointers, which may have enabled
permissions that include \cappermL, \cappermX, and
\cappermLC.
Other permissions, such as \cappermG or \cappermInvoke, may also be present.
The following architectural values will normally be used:
\begin{itemize}
\item The \ctag{} is set.
\item The capability is unsealed (has \cotype{} of $2^{\xlen{}}-1$).
\item \cperms{} contains a suitable combination of load, store, and
execute permissions, as well as other possible permissions.
\item \cbase{} will point to the bottom of the memory allocation, allowing for
suitable alignment if bounds compression is used.
\item \coffset{} will point within the memory allocation (but may point
outside in some circumstances).
\item The address will be equal to the integer value of the pointer.
\item \clength{} will be the length of the memory allocation, allowing for
suitable alignment if bounds compression is used.
\end{itemize}
Code pointers will normally include \cappermL and \cappermLC
so that constant islands and global variables can be accessed via the code
segment.
Due to bounds compression, the memory allocation may require stronger than
word alignment or padding so as to ensure non-overlapping bounds with other
allocations.
Implied pointers in the run-time environment, originating in
compiler-generated code or the run-time linker, such as Program Linkage Table
(PLT) entries, Global Offset Table (GOT) entries, the Thread-Local Storage
(TLS) pointer, C++ v-table pointers, and return addresses, will typically have
similar values.
Note that the \cflags{} field may have an architecture-specific default value.
\subsubsection{The NULL Capability}
When representing C-language pointers as capabilities, it is important to have
a definition of NULL with as close-as-possible semantics to today's
definition that NULL has an integer value of 0.
We choose to define a NULL capability that has the following architecture
values set:
\begin{itemize}
\item \ctag{} is cleared.
\item The capability is unsealed (has \cotype{} of $2^{\xlen{}}-1$).
\item \cperms{} is 0x0.
\item \cflags{} is 0x0.
\item \cbase{} is 0x0.
\item \coffset{} is 0x0.
\item By implication, the virtual address of the capability is 0x0.
\item \clength{} is the largest permitted length ($2^{\xlen{}}$).
\end{itemize}
\subsection{Integer Values in Capabilities}
\label{subsection:integer_values_in_capabilities}
In the C language, the \ccode{intptr_t} type is intended to be an integer
type large enough to hold a pointer, and sees two common uses: an opaque field
that can hold either an integer or pointer type; or an integer type permitting
arithmetic and other integer operations on pointer values.
We find it convenient to store an integer value in a capability using the
following conventions:
\begin{itemize}
\item \ctag{} is cleared.
\item The capability is unsealed (has \cotype{} of $2^{\xlen{}}-1$).
\item \cperms{} is 0x0.
\item \cflags{} is 0x0.
\item \cbase{} is 0x0.
\item \coffset{} is the integer value to be stored.
\item By implication, the virtual address of the capability is the integer
value to be stored.
\item \clength{} is the largest permitted length ($2^{\xlen{}}$).
\end{itemize}
Note that:
\begin{itemize}
\item Adding an integer value to the offset of a NULL capability (e.g., using
\insnref{CIncOffset}) gives a capability that follows these
conventions.
\item Maximal bounds allow the virtual address to take on any value without
risking a bounds representability failure during arithmetic -- in contrast
to using a maximum length of 0, which might otherwise seem intuitive.
\end{itemize}
\subsection{General-Purpose Capability Registers}
General-purpose capability registers are registers that are able to load,
store, inspect,
manipulate, and dereference capabilities while preserving their 1-bit tag and
full set of structured fields.
New capability-aware instructions (see
Section~\ref{sec:capability-aware-instructions}) allow use of new registers or
new fields added to existing registers, and via guarded manipulation must
implement properties such as tag preservation, monotonic transformation, and
so on.
Capability registers are tagged so that capability-oblivious operations --
such as tag-preserving memory copies of regions containing both data and
capabilities -- can be performed, preserving both set and unset tag bits.
This means that all capability-aware instructions dereferencing a capability
must check for a valid tag, as capability registers may contain data values
that are not permitted to be dereferenced.
CHERI architectures extend the existing general-purpose integer
register file to allow it to hold \xlen{}-sized integers and also capabilities, with
instructions selecting the desired semantics when utilizing a register.
This is similar to extension of 32-bit registers to 64-bit registers, in which
32-bit load, store, and manipulation can take place despite the full register
size being large enough to hold a 64-bit value.
A similar set of constraints applies: when an integer is loaded into a
capability-width register, the tag bit and remainder of the non-integer data
bits in the register must be zeroed, in similar manner to the use of zero or
sign extension when loading a smaller integer into a larger integer register.
When a register containing a tagged capability is used as an input to an
integer arithmetic operation, we recommend that the virtual address of a
capability be used as the integer value used for input.
\jhbnote{We should probably make clear here that the
integer-into-a-cap-reg case follows Section
~\ref{subsection:integer_values_in_capabilities}.}
It is essential that intentionality be maintained: instructions
must not select between integer and capability interpretations based on the
tag value.
Instead, instructions must specifically interpret input and output registers
as integers or as capabilities.
If a capability dereference is expected, an exception must be thrown if the
input register does not contain a valid tag.
If an integer dereference is to be performed, only the integer portion of the
capability register will be used (per above, the virtual address of the
capability), and it will be checked using an appropriate implied
capability such as the Program-Counter Capability (\PCC{}) or Default Data
Capability (\DDC{}).
Not all
integer registers may be extended to hold capabilities.
A tradeoff exists around the extension of existing well-supported ABIs, such
as the calling convention, vs. the impact of register-file growth and opcode
utilization.
Larger numbers of capability registers will increase the memory footprint of
context switching and the cost of stack spillage (where a callee cannot know
whether a register requires saving as a full capability or whether integer
width would be sufficient).
Similarly, larger numbers of available capability registers increase the
opcode footprint of capability-relative instructions.
While this opcode space is no greater than for integer-relative instructions,
in some architectures (e.g., ARMv8-A), opcode space is at a substantial premium,
and adding new capability variants of all load/store/jump instructions will
over-consume or exhaust the space.
Reducing the number of capability registers comes at other costs, such as
potentially disrupting current ABI design choices, and increasing register
pressure for pointer-intensive workloads.
Here, a variety of design points are available, but one option would be to
limit capabilities to a subset of the full register file, allowing a smaller
number of bits to name the available capability registers.
This pressure is especially acute in variable-size instruction sets (e.g.,
with the RISC-V compressed instruction set).
Other options to avoid this pressure include the introduction of new opcode
modes in which existing opcodes can be reused to refer to capabilities instead
of integers, at a cost to binary compatibility.
The most straightforward choice, where opcode space is plentiful with respect
to the vocabulary of load-store instructions, is to allow all existing
general-purpose integer registers to hold capabilities.
Microarchitectural and in-memory representations of capabilities may differ
substantially from the architectural representation in terms of size and
contents, but these differences will not be exposed via instructions operating
on capability-register fields.
See Section~\ref{compression} for a discussion of capability compression,
used to avoid storing a minimum of 3$\times$ \xlen{} bits in each capability.
\subsection{Special Capability Registers}
\label{section:special-capability-registers}
In addition to the general-purpose capability registers available for use via
capability load, store, jump, query, and manipulation instructions, there are
also a set of \textit{Special Capability Registers} (SCRs).
These capability registers provide similar functionality to
architecture-specific special registers such as RISC-V \textit{Control
and Status Registers}. In many cases, SCRs extend an existing
special register.
SCRs are accessed via new variants of architecture-specific
instructions used to access special registers, and serve specific
architectural functions.
Access to special capability registers is controlled on a case-by-case basis
and may be restricted based on \cappermASR, execution ring, or
exception-handling state.
The specific registers vary by underlying architecture, but will include the
following:
\begin{description}
\item[Program Counter Capability (\PCC{})] extends the existing Program
Counter (\PC{}) to be a full capability, imposing validity, permission,
bounds, and other checks on instruction fetch.
\item[Default Data Capability (\DDC{})] constrains legacy non-capability loads
and stores, controlling data accesses to memory.
\end{description}
Although these capability special registers may be viewed as extensions to
existing special registers (e.g., \PC{}), CHERI introduces new
capability-based instructions to get and set their values, rather than
conflating them with existing integer-based special-register instructions in
the architecture ISA, in order to ensure intentional use.
Where existing special registers, such as the Program Counter (\PC{}),
are extended to become capabilities, the
semantics of accessing the integer interpretation must be determined with
care.
Unlike with the general-purpose integer register file, it may be desirable for
reasons of compatibility to modify the capability while retaining its tag
and other metadata (such as bounds and permissions) without modification --
subject to maintaining monotonicity.
For example, when modifying \PC{}, it is desirable to leave other fields (such
as bounds of \PCC{}) unmodified, so that
capability-unaware code can jump within its code segment without experiencing
a tag violation.
%%%% SUCH AS BOUNDS was ambiguous, in a sentence with TOO MANY COMMAS,
%%%% and I may have miscorrected it. PLEASE VET MY SECOND TRY.
\subsection{Values Extended to Capabilities}
Several other existing values also require extending to hold
capabilities. These values may be stored in a general-purpose
capability register, a special capability register, or some other
architecture-specific location. When possible, the capability variant
should be stored as an extension of the equivalent value from the base
architecture:
\begin{description}
\item[Exception Program Counter Capability] Just as conventional
architectures save the \PC{} following an exception and restore the
\PC{} on exception return, CHERI architectures must save and restore
the full \PCC{} when handling exceptions.
\item[Exception Code Capability] When an exception is taken, \PCC{} must
be replaced with a code capability containing a suitable
execution and security context for the exception handler.
\item[Exception Data Capability] When an exception is taken, the
exception handler must have a way to access a suitable data
capability for use by the exception handler. This capability should
permit access to a stack pointer as well as a value for \DDC{}.
\item[Thread-Local Storage] A capability extended
version of a Thread-Local Storage (TLS) register, available to any executing
code.
\end{description}
\section{Capabilities in Memory}
Maintaining the integrity and provenance validity of capabilities stored to,
and later read from, memory, is an essential feature of the CHERI
architecture.
Capabilities may be stored to memory in a broad variety of circumstances,
including, when language-level pointers are implemented using capabilities,
operating-system context switching, stack spills of capability registers,
stack storage for local pointer variables, pushing return capabilities to the
stack on function call, the capabilities held in Global Offset Table (GOT)
structures to reach global variables, global variables themselves holding
types implemented via capabilities, Procedure Linkage Table (PLT) entries
holding code capabilities that can be jumped to, and so on.
As tagged memory maintains tag bits at capability-sized, capability-aligned
intervals, stores of capabilities to memory will retain their tags only if
at suitable alignment.
This allows capabilities to be held at any suitably aligned memory location,
interleaved arbitrarily with other data -- such as is commonly the case with
pointers and other data today.
\subsection{In-Memory Representation}
As implemented in CHERI-RISC-V, all in-memory capability bits
are directly addressable via ordinary data accesses (e.g., byte loads) except
for the tag bit, which is stored ``out-of-band'' as a 65th or 129th bit.
The in-memory capability representation will typically not be a direct mapping
of architectural capability fields into memory, as fields may be stored as
partially computed values to improve performance (e.g., storing a virtual
address rather than base and offset), to reduce size (e.g., through bounds
compression), or to utilize multiple formats (e.g., for unsealed vs.\@ sealed
capabilities).
Given the prior definitions, we impose several constraints on the in-memory
representation:
\begin{description}
\item[NULL has an all zeroes in-memory representation, with cleared tag.]
This definition allows zero-filled memory to be interpreted as NULL-filled
memory when loaded as a capability, providing greater consistency with the
C-language expectations for NULL pointers.
\item[The bottom \xlen{} bits of a capability hold its address value.]
Supporting casts between a capability and an ordinary integer type sized to
correspond to the size of a virtual address has significant utility in
practical C code.
\end{description}
The CHERI Concentrate compression format used for both 64-bit and 128-bit
capabilities is described in Section~\ref{compression}.
These formats vary in terms of the number of permission bits they offer, and
also bounds precision effects stemming from capability compression. Concrete
architectures may additionally allocate bits for the \cflags{} field.
\pdrnote{Do we want to somehow specify the in-memory representation of \cflags{}?
It seems hard to do this in an arch-neutral manner.}
Software authors are discouraged from directly interpreting the in-memory
capability representation to improve the chances of software portability
(e.g., across architectures) and forward compatibility (e.g., with respect to
newly added permissions or other changes in field behavior).
This also allows multi-endian architectures or heterogeneous designs to utilize
a single endianness for in-memory capability storage (e.g., little endian) to
avoid ambiguities in which the same in-memory bit pattern might otherwise
describe two different sets of rights depending on where it is loaded and
interpreted.
This is also important given the desire to be able to retrieve the virtual
address or integer value of an in-memory capability by loading from the bottom
\xlen{} bits of the capability.
Despite the software benefits from avoiding encoding the in-memory capability
representation, it is important that the in-memory representation be
considered architectural (i.e., having a defined and externally consistent
representation) to better support systems software functions such as swap,
core dumps, debuggers, virtual-machine migration, and efficient run-time
linking, which may embed that representation within file formats or network
protocols.
\subsection{Tagged Memory}
\label{sec:tagged-memory}
CHERI relies on tagged physical memory: the association of a 1-bit {\em tag}
with each capability-sized, capability-aligned location in physical memory.
Associating tags with physical memory ensures that if memory is mapped at
multiple virtual addresses, the same tags will be loaded and stored regardless
of the virtual address through which it is accessed.
Tags must be atomically bound to the data they protect.
As a result, it is expected that tags will be cached with the memory they describe within the cache hierarchy.
When a capability-sized value in a capability register is written to a
capability-aligned area of memory using a capability store instruction, and
the capability via which the store takes place has suitable permissions, the
tag bit on the capability register will be stored atomically in memory with
the capability value.
Other stores of untagged capability values or other types (e.g., bytes, half
words, words, floats, doubles, and double words) across one or more
capability-aligned locations in memory will atomically clear the corresponding
tag bits for that memory.
When a capability-sized value is loaded into a capability register from a
capability-aligned location in memory using a capability load instruction, and
the capability via which the load takes place has suitable permissions, the
tag associated with that memory is loaded atomically into the register along
with the capability value.
Otherwise, loads will clear the capability register tag bit.
Strong atomicity properties are required such that it is not possible to
partially overwrite a capability value in memory while retaining the tag, or
partially load a capability and have the tag bit set.
These strong atomicity properties ensure that tag bits are set only on
capability values that have valid provenance -- i.e., that have not been
corrupted due to data stores into their contents, or undergone non-monotonic
transformations.