2
1

0008-fru-Fix-buffer-overflow-vulnerabilities.patch 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. From d615cb6c39d401a569941be2a615176191afa7ac Mon Sep 17 00:00:00 2001
  2. From: Chrostoper Ertl <chertl@microsoft.com>
  3. Date: Thu, 28 Nov 2019 16:33:59 +0000
  4. Subject: [PATCH] fru: Fix buffer overflow vulnerabilities
  5. Partial fix for CVE-2020-5208, see
  6. https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp
  7. The `read_fru_area_section` function only performs size validation of
  8. requested read size, and falsely assumes that the IPMI message will not
  9. respond with more than the requested amount of data; it uses the
  10. unvalidated response size to copy into `frubuf`. If the response is
  11. larger than the request, this can result in overflowing the buffer.
  12. The same issue affects the `read_fru_area` function.
  13. [Retrieve from
  14. https://github.com/ipmitool/ipmitool/commit/e824c23316ae50beb7f7488f2055ac65e8b341f2]
  15. Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
  16. ---
  17. lib/ipmi_fru.c | 33 +++++++++++++++++++++++++++++++--
  18. 1 file changed, 31 insertions(+), 2 deletions(-)
  19. diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
  20. index cf00eff..af99aa9 100644
  21. --- a/lib/ipmi_fru.c
  22. +++ b/lib/ipmi_fru.c
  23. @@ -615,7 +615,10 @@ int
  24. read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  25. uint32_t offset, uint32_t length, uint8_t *frubuf)
  26. {
  27. - uint32_t off = offset, tmp, finish;
  28. + uint32_t off = offset;
  29. + uint32_t tmp;
  30. + uint32_t finish;
  31. + uint32_t size_left_in_buffer;
  32. struct ipmi_rs * rsp;
  33. struct ipmi_rq req;
  34. uint8_t msg_data[4];
  35. @@ -628,10 +631,12 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  36. finish = offset + length;
  37. if (finish > fru->size) {
  38. + memset(frubuf + fru->size, 0, length - fru->size);
  39. finish = fru->size;
  40. lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
  41. "Adjusting to %d",
  42. offset + length, finish - offset);
  43. + length = finish - offset;
  44. }
  45. memset(&req, 0, sizeof(req));
  46. @@ -667,6 +672,7 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  47. }
  48. }
  49. + size_left_in_buffer = length;
  50. do {
  51. tmp = fru->access ? off >> 1 : off;
  52. msg_data[0] = id;
  53. @@ -707,9 +713,18 @@ read_fru_area(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  54. }
  55. tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
  56. + if(rsp->data_len < 1
  57. + || tmp > rsp->data_len - 1
  58. + || tmp > size_left_in_buffer)
  59. + {
  60. + printf(" Not enough buffer size");
  61. + return -1;
  62. + }
  63. +
  64. memcpy(frubuf, rsp->data + 1, tmp);
  65. off += tmp;
  66. frubuf += tmp;
  67. + size_left_in_buffer -= tmp;
  68. /* sometimes the size returned in the Info command
  69. * is too large. return 0 so higher level function
  70. * still attempts to parse what was returned */
  71. @@ -742,7 +757,9 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  72. uint32_t offset, uint32_t length, uint8_t *frubuf)
  73. {
  74. static uint32_t fru_data_rqst_size = 20;
  75. - uint32_t off = offset, tmp, finish;
  76. + uint32_t off = offset;
  77. + uint32_t tmp, finish;
  78. + uint32_t size_left_in_buffer;
  79. struct ipmi_rs * rsp;
  80. struct ipmi_rq req;
  81. uint8_t msg_data[4];
  82. @@ -755,10 +772,12 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  83. finish = offset + length;
  84. if (finish > fru->size) {
  85. + memset(frubuf + fru->size, 0, length - fru->size);
  86. finish = fru->size;
  87. lprintf(LOG_NOTICE, "Read FRU Area length %d too large, "
  88. "Adjusting to %d",
  89. offset + length, finish - offset);
  90. + length = finish - offset;
  91. }
  92. memset(&req, 0, sizeof(req));
  93. @@ -773,6 +792,8 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  94. if (fru->access && fru_data_rqst_size > 16)
  95. #endif
  96. fru_data_rqst_size = 16;
  97. +
  98. + size_left_in_buffer = length;
  99. do {
  100. tmp = fru->access ? off >> 1 : off;
  101. msg_data[0] = id;
  102. @@ -804,8 +825,16 @@ read_fru_area_section(struct ipmi_intf * intf, struct fru_info *fru, uint8_t id,
  103. }
  104. tmp = fru->access ? rsp->data[0] << 1 : rsp->data[0];
  105. + if(rsp->data_len < 1
  106. + || tmp > rsp->data_len - 1
  107. + || tmp > size_left_in_buffer)
  108. + {
  109. + printf(" Not enough buffer size");
  110. + return -1;
  111. + }
  112. memcpy((frubuf + off)-offset, rsp->data + 1, tmp);
  113. off += tmp;
  114. + size_left_in_buffer -= tmp;
  115. /* sometimes the size returned in the Info command
  116. * is too large. return 0 so higher level function
  117. --
  118. 2.20.1