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.

130 lines
4.5 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. --- a/lib/ipmi_fru.c
  21. +++ b/lib/ipmi_fru.c
  22. @@ -3062,7 +3062,7 @@ ipmi_fru_print(struct ipmi_intf * intf,
  23. return 0;
  24. memset(desc, 0, sizeof(desc));
  25. - memcpy(desc, fru->id_string, fru->id_code & 0x01f);
  26. + memcpy(desc, fru->id_string, __min(fru->id_code & 0x01f, sizeof(desc)));
  27. desc[fru->id_code & 0x01f] = 0;
  28. printf("FRU Device Description : %s (ID %d)\n", desc, fru->device_id);
  29. --- a/lib/ipmi_sdr.c
  30. +++ b/lib/ipmi_sdr.c
  31. @@ -2084,7 +2084,7 @@ ipmi_sdr_print_sensor_eventonly(struct i
  32. return -1;
  33. memset(desc, 0, sizeof (desc));
  34. - snprintf(desc, (sensor->id_code & 0x1f) + 1, "%s", sensor->id_string);
  35. + snprintf(desc, sizeof(desc), "%.*s", (sensor->id_code & 0x1f) + 1, sensor->id_string);
  36. if (verbose) {
  37. printf("Sensor ID : %s (0x%x)\n",
  38. @@ -2135,7 +2135,7 @@ ipmi_sdr_print_sensor_mc_locator(struct
  39. return -1;
  40. memset(desc, 0, sizeof (desc));
  41. - snprintf(desc, (mc->id_code & 0x1f) + 1, "%s", mc->id_string);
  42. + snprintf(desc, sizeof(desc), "%.*s", (mc->id_code & 0x1f) + 1, mc->id_string);
  43. if (verbose == 0) {
  44. if (csv_output)
  45. @@ -2228,7 +2228,7 @@ ipmi_sdr_print_sensor_generic_locator(st
  46. char desc[17];
  47. memset(desc, 0, sizeof (desc));
  48. - snprintf(desc, (dev->id_code & 0x1f) + 1, "%s", dev->id_string);
  49. + snprintf(desc, sizeof(desc), "%.*s", (dev->id_code & 0x1f) + 1, dev->id_string);
  50. if (!verbose) {
  51. if (csv_output)
  52. @@ -2285,7 +2285,7 @@ ipmi_sdr_print_sensor_fru_locator(struct
  53. char desc[17];
  54. memset(desc, 0, sizeof (desc));
  55. - snprintf(desc, (fru->id_code & 0x1f) + 1, "%s", fru->id_string);
  56. + snprintf(desc, sizeof(desc), "%.*s", (fru->id_code & 0x1f) + 1, fru->id_string);
  57. if (!verbose) {
  58. if (csv_output)
  59. @@ -2489,35 +2489,43 @@ ipmi_sdr_print_name_from_rawentry(struct
  60. int rc =0;
  61. char desc[17];
  62. + const char *id_string;
  63. + uint8_t id_code;
  64. memset(desc, ' ', sizeof (desc));
  65. switch ( type) {
  66. case SDR_RECORD_TYPE_FULL_SENSOR:
  67. record.full = (struct sdr_record_full_sensor *) raw;
  68. - snprintf(desc, (record.full->id_code & 0x1f) +1, "%s",
  69. - (const char *)record.full->id_string);
  70. + id_code = record.full->id_code;
  71. + id_string = record.full->id_string;
  72. break;
  73. +
  74. case SDR_RECORD_TYPE_COMPACT_SENSOR:
  75. record.compact = (struct sdr_record_compact_sensor *) raw ;
  76. - snprintf(desc, (record.compact->id_code & 0x1f) +1, "%s",
  77. - (const char *)record.compact->id_string);
  78. + id_code = record.compact->id_code;
  79. + id_string = record.compact->id_string;
  80. break;
  81. +
  82. case SDR_RECORD_TYPE_EVENTONLY_SENSOR:
  83. record.eventonly = (struct sdr_record_eventonly_sensor *) raw ;
  84. - snprintf(desc, (record.eventonly->id_code & 0x1f) +1, "%s",
  85. - (const char *)record.eventonly->id_string);
  86. - break;
  87. + id_code = record.eventonly->id_code;
  88. + id_string = record.eventonly->id_string;
  89. + break;
  90. +
  91. case SDR_RECORD_TYPE_MC_DEVICE_LOCATOR:
  92. record.mcloc = (struct sdr_record_mc_locator *) raw ;
  93. - snprintf(desc, (record.mcloc->id_code & 0x1f) +1, "%s",
  94. - (const char *)record.mcloc->id_string);
  95. + id_code = record.mcloc->id_code;
  96. + id_string = record.mcloc->id_string;
  97. break;
  98. +
  99. default:
  100. rc = -1;
  101. - break;
  102. - }
  103. + }
  104. + if (!rc) {
  105. + snprintf(desc, sizeof(desc), "%.*s", (id_code & 0x1f) + 1, id_string);
  106. + }
  107. - lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
  108. + lprintf(LOG_INFO, "ID: 0x%04x , NAME: %-16s", id, desc);
  109. return rc;
  110. }