From 767ea6dc810e900a61030a673c906131500622ec Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Fri, 2 Dec 2016 14:18:05 -0800 Subject: [PATCH] efi: Fix out-of-bounds read in variable_matches() Orabug: 25227159 [ Upstream commit 630ba0cc7a6dbafbdee43795617c872b35cde1b4 ] The variable_matches() function can currently read "var_name[len]", for example when: - var_name[0] == 'a', - len == 1 - match_name points to the NUL-terminated string "ab". This function is supposed to accept "var_name" inputs that are not NUL-terminated (hence the "len" parameter"). Document the function, and access "var_name[*match]" only if "*match" is smaller than "len". Reported-by: Chris Wilson Signed-off-by: Laszlo Ersek Cc: Peter Jones Cc: Matthew Garrett Cc: Jason Andryuk Cc: Jani Nikula Cc: # v3.10+ Link: http://thread.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/86906 Signed-off-by: Matt Fleming Signed-off-by: Sasha Levin (cherry picked from commit 83619523130164cb525e35b6001755cd185055fb) Conflicts: drivers/firmware/efi/vars.c Signed-off-by: Dhaval Giani --- drivers/firmware/efi/vars.c | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c index 70a0fb10517f..338963cf7fba 100644 --- a/drivers/firmware/efi/vars.c +++ b/drivers/firmware/efi/vars.c @@ -188,6 +188,46 @@ static const struct variable_validate variable_validate[] = { { "", NULL }, }; +/* + * Check if @var_name matches the pattern given in @match_name. + * + * @var_name: an array of @len non-NUL characters. + * @match_name: a NUL-terminated pattern string, optionally ending in "*". A + * final "*" character matches any trailing characters @var_name, + * including the case when there are none left in @var_name. + * @match: on output, the number of non-wildcard characters in @match_name + * that @var_name matches, regardless of the return value. + * @return: whether @var_name fully matches @match_name. + */ +static bool +variable_matches(const char *var_name, size_t len, const char *match_name, + int *match) +{ + for (*match = 0; ; (*match)++) { + char c = match_name[*match]; + + switch (c) { + case '*': + /* Wildcard in @match_name means we've matched. */ + return true; + + case '\0': + /* @match_name has ended. Has @var_name too? */ + return (*match == len); + + default: + /* + * We've reached a non-wildcard char in @match_name. + * Continue only if there's an identical character in + * @var_name. + */ + if (*match < len && c == var_name[*match]) + continue; + return false; + } + } +} + bool efivar_validate(efi_char16_t *var_name, u8 *data, unsigned long len) { -- 2.50.1