Blame SOURCES/0316-script-Avoid-a-use-after-free-when-redefining-a-func.patch

b1bcb2
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
c4e390
From: Chris Coulson <chris.coulson@canonical.com>
c4e390
Date: Fri, 10 Jul 2020 14:41:45 +0100
b1bcb2
Subject: [PATCH] script: Avoid a use-after-free when redefining a function
b1bcb2
 during execution
c4e390
c4e390
Defining a new function with the same name as a previously defined
c4e390
function causes the grub_script and associated resources for the
c4e390
previous function to be freed. If the previous function is currently
c4e390
executing when a function with the same name is defined, this results
c4e390
in use-after-frees when processing subsequent commands in the original
c4e390
function.
c4e390
c4e390
Instead, reject a new function definition if it has the same name as
c4e390
a previously defined function, and that function is currently being
c4e390
executed. Although a behavioural change, this should be backwards
c4e390
compatible with existing configurations because they can't be
c4e390
dependent on the current behaviour without being broken.
c4e390
c4e390
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
c4e390
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
c4e390
Upstream-commit-id: f6253a1f540
c4e390
---
c4e390
 grub-core/script/execute.c  |  2 ++
c4e390
 grub-core/script/function.c | 16 +++++++++++++---
c4e390
 include/grub/script_sh.h    |  2 ++
c4e390
 grub-core/script/parser.y   |  3 ++-
c4e390
 4 files changed, 19 insertions(+), 4 deletions(-)
c4e390
c4e390
diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
c4e390
index 043b4c4bb66..52ccbd9965b 100644
c4e390
--- a/grub-core/script/execute.c
c4e390
+++ b/grub-core/script/execute.c
c4e390
@@ -855,7 +855,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
c4e390
   old_scope = scope;
c4e390
   scope = &new_scope;
c4e390
 
c4e390
+  func->executing++;
c4e390
   ret = grub_script_execute (func->func);
c4e390
+  func->executing--;
c4e390
 
c4e390
   function_return = 0;
c4e390
   active_loops = loops;
c4e390
diff --git a/grub-core/script/function.c b/grub-core/script/function.c
c4e390
index d36655e510f..3aad04bf9dd 100644
c4e390
--- a/grub-core/script/function.c
c4e390
+++ b/grub-core/script/function.c
c4e390
@@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
c4e390
   func = (grub_script_function_t) grub_malloc (sizeof (*func));
c4e390
   if (! func)
c4e390
     return 0;
c4e390
+  func->executing = 0;
c4e390
 
c4e390
   func->name = grub_strdup (functionname_arg->str);
c4e390
   if (! func->name)
c4e390
@@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
c4e390
       grub_script_function_t q;
c4e390
 
c4e390
       q = *p;
c4e390
-      grub_script_free (q->func);
c4e390
-      q->func = cmd;
c4e390
       grub_free (func);
c4e390
-      func = q;
c4e390
+      if (q->executing > 0)
c4e390
+        {
c4e390
+          grub_error (GRUB_ERR_BAD_ARGUMENT,
c4e390
+		      N_("attempt to redefine a function being executed"));
c4e390
+          func = NULL;
c4e390
+        }
c4e390
+      else
c4e390
+        {
c4e390
+          grub_script_free (q->func);
c4e390
+          q->func = cmd;
c4e390
+          func = q;
c4e390
+        }
c4e390
     }
c4e390
   else
c4e390
     {
c4e390
diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
c4e390
index b382bcf09bc..6c48e075122 100644
c4e390
--- a/include/grub/script_sh.h
c4e390
+++ b/include/grub/script_sh.h
c4e390
@@ -361,6 +361,8 @@ struct grub_script_function
c4e390
 
c4e390
   /* The next element.  */
c4e390
   struct grub_script_function *next;
c4e390
+
c4e390
+  unsigned executing;
c4e390
 };
c4e390
 typedef struct grub_script_function *grub_script_function_t;
c4e390
 
c4e390
diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
c4e390
index 1d60e9de2f3..26b72e52556 100644
c4e390
--- a/grub-core/script/parser.y
c4e390
+++ b/grub-core/script/parser.y
c4e390
@@ -290,7 +290,8 @@ function: "function" "name"
c4e390
 	      grub_script_mem_free (state->func_mem);
c4e390
 	    else {
c4e390
 	      script->children = state->scripts;
c4e390
-	      grub_script_function_create ($2, script);
c4e390
+	      if (!grub_script_function_create ($2, script))
c4e390
+		grub_script_free (script);
c4e390
 	    }
c4e390
 
c4e390
 	    state->scripts = $<scripts>3;