diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-28 22:54:50 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-04-28 22:54:50 -0400 |
commit | 8f3603a210970d665e7cecf6623331ce6b24f713 (patch) | |
tree | 3dc33db5d8ea1c8a741a91d0e05c38629753352e | |
parent | ba14e961b4fc0b0efcb1b2af7aab605bfce55fb8 (diff) | |
parent | ede85e90be26e5de2a72f76feec01cfc5281d4bd (diff) |
Merge branch 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull EFI fix from Ingo Molnar:
"This fixes a bug in the efivars code"
* 'efi-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
efi: Fix out-of-bounds read in variable_matches()
-rw-r--r-- | drivers/firmware/efi/vars.c | 37 |
1 files changed, 26 insertions, 11 deletions
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 0ac594c0a234..34b741940494 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c | |||
@@ -202,29 +202,44 @@ static const struct variable_validate variable_validate[] = { | |||
202 | { NULL_GUID, "", NULL }, | 202 | { NULL_GUID, "", NULL }, |
203 | }; | 203 | }; |
204 | 204 | ||
205 | /* | ||
206 | * Check if @var_name matches the pattern given in @match_name. | ||
207 | * | ||
208 | * @var_name: an array of @len non-NUL characters. | ||
209 | * @match_name: a NUL-terminated pattern string, optionally ending in "*". A | ||
210 | * final "*" character matches any trailing characters @var_name, | ||
211 | * including the case when there are none left in @var_name. | ||
212 | * @match: on output, the number of non-wildcard characters in @match_name | ||
213 | * that @var_name matches, regardless of the return value. | ||
214 | * @return: whether @var_name fully matches @match_name. | ||
215 | */ | ||
205 | static bool | 216 | static bool |
206 | variable_matches(const char *var_name, size_t len, const char *match_name, | 217 | variable_matches(const char *var_name, size_t len, const char *match_name, |
207 | int *match) | 218 | int *match) |
208 | { | 219 | { |
209 | for (*match = 0; ; (*match)++) { | 220 | for (*match = 0; ; (*match)++) { |
210 | char c = match_name[*match]; | 221 | char c = match_name[*match]; |
211 | char u = var_name[*match]; | ||
212 | 222 | ||
213 | /* Wildcard in the matching name means we've matched */ | 223 | switch (c) { |
214 | if (c == '*') | 224 | case '*': |
225 | /* Wildcard in @match_name means we've matched. */ | ||
215 | return true; | 226 | return true; |
216 | 227 | ||
217 | /* Case sensitive match */ | 228 | case '\0': |
218 | if (!c && *match == len) | 229 | /* @match_name has ended. Has @var_name too? */ |
219 | return true; | 230 | return (*match == len); |
220 | 231 | ||
221 | if (c != u) | 232 | default: |
233 | /* | ||
234 | * We've reached a non-wildcard char in @match_name. | ||
235 | * Continue only if there's an identical character in | ||
236 | * @var_name. | ||
237 | */ | ||
238 | if (*match < len && c == var_name[*match]) | ||
239 | continue; | ||
222 | return false; | 240 | return false; |
223 | 241 | } | |
224 | if (!c) | ||
225 | return true; | ||
226 | } | 242 | } |
227 | return true; | ||
228 | } | 243 | } |
229 | 244 | ||
230 | bool | 245 | bool |