diff options
| -rw-r--r-- | fs/partitions/ldm.c | 137 | ||||
| -rw-r--r-- | fs/partitions/ldm.h | 2 |
2 files changed, 93 insertions, 46 deletions
diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c index 99873a2b4cbc..e7dd1d4e3473 100644 --- a/fs/partitions/ldm.c +++ b/fs/partitions/ldm.c | |||
| @@ -677,15 +677,24 @@ static bool ldm_create_data_partitions (struct parsed_partitions *pp, | |||
| 677 | * Return: -1 Error, the calculated offset exceeded the size of the buffer | 677 | * Return: -1 Error, the calculated offset exceeded the size of the buffer |
| 678 | * n OK, a range-checked offset into buffer | 678 | * n OK, a range-checked offset into buffer |
| 679 | */ | 679 | */ |
| 680 | static int ldm_relative (const u8 *buffer, int buflen, int base, int offset) | 680 | static int ldm_relative(const u8 *buffer, int buflen, int base, int offset) |
| 681 | { | 681 | { |
| 682 | 682 | ||
| 683 | base += offset; | 683 | base += offset; |
| 684 | if ((!buffer) || (offset < 0) || (base > buflen)) | 684 | if (!buffer || offset < 0 || base > buflen) { |
| 685 | if (!buffer) | ||
| 686 | ldm_error("!buffer"); | ||
| 687 | if (offset < 0) | ||
| 688 | ldm_error("offset (%d) < 0", offset); | ||
| 689 | if (base > buflen) | ||
| 690 | ldm_error("base (%d) > buflen (%d)", base, buflen); | ||
| 685 | return -1; | 691 | return -1; |
| 686 | if ((base + buffer[base]) >= buflen) | 692 | } |
| 693 | if (base + buffer[base] >= buflen) { | ||
| 694 | ldm_error("base (%d) + buffer[base] (%d) >= buflen (%d)", base, | ||
| 695 | buffer[base], buflen); | ||
| 687 | return -1; | 696 | return -1; |
| 688 | 697 | } | |
| 689 | return buffer[base] + offset + 1; | 698 | return buffer[base] + offset + 1; |
| 690 | } | 699 | } |
| 691 | 700 | ||
| @@ -1054,60 +1063,98 @@ static bool ldm_parse_prt3(const u8 *buffer, int buflen, struct vblk *vb) | |||
| 1054 | * Return: 'true' @vb contains a Volume VBLK | 1063 | * Return: 'true' @vb contains a Volume VBLK |
| 1055 | * 'false' @vb contents are not defined | 1064 | * 'false' @vb contents are not defined |
| 1056 | */ | 1065 | */ |
| 1057 | static bool ldm_parse_vol5 (const u8 *buffer, int buflen, struct vblk *vb) | 1066 | static bool ldm_parse_vol5(const u8 *buffer, int buflen, struct vblk *vb) |
| 1058 | { | 1067 | { |
| 1059 | int r_objid, r_name, r_vtype, r_child, r_size, r_id1, r_id2, r_size2; | 1068 | int r_objid, r_name, r_vtype, r_disable_drive_letter, r_child, r_size; |
| 1060 | int r_drive, len; | 1069 | int r_id1, r_id2, r_size2, r_drive, len; |
| 1061 | struct vblk_volu *volu; | 1070 | struct vblk_volu *volu; |
| 1062 | 1071 | ||
| 1063 | BUG_ON (!buffer || !vb); | 1072 | BUG_ON(!buffer || !vb); |
| 1064 | 1073 | r_objid = ldm_relative(buffer, buflen, 0x18, 0); | |
| 1065 | r_objid = ldm_relative (buffer, buflen, 0x18, 0); | 1074 | if (r_objid < 0) { |
| 1066 | r_name = ldm_relative (buffer, buflen, 0x18, r_objid); | 1075 | ldm_error("r_objid %d < 0", r_objid); |
| 1067 | r_vtype = ldm_relative (buffer, buflen, 0x18, r_name); | 1076 | return false; |
| 1068 | r_child = ldm_relative (buffer, buflen, 0x2E, r_vtype); | 1077 | } |
| 1069 | r_size = ldm_relative (buffer, buflen, 0x3E, r_child); | 1078 | r_name = ldm_relative(buffer, buflen, 0x18, r_objid); |
| 1070 | 1079 | if (r_name < 0) { | |
| 1071 | if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) | 1080 | ldm_error("r_name %d < 0", r_name); |
| 1072 | r_id1 = ldm_relative (buffer, buflen, 0x53, r_size); | 1081 | return false; |
| 1073 | else | 1082 | } |
| 1083 | r_vtype = ldm_relative(buffer, buflen, 0x18, r_name); | ||
| 1084 | if (r_vtype < 0) { | ||
| 1085 | ldm_error("r_vtype %d < 0", r_vtype); | ||
| 1086 | return false; | ||
| 1087 | } | ||
| 1088 | r_disable_drive_letter = ldm_relative(buffer, buflen, 0x18, r_vtype); | ||
| 1089 | if (r_disable_drive_letter < 0) { | ||
| 1090 | ldm_error("r_disable_drive_letter %d < 0", | ||
| 1091 | r_disable_drive_letter); | ||
| 1092 | return false; | ||
| 1093 | } | ||
| 1094 | r_child = ldm_relative(buffer, buflen, 0x2D, r_disable_drive_letter); | ||
| 1095 | if (r_child < 0) { | ||
| 1096 | ldm_error("r_child %d < 0", r_child); | ||
| 1097 | return false; | ||
| 1098 | } | ||
| 1099 | r_size = ldm_relative(buffer, buflen, 0x3D, r_child); | ||
| 1100 | if (r_size < 0) { | ||
| 1101 | ldm_error("r_size %d < 0", r_size); | ||
| 1102 | return false; | ||
| 1103 | } | ||
| 1104 | if (buffer[0x12] & VBLK_FLAG_VOLU_ID1) { | ||
| 1105 | r_id1 = ldm_relative(buffer, buflen, 0x52, r_size); | ||
| 1106 | if (r_id1 < 0) { | ||
| 1107 | ldm_error("r_id1 %d < 0", r_id1); | ||
| 1108 | return false; | ||
| 1109 | } | ||
| 1110 | } else | ||
| 1074 | r_id1 = r_size; | 1111 | r_id1 = r_size; |
| 1075 | 1112 | if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) { | |
| 1076 | if (buffer[0x12] & VBLK_FLAG_VOLU_ID2) | 1113 | r_id2 = ldm_relative(buffer, buflen, 0x52, r_id1); |
| 1077 | r_id2 = ldm_relative (buffer, buflen, 0x53, r_id1); | 1114 | if (r_id2 < 0) { |
| 1078 | else | 1115 | ldm_error("r_id2 %d < 0", r_id2); |
| 1116 | return false; | ||
| 1117 | } | ||
| 1118 | } else | ||
| 1079 | r_id2 = r_id1; | 1119 | r_id2 = r_id1; |
| 1080 | 1120 | if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) { | |
| 1081 | if (buffer[0x12] & VBLK_FLAG_VOLU_SIZE) | 1121 | r_size2 = ldm_relative(buffer, buflen, 0x52, r_id2); |
| 1082 | r_size2 = ldm_relative (buffer, buflen, 0x53, r_id2); | 1122 | if (r_size2 < 0) { |
| 1083 | else | 1123 | ldm_error("r_size2 %d < 0", r_size2); |
| 1124 | return false; | ||
| 1125 | } | ||
| 1126 | } else | ||
| 1084 | r_size2 = r_id2; | 1127 | r_size2 = r_id2; |
| 1085 | 1128 | if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) { | |
| 1086 | if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) | 1129 | r_drive = ldm_relative(buffer, buflen, 0x52, r_size2); |
| 1087 | r_drive = ldm_relative (buffer, buflen, 0x53, r_size2); | 1130 | if (r_drive < 0) { |
| 1088 | else | 1131 | ldm_error("r_drive %d < 0", r_drive); |
| 1132 | return false; | ||
| 1133 | } | ||
| 1134 | } else | ||
| 1089 | r_drive = r_size2; | 1135 | r_drive = r_size2; |
| 1090 | |||
| 1091 | len = r_drive; | 1136 | len = r_drive; |
| 1092 | if (len < 0) | 1137 | if (len < 0) { |
| 1138 | ldm_error("len %d < 0", len); | ||
| 1093 | return false; | 1139 | return false; |
| 1094 | 1140 | } | |
| 1095 | len += VBLK_SIZE_VOL5; | 1141 | len += VBLK_SIZE_VOL5; |
| 1096 | if (len != BE32 (buffer + 0x14)) | 1142 | if (len > BE32(buffer + 0x14)) { |
| 1143 | ldm_error("len %d > BE32(buffer + 0x14) %d", len, | ||
| 1144 | BE32(buffer + 0x14)); | ||
| 1097 | return false; | 1145 | return false; |
| 1098 | 1146 | } | |
| 1099 | volu = &vb->vblk.volu; | 1147 | volu = &vb->vblk.volu; |
| 1100 | 1148 | ldm_get_vstr(buffer + 0x18 + r_name, volu->volume_type, | |
| 1101 | ldm_get_vstr (buffer + 0x18 + r_name, volu->volume_type, | 1149 | sizeof(volu->volume_type)); |
| 1102 | sizeof (volu->volume_type)); | 1150 | memcpy(volu->volume_state, buffer + 0x18 + r_disable_drive_letter, |
| 1103 | memcpy (volu->volume_state, buffer + 0x19 + r_vtype, | 1151 | sizeof(volu->volume_state)); |
| 1104 | sizeof (volu->volume_state)); | 1152 | volu->size = ldm_get_vnum(buffer + 0x3D + r_child); |
| 1105 | volu->size = ldm_get_vnum (buffer + 0x3E + r_child); | 1153 | volu->partition_type = buffer[0x41 + r_size]; |
| 1106 | volu->partition_type = buffer[0x42 + r_size]; | 1154 | memcpy(volu->guid, buffer + 0x42 + r_size, sizeof(volu->guid)); |
| 1107 | memcpy (volu->guid, buffer + 0x43 + r_size, sizeof (volu->guid)); | ||
| 1108 | if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) { | 1155 | if (buffer[0x12] & VBLK_FLAG_VOLU_DRIVE) { |
| 1109 | ldm_get_vstr (buffer + 0x53 + r_size, volu->drive_hint, | 1156 | ldm_get_vstr(buffer + 0x52 + r_size, volu->drive_hint, |
| 1110 | sizeof (volu->drive_hint)); | 1157 | sizeof(volu->drive_hint)); |
| 1111 | } | 1158 | } |
| 1112 | return true; | 1159 | return true; |
| 1113 | } | 1160 | } |
diff --git a/fs/partitions/ldm.h b/fs/partitions/ldm.h index d2e6a3046939..80f63b5fdd9f 100644 --- a/fs/partitions/ldm.h +++ b/fs/partitions/ldm.h | |||
| @@ -68,7 +68,7 @@ struct parsed_partitions; | |||
| 68 | #define VBLK_SIZE_DSK3 12 | 68 | #define VBLK_SIZE_DSK3 12 |
| 69 | #define VBLK_SIZE_DSK4 45 | 69 | #define VBLK_SIZE_DSK4 45 |
| 70 | #define VBLK_SIZE_PRT3 28 | 70 | #define VBLK_SIZE_PRT3 28 |
| 71 | #define VBLK_SIZE_VOL5 59 | 71 | #define VBLK_SIZE_VOL5 58 |
| 72 | 72 | ||
| 73 | /* component types */ | 73 | /* component types */ |
| 74 | #define COMP_STRIPE 0x01 /* Stripe-set */ | 74 | #define COMP_STRIPE 0x01 /* Stripe-set */ |
