You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
163 lines
7.4 KiB
163 lines
7.4 KiB
4 months ago
|
Advisory TFV-1 (CVE-2016-10319)
|
||
|
===============================
|
||
|
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Title | Malformed Firmware Update SMC can result in copy of |
|
||
|
| | unexpectedly large data into secure memory |
|
||
|
+================+=============================================================+
|
||
|
| CVE ID | `CVE-2016-10319`_ |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Date | 18 Oct 2016 |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Versions | v1.2 and v1.3 (since commit `48bfb88`_) |
|
||
|
| Affected | |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Configurations | Platforms that use AArch64 BL1 plus untrusted normal world |
|
||
|
| Affected | firmware update code executing before BL31 |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Impact | Copy of unexpectedly large data into the free secure memory |
|
||
|
| | reported by BL1 platform code |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Fix Version | `Pull Request #783`_ |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
| Credit | IOActive |
|
||
|
+----------------+-------------------------------------------------------------+
|
||
|
|
||
|
Generic Trusted Firmware (TF) BL1 code contains an SMC interface that is briefly
|
||
|
available after cold reset to support the Firmware Update (FWU) feature (also
|
||
|
known as recovery mode). This allows most FWU functionality to be implemented in
|
||
|
the normal world, while retaining the essential image authentication
|
||
|
functionality in BL1. When cold boot reaches the EL3 Runtime Software (for
|
||
|
example, BL31 on AArch64 systems), the FWU SMC interface is replaced by the EL3
|
||
|
Runtime SMC interface. Platforms may choose how much of this FWU functionality
|
||
|
to use, if any.
|
||
|
|
||
|
The BL1 FWU SMC handling code, currently only supported on AArch64, contains
|
||
|
several vulnerabilities that may be exploited when *all* the following
|
||
|
conditions apply:
|
||
|
|
||
|
1. Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option
|
||
|
enabled.
|
||
|
|
||
|
2. Platform code arranges for untrusted normal world FWU code to be executed in
|
||
|
the cold boot path, before BL31 starts. Untrusted in this sense means code
|
||
|
that is not in ROM or has not been authenticated or has otherwise been
|
||
|
executed by an attacker.
|
||
|
|
||
|
3. Platform code copies the insecure pattern described below from the ARM
|
||
|
platform version of ``bl1_plat_mem_check()``.
|
||
|
|
||
|
The vulnerabilities consist of potential integer overflows in the input
|
||
|
validation checks while handling the ``FWU_SMC_IMAGE_COPY`` SMC. The SMC
|
||
|
implementation is designed to copy an image into secure memory for subsequent
|
||
|
authentication, but the vulnerabilities may allow an attacker to copy
|
||
|
unexpectedly large data into secure memory. Note that a separate vulnerability
|
||
|
is required to leverage these vulnerabilities; for example a way to get the
|
||
|
system to change its behaviour based on the unexpected secure memory contents.
|
||
|
|
||
|
Two of the vulnerabilities are in the function ``bl1_fwu_image_copy()`` in
|
||
|
``bl1/bl1_fwu.c``. These are listed below, referring to the v1.3 tagged version
|
||
|
of the code:
|
||
|
|
||
|
- Line 155:
|
||
|
|
||
|
.. code:: c
|
||
|
|
||
|
/*
|
||
|
* If last block is more than expected then
|
||
|
* clip the block to the required image size.
|
||
|
*/
|
||
|
if (image_desc->copied_size + block_size >
|
||
|
image_desc->image_info.image_size) {
|
||
|
block_size = image_desc->image_info.image_size -
|
||
|
image_desc->copied_size;
|
||
|
WARN("BL1-FWU: Copy argument block_size > remaining image size."
|
||
|
" Clipping block_size\n");
|
||
|
}
|
||
|
|
||
|
/* Make sure the image src/size is mapped. */
|
||
|
if (bl1_plat_mem_check(image_src, block_size, flags)) {
|
||
|
WARN("BL1-FWU: Copy arguments source/size not mapped\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
INFO("BL1-FWU: Continuing image copy in blocks\n");
|
||
|
|
||
|
/* Copy image for given block size. */
|
||
|
base_addr += image_desc->copied_size;
|
||
|
image_desc->copied_size += block_size;
|
||
|
memcpy((void *)base_addr, (const void *)image_src, block_size);
|
||
|
...
|
||
|
|
||
|
This code fragment is executed when the image copy operation is performed in
|
||
|
blocks over multiple SMCs. ``block_size`` is an SMC argument and therefore
|
||
|
potentially controllable by an attacker. A very large value may result in an
|
||
|
integer overflow in the 1st ``if`` statement, which would bypass the check,
|
||
|
allowing an unclipped ``block_size`` to be passed into
|
||
|
``bl1_plat_mem_check()``. If ``bl1_plat_mem_check()`` also passes, this may
|
||
|
result in an unexpectedly large copy of data into secure memory.
|
||
|
|
||
|
- Line 206:
|
||
|
|
||
|
.. code:: c
|
||
|
|
||
|
/* Make sure the image src/size is mapped. */
|
||
|
if (bl1_plat_mem_check(image_src, block_size, flags)) {
|
||
|
WARN("BL1-FWU: Copy arguments source/size not mapped\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
/* Find out how much free trusted ram remains after BL1 load */
|
||
|
mem_layout = bl1_plat_sec_mem_layout();
|
||
|
if ((image_desc->image_info.image_base < mem_layout->free_base) ||
|
||
|
(image_desc->image_info.image_base + image_size >
|
||
|
mem_layout->free_base + mem_layout->free_size)) {
|
||
|
WARN("BL1-FWU: Memory not available to copy\n");
|
||
|
return -ENOMEM;
|
||
|
}
|
||
|
|
||
|
/* Update the image size. */
|
||
|
image_desc->image_info.image_size = image_size;
|
||
|
|
||
|
/* Copy image for given size. */
|
||
|
memcpy((void *)base_addr, (const void *)image_src, block_size);
|
||
|
...
|
||
|
|
||
|
This code fragment is executed during the 1st invocation of the image copy
|
||
|
operation. Both ``block_size`` and ``image_size`` are SMC arguments. A very
|
||
|
large value of ``image_size`` may result in an integer overflow in the 2nd
|
||
|
``if`` statement, which would bypass the check, allowing execution to proceed.
|
||
|
If ``bl1_plat_mem_check()`` also passes, this may result in an unexpectedly
|
||
|
large copy of data into secure memory.
|
||
|
|
||
|
If the platform's implementation of ``bl1_plat_mem_check()`` is correct then it
|
||
|
may help prevent the above 2 vulnerabilities from being exploited. However, the
|
||
|
ARM platform version of this function contains a similar vulnerability:
|
||
|
|
||
|
- Line 88 of ``plat/arm/common/arm_bl1_fwu.c`` in function of
|
||
|
``bl1_plat_mem_check()``:
|
||
|
|
||
|
.. code:: c
|
||
|
|
||
|
while (mmap[index].mem_size) {
|
||
|
if ((mem_base >= mmap[index].mem_base) &&
|
||
|
((mem_base + mem_size)
|
||
|
<= (mmap[index].mem_base +
|
||
|
mmap[index].mem_size)))
|
||
|
return 0;
|
||
|
|
||
|
index++;
|
||
|
}
|
||
|
...
|
||
|
|
||
|
This function checks that the passed memory region is within one of the
|
||
|
regions mapped in by ARM platforms. Here, ``mem_size`` may be the
|
||
|
``block_size`` passed from ``bl1_fwu_image_copy()``. A very large value of
|
||
|
``mem_size`` may result in an integer overflow and the function to incorrectly
|
||
|
return success. Platforms that copy this insecure pattern will have the same
|
||
|
vulnerability.
|
||
|
|
||
|
.. _CVE-2016-10319: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10319
|
||
|
.. _48bfb88: https://github.com/ARM-software/arm-trusted-firmware/commit/48bfb88
|
||
|
.. _Pull Request #783: https://github.com/ARM-software/arm-trusted-firmware/pull/783
|