efi: Fix out-of-bounds read in variable_matches()
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 <chris@chris-wilson.co.uk> Signed-off-by: Laszlo Ersek <lersek@redhat.com> Cc: Peter Jones <pjones@redhat.com> Cc: Matthew Garrett <mjg59@coreos.com> Cc: Jason Andryuk <jandryuk@gmail.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: <stable@vger.kernel.org> # v3.10+ Link: http://thread.gmane.org/gmane.comp.freedesktop.xorg.drivers.intel/86906 Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
This commit is contained in:
Родитель
c3b46c7326
Коммит
630ba0cc7a
|
@ -202,29 +202,44 @@ static const struct variable_validate variable_validate[] = {
|
||||||
{ NULL_GUID, "", NULL },
|
{ NULL_GUID, "", 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
|
static bool
|
||||||
variable_matches(const char *var_name, size_t len, const char *match_name,
|
variable_matches(const char *var_name, size_t len, const char *match_name,
|
||||||
int *match)
|
int *match)
|
||||||
{
|
{
|
||||||
for (*match = 0; ; (*match)++) {
|
for (*match = 0; ; (*match)++) {
|
||||||
char c = match_name[*match];
|
char c = match_name[*match];
|
||||||
char u = var_name[*match];
|
|
||||||
|
|
||||||
/* Wildcard in the matching name means we've matched */
|
switch (c) {
|
||||||
if (c == '*')
|
case '*':
|
||||||
|
/* Wildcard in @match_name means we've matched. */
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Case sensitive match */
|
case '\0':
|
||||||
if (!c && *match == len)
|
/* @match_name has ended. Has @var_name too? */
|
||||||
return true;
|
return (*match == len);
|
||||||
|
|
||||||
if (c != u)
|
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;
|
return false;
|
||||||
|
}
|
||||||
if (!c)
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
Загрузка…
Ссылка в новой задаче