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.

137 lines
4.8 KiB

  1. From 98b47424cf548f58c4d295fa8235210406ea85ca Mon Sep 17 00:00:00 2001
  2. From: Chrostoper Ertl <chertl@microsoft.com>
  3. Date: Thu, 28 Nov 2019 17:13:45 +0000
  4. Subject: [PATCH 11/11] fru, sdr: Fix id_string buffer overflows
  5. Final part of the fixes for CVE-2020-5208, see
  6. https://github.com/ipmitool/ipmitool/security/advisories/GHSA-g659-9qxw-p7cp
  7. 9 variants of stack buffer overflow when parsing `id_string` field of
  8. SDR records returned from `CMD_GET_SDR` command.
  9. SDR record structs have an `id_code` field, and an `id_string` `char`
  10. array.
  11. The length of `id_string` is calculated as `(id_code & 0x1f) + 1`,
  12. which can be larger than expected 16 characters (if `id_code = 0xff`,
  13. then length will be `(0xff & 0x1f) + 1 = 32`).
  14. In numerous places, this can cause stack buffer overflow when copying
  15. into fixed buffer of size `17` bytes from this calculated length.
  16. ---
  17. lib/ipmi_fru.c | 2 +-
  18. lib/ipmi_sdr.c | 40 ++++++++++++++++++++++++----------------
  19. 2 files changed, 25 insertions(+), 17 deletions(-)
  20. diff --git a/lib/ipmi_fru.c b/lib/ipmi_fru.c
  21. index af99aa99444c..98bc9840955a 100644
  22. --- a/lib/ipmi_fru.c
  23. +++ b/lib/ipmi_fru.c
  24. @@ -3062,7 +3062,7 @@ ipmi_fru_print(struct ipmi_intf * intf, struct sdr_record_fru_locator * fru)
  25. return 0;
  26. memset(desc, 0, sizeof(desc));
  27. - memcpy(desc, fru->id_string, fru->id_code & 0x01f);
  28. + memcpy(desc, fru->id_string, __min(fru->id_code & 0x01f, sizeof(desc)));
  29. desc[fru->id_code & 0x01f] = 0;
  30. printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
  31. diff --git a/lib/ipmi_sdr.c b/lib/ipmi_sdr.c
  32. index 2a9cbe3087af..62aac08a9002 100644
  33. --- a/lib/ipmi_sdr.c
  34. +++ b/lib/ipmi_sdr.c
  35. @@ -2084,7 +2084,7 @@ ipmi_sdr_print_sensor_eventonly(struct ipmi_intf *intf,
  36. return -1;
  37. memset(desc, 0, sizeof (desc));
  38. - snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
  39. + snprintf(desc, sizeof(desc), "%.*s", (sensor->id_code & 0x1f) + 1, sensor->id_string);
  40. if (verbose) {
  41. printf("Sensor ID : %s (0x%x)\n",
  42. @@ -2135,7 +2135,7 @@ ipmi_sdr_print_sensor_mc_locator(struct ipmi_intf *intf,
  43. return -1;
  44. memset(desc, 0, sizeof (desc));
  45. - snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
  46. + snprintf(desc, sizeof(desc), "%.*s", (mc->id_code & 0x1f) + 1, mc->id_string);
  47. if (verbose == 0) {
  48. if (csv_output)
  49. @@ -2228,7 +2228,7 @@ ipmi_sdr_print_sensor_generic_locator(struct ipmi_intf *intf,
  50. char desc[17];
  51. memset(desc, 0, sizeof (desc));
  52. - snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
  53. + snprintf(desc, sizeof(desc), "%.*s", (dev->id_code & 0x1f) + 1, dev->id_string);
  54. if (!verbose) {
  55. if (csv_output)
  56. @@ -2285,7 +2285,7 @@ ipmi_sdr_print_sensor_fru_locator(struct ipmi_intf *intf,
  57. char desc[17];
  58. memset(desc, 0, sizeof (desc));
  59. - snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
  60. + snprintf(desc, sizeof(desc), "%.*s", (fru->id_code & 0x1f) + 1, fru->id_string);
  61. if (!verbose) {
  62. if (csv_output)
  63. @@ -2489,35 +2489,43 @@ ipmi_sdr_print_name_from_rawentry(struct ipmi_intf *intf, uint16_t id,
  64. int rc =0;
  65. char desc[17];
  66. + const char *id_string;
  67. + uint8_t id_code;
  68. memset(desc, ' ', sizeof (desc));
  69. switch ( type) {
  70. case SDR_RECORD_TYPE_FULL_SENSOR:
  71. record.full = (struct sdr_record_full_sensor *) raw;
  72. - snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
  73. - (const char *)record.full->id_string);
  74. + id_code = record.full->id_code;
  75. + id_string = record.full->id_string;
  76. break;
  77. +
  78. case SDR_RECORD_TYPE_COMPACT_SENSOR:
  79. record.compact = (struct sdr_record_compact_sensor *) raw ;
  80. - snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s",
  81. - (const char *)record.compact->id_string);
  82. + id_code = record.compact->id_code;
  83. + id_string = record.compact->id_string;
  84. break;
  85. +
  86. case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
  87. record.eventonly = (struct sdr_record_eventonly_sensor *) raw ;
  88. - snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s",
  89. - (const char *)record.eventonly->id_string);
  90. - break;
  91. + id_code = record.eventonly->id_code;
  92. + id_string = record.eventonly->id_string;
  93. + break;
  94. +
  95. case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
  96. record.mcloc = (struct sdr_record_mc_locator *) raw ;
  97. - snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s",
  98. - (const char *)record.mcloc->id_string);
  99. + id_code = record.mcloc->id_code;
  100. + id_string = record.mcloc->id_string;
  101. break;
  102. +
  103. default:
  104. rc = -1;
  105. - break;
  106. - }
  107. + }
  108. + if (!rc) {
  109. + snprintf(desc, sizeof(desc), "%.*s", (id_code & 0x1f) + 1, id_string);
  110. + }
  111. - lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
  112. + lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
  113. return rc;
  114. }
  115. --
  116. 2.27.0