Check whether the shadow mbr does fit in the provided space on the target. Also a proper firmware should handle this case and return an error we may prevent problems or even damage with crappy firmwares.
Unified · Split
| @@ -98,6 +98,7 @@ enum opal_uid { · 97 unmodified lines | ||
| 98 | 98 | OPAL_ENTERPRISE_BANDMASTER0_UID, |
| 99 | 99 | OPAL_ENTERPRISE_ERASEMASTER_UID, |
| 100 | 100 | /* tables */ |
| 101 | + OPAL_TABLE_TABLE, | |
| 101 | 102 | OPAL_LOCKINGRANGE_GLOBAL, |
| 102 | 103 | OPAL_LOCKINGRANGE_ACE_RDLOCKED, |
| 103 | 104 | OPAL_LOCKINGRANGE_ACE_WRLOCKED, |
| @@ -152,6 +153,21 @@ enum opal_token { · 48 unmodified lines | ||
| 152 | 153 | OPAL_STARTCOLUMN = 0x03, |
| 153 | 154 | OPAL_ENDCOLUMN = 0x04, |
| 154 | 155 | OPAL_VALUES = 0x01, |
| 156 | + /* table table */ | |
| 157 | + OPAL_TABLE_UID = 0x00, | |
| 158 | + OPAL_TABLE_NAME = 0x01, | |
| 159 | + OPAL_TABLE_COMMON = 0x02, | |
| 160 | + OPAL_TABLE_TEMPLATE = 0x03, | |
| 161 | + OPAL_TABLE_KIND = 0x04, | |
| 162 | + OPAL_TABLE_COLUMN = 0x05, | |
| 163 | + OPAL_TABLE_COLUMNS = 0x06, | |
| 164 | + OPAL_TABLE_ROWS = 0x07, | |
| 165 | + OPAL_TABLE_ROWS_FREE = 0x08, | |
| 166 | + OPAL_TABLE_ROW_BYTES = 0x09, | |
| 167 | + OPAL_TABLE_LASTID = 0x0A, | |
| 168 | + OPAL_TABLE_MIN = 0x0B, | |
| 169 | + OPAL_TABLE_MAX = 0x0C, | |
| 170 | + | |
| 155 | 171 | /* authority table */ |
| 156 | 172 | OPAL_PIN = 0x03, |
| 157 | 173 | /* locking tokens */ |
| @@ -130,6 +130,8 @@ static const u8 opaluid[][OPAL_UID_LENGTH] = { · 129 unmodified lines | ||
| 130 | 130 | |
| 131 | 131 | /* tables */ |
| 132 | 132 | |
| 133 | + [OPAL_TABLE_TABLE] | |
| 134 | + { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01 }, | |
| 133 | 135 | [OPAL_LOCKINGRANGE_GLOBAL] = |
| 134 | 136 | { 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x00, 0x01 }, |
| 135 | 137 | [OPAL_LOCKINGRANGE_ACE_RDLOCKED] = |
| @@ -1131,6 +1133,29 @@ static int generic_get_column(struct opal_dev *dev, const u8 *table, · 995 unmodified lines | ||
| 1131 | 1133 | return finalize_and_send(dev, parse_and_check_status); |
| 1132 | 1134 | } |
| 1133 | 1135 | |
| 1136 | +/* | |
| 1137 | + * see TCG SAS 5.3.2.3 for a description of the available columns | |
| 1138 | + * | |
| 1139 | + * the result is provided in dev->resp->tok[4] | |
| 1140 | + */ | |
| 1141 | +static int generic_get_table_info(struct opal_dev *dev, enum opal_uid table, | |
| 1142 | + u64 column) | |
| 1143 | +{ | |
| 1144 | + u8 uid[OPAL_UID_LENGTH]; | |
| 1145 | + const unsigned int half = OPAL_UID_LENGTH/2; | |
| 1146 | + | |
| 1147 | + /* sed-opal UIDs can be split in two halves: | |
| 1148 | + * first: actual table index | |
| 1149 | + * second: relative index in the table | |
| 1150 | + * so we have to get the first half of the OPAL_TABLE_TABLE and use the | |
| 1151 | + * first part of the target table as relative index into that table | |
| 1152 | + */ | |
| 1153 | + memcpy(uid, opaluid[OPAL_TABLE_TABLE], half); | |
| 1154 | + memcpy(uid+half, opaluid[table], half); | |
| 1155 | + | |
| 1156 | + return generic_get_column(dev, uid, column); | |
| 1157 | +} | |
| 1158 | + | |
| 1134 | 1159 | static int gen_key(struct opal_dev *dev, void *data) |
| 1135 | 1160 | { |
| 1136 | 1161 | u8 uid[OPAL_UID_LENGTH]; |
| @@ -1557,6 +1582,20 @@ static int write_shadow_mbr(struct opal_dev *dev, void *data) · 420 unmodified lines | ||
| 1557 | 1582 | u64 len; |
| 1558 | 1583 | int err = 0; |
| 1559 | 1584 | |
| 1585 | + /* do we fit in the available shadow mbr space? */ | |
| 1586 | + err = generic_get_table_info(dev, OPAL_MBR, OPAL_TABLE_ROWS); | |
| 1587 | + if (err) { | |
| 1588 | + pr_debug("MBR: could not get shadow size\n"); | |
| 1589 | + return err; | |
| 1590 | + } | |
| 1591 | + | |
| 1592 | + len = response_get_u64(&dev->parsed, 4); | |
| 1593 | + if (shadow->size > len || shadow->offset > len - shadow->size) { | |
| 1594 | + pr_debug("MBR: does not fit in shadow (%llu vs. %llu)\n", | |
| 1595 | + shadow->offset + shadow->size, len); | |
| 1596 | + return -ENOSPC; | |
| 1597 | + } | |
| 1598 | + | |
| 1560 | 1599 | /* do the actual transmission(s) */ |
| 1561 | 1600 | src = (u8 __user *)(uintptr_t)shadow->data; |
| 1562 | 1601 | while (off < shadow->size) { |