Skip to content

Commit 2b3a034

Browse files
authored
Merge pull request #2154 from Arnaud-de-Grandmaison-ARM/bounce-buffers
First sketch of the CCA DA LP.
2 parents b0b1387 + b35cb79 commit 2b3a034

File tree

5 files changed

+460
-23
lines changed

5 files changed

+460
-23
lines changed
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
---
2+
title: "About CCA Realms"
3+
weight: 2
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
Arm’s *Realm Management Extension (RME)* is a key security feature introduced in
10+
the Armv9-A architecture. It enables a new form of hardware-enforced isolation
11+
designed to support _confidential computing_. It defines the set of hardware
12+
features and properties that are required to comply with the Arm *Confidential
13+
Computing Architecture (CCA)* architecture.
14+
15+
At the heart of RME is the concept of a *Realm*, a protected execution
16+
environment that operates independently from the conventional *Normal World*
17+
(used by operating systems and applications) and the *Secure World* (used by
18+
trusted firmware or TEE). Realms are managed by a new privileged entity called
19+
the *Realm Management Monitor (RMM)* and are enforced by the hardware via the
20+
*Granule Protection Table (GPT)* and *Granule Transitioning* mechanism.
21+
22+
Realms allow lower-privileged software, such as an application or a virtual
23+
machine, to protect its content and execution from attacks by higher-privileged
24+
software, such as an OS or a hypervisor. Realms provide an environment for
25+
confidential computing, without requiring the Realm owner to trust the software
26+
components that manage the resources that the Realm uses.
27+
28+
To be useful, a Realm has to interact with the rest of the world at some point.
29+
For example, a network interface is likely to be needed. This learning path will
30+
teach you how devices are attached and used by Realms.
Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
---
2+
title: "Device attach - part 1: virtio"
3+
weight: 2
4+
5+
### FIXED, DO NOT MODIFY
6+
layout: learningpathall
7+
---
8+
9+
This section is a high level overview of VirtIO and Bounce Buffers, and how they
10+
relate to CCA Realms.
11+
12+
A Realm has to use physical devices at some point to interact with the external
13+
and / or physical world. The easiest way to do this is by using VirtIO, which
14+
provides a fast high level emulation layer. This can be seen as the level-0 of
15+
device attach.
16+
17+
As will be seen later in this learning path, more evolved device attach can be
18+
performed leveraging hardware security features like PCIe-TDISP (**T**EE
19+
**D**evice **I**nterface **S**ecurity **P**rotocol) and PCIe-IDE (**I**ntegrity
20+
and **D**ata **E**ncryption), where the host OS can assign a physical device to
21+
a realm, which will be able to make security measurements on the physical device
22+
and include it in its base and measurements.
23+
24+
## VirtIO
25+
26+
### What is VirtIO ?
27+
28+
VirtIO is an abstraction layer for virtual devices in virtualized environments.
29+
It provides standardized and efficient interfaces between guest virtual machines
30+
(VMs) and host devices, making it easier to develop _paravirtualized_ drivers.
31+
_Paravirtualized_ means that the guest OS is aware it’s running in a virtualized
32+
environment and can use optimized drivers (VirtIO) to communicate with virtual
33+
hardware. Emulating hardware devices (like NICs or disks) for VMs is slow and
34+
inefficient. VirtIO provides a standardized and efficient interface that allows
35+
VMs to bypass full device emulation and instead use optimized drivers.
36+
37+
VirtIO is most commonly used with KVM/QEMU virtualization. Example drivers are:
38+
- `virtio-net`: Paravirtualized networking
39+
- `virtio-blk`: Block device (disk) access
40+
- `virtio-fs`: File sharing (host ↔ guest)
41+
- `virtio-balloon`: Dynamic memory management
42+
- `virtio-rng`: Random number source
43+
- `virtio-console`: Simple console interface
44+
- ...
45+
46+
### How VirtIO works in VMs
47+
48+
1. The Host Hypervisor (e.g., QEMU/KVM) exposes VirtIO “backend” devices.
49+
2. The guest OS loads VirtIO _frontend_ drivers (e.g., `virtio_net`,
50+
`virtio_blk`) that speak the VirtIO protocol.
51+
3. Communication happens via shared memory (`virtqueues`) for I/O operations,
52+
avoiding full device emulation.
53+
4. Devices are exposed over the PCI or MMIO bus to the guest.
54+
55+
For example, instead of emulating an Intel e1000 NIC, the host exposes a
56+
`virtio-net` interface to the guest OS and the guest OS uses the `virtio-net`
57+
driver to send/receive packets via shared buffers.
58+
59+
## Bounce buffers
60+
61+
### What are bounce buffers?
62+
63+
Bounce buffers are a generic mechanism part of the Linux kernel. They are
64+
temporary memory buffers used in the Linux kernel to handle situations where
65+
direct memory access (DMA) can’t be performed directly on the original data
66+
buffer. This often happens because:
67+
1. The original buffer is not physically contiguous.
68+
2. The buffer is in high memory or not accessible to the device.
69+
3. The buffer doesn’t meet alignment or boundary requirements of the device.
70+
71+
### Why _bounce_ buffers?
72+
73+
Data _bounces_ between:
74+
- The original buffer (in user/kernel space) and
75+
- The DMA-capable bounce buffer (used for I/O with the device)
76+
77+
This ensures that data transfers can still happen even when the original memory
78+
is not suitable or accessible for transfers.
79+
80+
## CCA Realms, VirtIO and bounce buffers
81+
82+
The defining feature of a Realm is that its memory (called *Realm memory*) is
83+
cryptographically isolated from both the Normal and Secure Worlds. This means
84+
that:
85+
- Realm memory is encrypted using keys that are unique to each Realm.
86+
- Non-Realm entities (like the host OS or hypervisor) cannot directly read or
87+
write Realm memory.
88+
- Even Direct Memory Access (DMA) from peripherals or untrusted drivers cannot
89+
access Realm data.
90+
91+
This design ensures confidentiality but introduces a problem: *how can Realms
92+
interact with untrusted components*, such as:
93+
- Network stacks in the host OS,
94+
- Storage subsystems,
95+
- I/O devices managed by untrusted drivers?
96+
97+
The solution to safely exchange data between a Realm and the outside World is to
98+
use _bounce buffers_ as an intermediary !
99+
100+
### How bounce buffers are used with RME
101+
102+
1. Exporting Data:
103+
- A Realm application prepares some data (e.g., results of computation).
104+
- It copies this data from protected Realm memory into a bounce buffer.
105+
- The Realm notifies the untrusted host or hypervisor that the data is ready.
106+
- The host retrieves the data from the bounce buffer.
107+
108+
2. Importing Data:
109+
- The host places data (e.g., input from a file or device) into a bounce buffer.
110+
- The Realm is notified and validates the source.
111+
- The Realm copies the data from the bounce buffer into its protected memory.
112+
113+
This pattern preserves confidentiality and integrity of Realm data, since:
114+
- The Realm never allows direct access to its memory.
115+
- It can validate and sanitize any data received via bounce buffers.
116+
- No sensitive data is exposed without explicit copying.
117+
118+
### Confidentiality preserved with bounce buffers, really?
119+
120+
In the previous section, it was mentioned that _bounce buffers preserves
121+
confidentiality_, a sentence which deserves a bit more thoughts. Bounce buffers
122+
are nothing more than an explicitly shared temporary area between the Realm
123+
world and the outside world. This does indeed preserve the confidentiality of
124+
all the rest of the Realm data. On the other hand, for the data being
125+
transferred, it is leaving the Realm world and will only remain confidential if it
126+
is encrypted in some ways, e.g. for network traffic, TLS should be used.
127+
128+
## Seeing a Realm's bounce buffers at work
129+
130+
Let's put this to work and check for ourselves that bounce buffers are used. This
131+
will build on the Key Broker demo that was used in the [CCA
132+
Essentials learning path](/learning-paths/servers-and-cloud-computing/cca-essentials/example/),
133+
demonstrating an end-to-end attestation.
134+
135+
### Start the **K**eyb **B**roker **Server** (KBS)
136+
137+
First, pull the docker container image with the pre-built KBS, and then run the container:
138+
139+
```bash
140+
docker pull armswdev/cca-learning-path:cca-key-broker-v2
141+
docker run --rm -it armswdev/cca-learning-path:cca-key-broker-v2
142+
```
143+
144+
Now within your running docker container, get a list of network interfaces:
145+
146+
```bash
147+
ip -c a
148+
```
149+
150+
The output should look like:
151+
152+
```output
153+
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
154+
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
155+
inet 127.0.0.1/8 scope host lo
156+
valid_lft forever preferred_lft forever
157+
inet6 ::1/128 scope host
158+
valid_lft forever preferred_lft forever
159+
20: eth0@if21: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
160+
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
161+
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
162+
valid_lft forever preferred_lft forever
163+
```
164+
165+
Start the KBS on the `eth0` network interface, and replace 172.17.0.2 shown in
166+
the command below with the IP address corresponding to eth0 in the output of `ip
167+
-c a` above.
168+
169+
```bash
170+
./keybroker-server -v --addr 172.17.0.2
171+
```
172+
173+
The output should look like:
174+
175+
```output
176+
INFO starting 16 workers
177+
INFO Actix runtime found; starting in Actix runtime
178+
INFO starting service: "actix-web-service-172.17.0.2:8088", workers: 16, listening on: 172.17.0.2:8088
179+
```
180+
181+
### Get into a Realm
182+
183+
With the Key Broker Server running in one terminal, open up a new terminal in
184+
which you will run the **K**ey **B**roker **C**lient (KBC). The intent is to
185+
observe that the data transmitted over the network (thru `virtio_net`) are
186+
indeed using bounce buffers.
187+
188+
Pull the docker container image with the pre-built KBC, and then run the container:
189+
190+
```bash
191+
docker pull armswdev/cca-learning-path:cca-simulation-v2
192+
docker run --rm -it armswdev/cca-learning-path:cca-simulation-v2
193+
```
194+
195+
Within the running container, launch the `run-cca-fvp.sh` script to run the Arm
196+
CCA pre-built binaries on the FVP:
197+
198+
```bash
199+
./run-cca-fvp.sh
200+
```
201+
The `run-cca-fvp.sh` script uses the screen command to connect to the different
202+
UARTs in the FVP.
203+
204+
You should see the host Linux kernel boot on your terminal and you will be
205+
prompted to log in to the host. Enter root as the username:
206+
207+
```output
208+
[ 4.169458] Run /sbin/init as init process
209+
[ 4.273748] EXT4-fs (vda): re-mounted 64d1bcff-5d03-412c-83c6-48ec4253590e r/w. Quota mode: none.
210+
Starting syslogd: OK
211+
Starting klogd: OK
212+
Running sysctl: OK
213+
Starting network: [ 5.254843] smc91x 1a000000.ethernet eth0: link up, 10Mbps, half-duplex, lpa 0x0000
214+
udhcpc: started, v1.36.1
215+
udhcpc: broadcasting discover
216+
udhcpc: broadcasting select for 172.20.51.1, server 172.20.51.254
217+
udhcpc: lease of 172.20.51.1 obtained from 172.20.51.254, lease time 86400
218+
deleting routers
219+
adding dns 172.20.51.254
220+
OK
221+
222+
Welcome to the CCA host
223+
host login: root
224+
(host) #
225+
```
226+
227+
Change directory to `/cca` and use `lkvm` to launch a guest Linux in a Realm:
228+
```bash
229+
cd /cca
230+
./lkvm run --realm --disable-sve --irqchip=gicv3-its --firmware KVMTOOL_EFI.fd -c 1 -m 512 --no-pvtime --disk guest-disk.img --restricted_mem --virtio-transport pci --pmu --network mode=user
231+
```
232+
233+
You should see the realm boot. Note that `lkvm` is invoked with `--network
234+
mode=user`, which makes the guest see the network thru a VirtIO device.
235+
236+
After boot up, which might take some time, you will be prompted to log in at the
237+
guest Linux prompt. Use root again as the username:
238+
239+
```output
240+
Starting syslogd: OK
241+
Starting klogd: OK
242+
Running sysctl: OK
243+
Starting network: udhcpc: started, v1.36.1
244+
udhcpc: broadcasting discover
245+
udhcpc: broadcasting select for 192.168.33.15, server 192.168.33.1
246+
udhcpc: lease of 192.168.33.15 obtained from 192.168.33.1, lease time 14400
247+
deleting routers
248+
adding dns 172.20.51.254
249+
OK
250+
251+
Welcome to the CCA realm
252+
realm login: root
253+
(realm) #
254+
```
255+
256+
### Observe bounce buffer usage in the realm
257+
258+
First, check that the Linux kernel has tracing support:
259+
260+
```bash { output_lines="2-46" }
261+
ls /sys/kernel/debug/tracing/events/
262+
9p i2c_slave qcom_glink
263+
alarmtimer icmp qcom_smp2p
264+
asoc initcall qdisc
265+
block interconnect ras
266+
bpf_test_run io_uring raw_syscalls
267+
bpf_trace iomap rcu
268+
bridge iommu regmap
269+
capability ipi regulator
270+
cgroup irq rpcgss
271+
chipidea jbd2 rpm
272+
clk kmem rpmh
273+
cma ksm rseq
274+
compaction kvm rtc
275+
cpuhp kyber sched
276+
cros_ec libata scmi
277+
csd lock scsi
278+
dev lockd signal
279+
devfreq maple_tree skb
280+
devlink mdio smbus
281+
dma memcg sock
282+
dma_fence migrate spi
283+
dpaa2_eth mmap spmi
284+
dpaa_eth mmap_lock sunrpc
285+
dwc3 mmc swiotlb
286+
e1000e_trace module task
287+
enable mtu3 tcp
288+
error_report musb tegra_apb_dma
289+
ext4 napi thermal
290+
fib neigh thermal_power_allocator
291+
filelock net thp
292+
filemap netfs timer
293+
fsl_edma netlink timer_migration
294+
ftrace nfs timestamp
295+
gadget nfs4 tlb
296+
gpio notifier udp
297+
gpu_mem oom ufs
298+
handshake optee vmalloc
299+
header_event page_isolation vmscan
300+
header_page page_pool watchdog
301+
hns3 pagemap workqueue
302+
huge_memory percpu writeback
303+
hugetlbfs power xdp
304+
hw_pressure printk xhci-hcd
305+
hwmon pwm
306+
i2c qcom_aoss
307+
```
308+
309+
As shown in the above transcript, you should get a list of the available trace
310+
points.
311+
312+
Now, enable the kernel tracing infrastructure together with the bounce buffer
313+
tracing, read the trace in the background (filtering on `keybroker-app-`) and
314+
run the Key Broker Client application in the realm, using the endpoint address
315+
that the Key Broker Server is listening on (from the other terminal):
316+
317+
```bash
318+
echo 1 > /sys/kernel/debug/tracing/tracing_on
319+
echo 1 > /sys/kernel/debug/tracing/events/swiotlb/enable
320+
grep keybroker-app- /sys/kernel/debug/tracing/trace_pipe &
321+
keybroker-app -v --endpoint http://172.17.0.2:8088 skywalker
322+
```
323+
324+
In the `keybroker-app`command above, `skywalker` is the key name that is
325+
requested from the KBS.
326+
327+
You should get an output looking like:
328+
329+
```output
330+
INFO Requesting key named 'skywalker' from the keybroker server with URL http://172.17.0.2:8088/keys/v1/key/skywalker
331+
INFO Challenge (64 bytes) = [5c, ec, 1e, f5, 93, 54, 4a, 8a, ee, 2e, 46, a0, 50, 0d, 41, dd, d4, 60, b0, 58, 5b, 51, 71, 76, d1, 66, d3, b7, 38, e8, af, ae, 0a, 07, 4e, c5, 60, dc, 4a, c0, b8, 73, 98, d9, bd, af, 41, 96, 99, 6d, 74, cc, 19, 70, 24, c4, c9, 5c, 21, 61, 1a, cb, 76, 75]
332+
INFO Submitting evidence to URL http://172.17.0.2:8088/keys/v1/evidence/1928844131
333+
INFO Attestation success :-) ! The key returned from the keybroker is 'May the force be with you.'
334+
keybroker-app-143 [000] b..2. 1772.607321: swiotlb_bounced: dev_name: 0000:00:00.0 dma_mask=ffffffffffffffff dev_addr=80b6717e size=66 FORCE
335+
keybroker-app-143 [000] b..2. 1772.644478: swiotlb_bounced: dev_name: 0000:00:00.0 dma_mask=ffffffffffffffff dev_addr=80b6717e size=66 FORCE
336+
```
337+
338+
Note that the interleaving of the trace messages and KBC messages might differ
339+
from one run to another.

0 commit comments

Comments
 (0)