|
|
c4e390 |
From 0950880ab9a53d7632ca849ad2375352a3c2c972 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
|
|
|
c4e390 |
Subject: [PATCH 316/336] script: Avoid a use-after-free when redefining a
|
|
|
c4e390 |
function 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;
|
|
|
c4e390 |
--
|
|
|
c4e390 |
2.26.2
|
|
|
c4e390 |
|