]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
efi: Fix out-of-bounds read in variable_matches()
authorLaszlo Ersek <lersek@redhat.com>
Fri, 2 Dec 2016 22:18:05 +0000 (14:18 -0800)
committerDhaval Giani <dhaval.giani@oracle.com>
Fri, 20 Jan 2017 22:21:52 +0000 (17:21 -0500)
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 <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>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
(cherry picked from commit 83619523130164cb525e35b6001755cd185055fb)

Conflicts:

drivers/firmware/efi/vars.c

Signed-off-by: Dhaval Giani <dhaval.giani@oracle.com>
drivers/firmware/efi/vars.c

index 70a0fb10517f94ea5b28bada280d9935f0693cc7..338963cf7fba972e721e3136ed6c76e85d778d38 100644 (file)
@@ -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)
 {