0019-script-Avoid-a-use-after-free-when-redefining-a-func.patch 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. From 26349fcf80982b4d0120b73b2836e88bcf16853c Mon Sep 17 00:00:00 2001
  2. From: Chris Coulson <chris.coulson@canonical.com>
  3. Date: Fri, 10 Jul 2020 14:41:45 +0100
  4. Subject: [PATCH] script: Avoid a use-after-free when redefining a
  5. function during execution
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. Defining a new function with the same name as a previously defined
  10. function causes the grub_script and associated resources for the
  11. previous function to be freed. If the previous function is currently
  12. executing when a function with the same name is defined, this results
  13. in use-after-frees when processing subsequent commands in the original
  14. function.
  15. Instead, reject a new function definition if it has the same name as
  16. a previously defined function, and that function is currently being
  17. executed. Although a behavioural change, this should be backwards
  18. compatible with existing configurations because they can't be
  19. dependent on the current behaviour without being broken.
  20. Fixes: CVE-2020-15706
  21. Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
  22. Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
  23. Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
  24. ---
  25. grub-core/script/execute.c | 2 ++
  26. grub-core/script/function.c | 16 +++++++++++++---
  27. grub-core/script/parser.y | 3 ++-
  28. include/grub/script_sh.h | 2 ++
  29. 4 files changed, 19 insertions(+), 4 deletions(-)
  30. diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c
  31. index c8d6806fe..7e028e135 100644
  32. --- a/grub-core/script/execute.c
  33. +++ b/grub-core/script/execute.c
  34. @@ -838,7 +838,9 @@ grub_script_function_call (grub_script_function_t func, int argc, char **args)
  35. old_scope = scope;
  36. scope = &new_scope;
  37. + func->executing++;
  38. ret = grub_script_execute (func->func);
  39. + func->executing--;
  40. function_return = 0;
  41. active_loops = loops;
  42. diff --git a/grub-core/script/function.c b/grub-core/script/function.c
  43. index d36655e51..3aad04bf9 100644
  44. --- a/grub-core/script/function.c
  45. +++ b/grub-core/script/function.c
  46. @@ -34,6 +34,7 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
  47. func = (grub_script_function_t) grub_malloc (sizeof (*func));
  48. if (! func)
  49. return 0;
  50. + func->executing = 0;
  51. func->name = grub_strdup (functionname_arg->str);
  52. if (! func->name)
  53. @@ -60,10 +61,19 @@ grub_script_function_create (struct grub_script_arg *functionname_arg,
  54. grub_script_function_t q;
  55. q = *p;
  56. - grub_script_free (q->func);
  57. - q->func = cmd;
  58. grub_free (func);
  59. - func = q;
  60. + if (q->executing > 0)
  61. + {
  62. + grub_error (GRUB_ERR_BAD_ARGUMENT,
  63. + N_("attempt to redefine a function being executed"));
  64. + func = NULL;
  65. + }
  66. + else
  67. + {
  68. + grub_script_free (q->func);
  69. + q->func = cmd;
  70. + func = q;
  71. + }
  72. }
  73. else
  74. {
  75. diff --git a/grub-core/script/parser.y b/grub-core/script/parser.y
  76. index 4f0ab8319..f80b86b6f 100644
  77. --- a/grub-core/script/parser.y
  78. +++ b/grub-core/script/parser.y
  79. @@ -289,7 +289,8 @@ function: "function" "name"
  80. grub_script_mem_free (state->func_mem);
  81. else {
  82. script->children = state->scripts;
  83. - grub_script_function_create ($2, script);
  84. + if (!grub_script_function_create ($2, script))
  85. + grub_script_free (script);
  86. }
  87. state->scripts = $<scripts>3;
  88. diff --git a/include/grub/script_sh.h b/include/grub/script_sh.h
  89. index b382bcf09..6c48e0751 100644
  90. --- a/include/grub/script_sh.h
  91. +++ b/include/grub/script_sh.h
  92. @@ -361,6 +361,8 @@ struct grub_script_function
  93. /* The next element. */
  94. struct grub_script_function *next;
  95. +
  96. + unsigned executing;
  97. };
  98. typedef struct grub_script_function *grub_script_function_t;
  99. --
  100. 2.26.2