security-advisory-tfv-1.rst 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. Advisory TFV-1 (CVE-2016-10319)
  2. ===============================
  3. +----------------+-------------------------------------------------------------+
  4. | Title | Malformed Firmware Update SMC can result in copy of |
  5. | | unexpectedly large data into secure memory |
  6. +================+=============================================================+
  7. | CVE ID | `CVE-2016-10319`_ |
  8. +----------------+-------------------------------------------------------------+
  9. | Date | 18 Oct 2016 |
  10. +----------------+-------------------------------------------------------------+
  11. | Versions | v1.2 and v1.3 (since commit `48bfb88`_) |
  12. | Affected | |
  13. +----------------+-------------------------------------------------------------+
  14. | Configurations | Platforms that use AArch64 BL1 plus untrusted normal world |
  15. | Affected | firmware update code executing before BL31 |
  16. +----------------+-------------------------------------------------------------+
  17. | Impact | Copy of unexpectedly large data into the free secure memory |
  18. | | reported by BL1 platform code |
  19. +----------------+-------------------------------------------------------------+
  20. | Fix Version | `Pull Request #783`_ |
  21. +----------------+-------------------------------------------------------------+
  22. | Credit | IOActive |
  23. +----------------+-------------------------------------------------------------+
  24. Generic Trusted Firmware (TF) BL1 code contains an SMC interface that is briefly
  25. available after cold reset to support the Firmware Update (FWU) feature (also
  26. known as recovery mode). This allows most FWU functionality to be implemented in
  27. the normal world, while retaining the essential image authentication
  28. functionality in BL1. When cold boot reaches the EL3 Runtime Software (for
  29. example, BL31 on AArch64 systems), the FWU SMC interface is replaced by the EL3
  30. Runtime SMC interface. Platforms may choose how much of this FWU functionality
  31. to use, if any.
  32. The BL1 FWU SMC handling code, currently only supported on AArch64, contains
  33. several vulnerabilities that may be exploited when *all* the following
  34. conditions apply:
  35. 1. Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option
  36. enabled.
  37. 2. Platform code arranges for untrusted normal world FWU code to be executed in
  38. the cold boot path, before BL31 starts. Untrusted in this sense means code
  39. that is not in ROM or has not been authenticated or has otherwise been
  40. executed by an attacker.
  41. 3. Platform code copies the insecure pattern described below from the ARM
  42. platform version of ``bl1_plat_mem_check()``.
  43. The vulnerabilities consist of potential integer overflows in the input
  44. validation checks while handling the ``FWU_SMC_IMAGE_COPY`` SMC. The SMC
  45. implementation is designed to copy an image into secure memory for subsequent
  46. authentication, but the vulnerabilities may allow an attacker to copy
  47. unexpectedly large data into secure memory. Note that a separate vulnerability
  48. is required to leverage these vulnerabilities; for example a way to get the
  49. system to change its behaviour based on the unexpected secure memory contents.
  50. Two of the vulnerabilities are in the function ``bl1_fwu_image_copy()`` in
  51. ``bl1/bl1_fwu.c``. These are listed below, referring to the v1.3 tagged version
  52. of the code:
  53. - Line 155:
  54. .. code:: c
  55. /*
  56. * If last block is more than expected then
  57. * clip the block to the required image size.
  58. */
  59. if (image_desc->copied_size + block_size >
  60. image_desc->image_info.image_size) {
  61. block_size = image_desc->image_info.image_size -
  62. image_desc->copied_size;
  63. WARN("BL1-FWU: Copy argument block_size > remaining image size."
  64. " Clipping block_size\n");
  65. }
  66. /* Make sure the image src/size is mapped. */
  67. if (bl1_plat_mem_check(image_src, block_size, flags)) {
  68. WARN("BL1-FWU: Copy arguments source/size not mapped\n");
  69. return -ENOMEM;
  70. }
  71. INFO("BL1-FWU: Continuing image copy in blocks\n");
  72. /* Copy image for given block size. */
  73. base_addr += image_desc->copied_size;
  74. image_desc->copied_size += block_size;
  75. memcpy((void *)base_addr, (const void *)image_src, block_size);
  76. ...
  77. This code fragment is executed when the image copy operation is performed in
  78. blocks over multiple SMCs. ``block_size`` is an SMC argument and therefore
  79. potentially controllable by an attacker. A very large value may result in an
  80. integer overflow in the 1st ``if`` statement, which would bypass the check,
  81. allowing an unclipped ``block_size`` to be passed into
  82. ``bl1_plat_mem_check()``. If ``bl1_plat_mem_check()`` also passes, this may
  83. result in an unexpectedly large copy of data into secure memory.
  84. - Line 206:
  85. .. code:: c
  86. /* Make sure the image src/size is mapped. */
  87. if (bl1_plat_mem_check(image_src, block_size, flags)) {
  88. WARN("BL1-FWU: Copy arguments source/size not mapped\n");
  89. return -ENOMEM;
  90. }
  91. /* Find out how much free trusted ram remains after BL1 load */
  92. mem_layout = bl1_plat_sec_mem_layout();
  93. if ((image_desc->image_info.image_base < mem_layout->free_base) ||
  94. (image_desc->image_info.image_base + image_size >
  95. mem_layout->free_base + mem_layout->free_size)) {
  96. WARN("BL1-FWU: Memory not available to copy\n");
  97. return -ENOMEM;
  98. }
  99. /* Update the image size. */
  100. image_desc->image_info.image_size = image_size;
  101. /* Copy image for given size. */
  102. memcpy((void *)base_addr, (const void *)image_src, block_size);
  103. ...
  104. This code fragment is executed during the 1st invocation of the image copy
  105. operation. Both ``block_size`` and ``image_size`` are SMC arguments. A very
  106. large value of ``image_size`` may result in an integer overflow in the 2nd
  107. ``if`` statement, which would bypass the check, allowing execution to proceed.
  108. If ``bl1_plat_mem_check()`` also passes, this may result in an unexpectedly
  109. large copy of data into secure memory.
  110. If the platform's implementation of ``bl1_plat_mem_check()`` is correct then it
  111. may help prevent the above 2 vulnerabilities from being exploited. However, the
  112. ARM platform version of this function contains a similar vulnerability:
  113. - Line 88 of ``plat/arm/common/arm_bl1_fwu.c`` in function of
  114. ``bl1_plat_mem_check()``:
  115. .. code:: c
  116. while (mmap[index].mem_size) {
  117. if ((mem_base >= mmap[index].mem_base) &&
  118. ((mem_base + mem_size)
  119. <= (mmap[index].mem_base +
  120. mmap[index].mem_size)))
  121. return 0;
  122. index++;
  123. }
  124. ...
  125. This function checks that the passed memory region is within one of the
  126. regions mapped in by ARM platforms. Here, ``mem_size`` may be the
  127. ``block_size`` passed from ``bl1_fwu_image_copy()``. A very large value of
  128. ``mem_size`` may result in an integer overflow and the function to incorrectly
  129. return success. Platforms that copy this insecure pattern will have the same
  130. vulnerability.
  131. .. _CVE-2016-10319: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10319
  132. .. _48bfb88: https://github.com/ARM-software/arm-trusted-firmware/commit/48bfb88
  133. .. _Pull Request #783: https://github.com/ARM-software/arm-trusted-firmware/pull/783