0049-x86-boot-Add-early-cmdline-parsing-for-options-with-.patch 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
  2. From: Tom Lendacky <[email protected]>
  3. Date: Mon, 17 Jul 2017 16:10:33 -0500
  4. Subject: [PATCH] x86/boot: Add early cmdline parsing for options with
  5. arguments
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. CVE-2017-5754
  10. Add a cmdline_find_option() function to look for cmdline options that
  11. take arguments. The argument is returned in a supplied buffer and the
  12. argument length (regardless of whether it fits in the supplied buffer)
  13. is returned, with -1 indicating not found.
  14. Signed-off-by: Tom Lendacky <[email protected]>
  15. Reviewed-by: Thomas Gleixner <[email protected]>
  16. Cc: Alexander Potapenko <[email protected]>
  17. Cc: Andrey Ryabinin <[email protected]>
  18. Cc: Andy Lutomirski <[email protected]>
  19. Cc: Arnd Bergmann <[email protected]>
  20. Cc: Borislav Petkov <[email protected]>
  21. Cc: Brijesh Singh <[email protected]>
  22. Cc: Dave Young <[email protected]>
  23. Cc: Dmitry Vyukov <[email protected]>
  24. Cc: Jonathan Corbet <[email protected]>
  25. Cc: Konrad Rzeszutek Wilk <[email protected]>
  26. Cc: Larry Woodman <[email protected]>
  27. Cc: Linus Torvalds <[email protected]>
  28. Cc: Matt Fleming <[email protected]>
  29. Cc: Michael S. Tsirkin <[email protected]>
  30. Cc: Paolo Bonzini <[email protected]>
  31. Cc: Peter Zijlstra <[email protected]>
  32. Cc: Radim Krčmář <[email protected]>
  33. Cc: Rik van Riel <[email protected]>
  34. Cc: Toshimitsu Kani <[email protected]>
  35. Cc: [email protected]
  36. Cc: [email protected]
  37. Cc: [email protected]
  38. Cc: [email protected]
  39. Cc: [email protected]
  40. Cc: [email protected]
  41. Link: http://lkml.kernel.org/r/36b5f97492a9745dce27682305f990fc20e5cf8a.1500319216.git.thomas.lendacky@amd.com
  42. Signed-off-by: Ingo Molnar <[email protected]>
  43. (cherry picked from commit e505371dd83963caae1a37ead9524e8d997341be)
  44. Signed-off-by: Andy Whitcroft <[email protected]>
  45. (cherry picked from commit 37569cd003aa69a57d5666530436c2d973a57b26)
  46. Signed-off-by: Andy Whitcroft <[email protected]>
  47. Signed-off-by: Kleber Sacilotto de Souza <[email protected]>
  48. (cherry picked from commit b9f03418aa9b8ecbb1c7f32ac2bfe68fd21de4f5)
  49. Signed-off-by: Fabian Grünbichler <[email protected]>
  50. ---
  51. arch/x86/include/asm/cmdline.h | 2 +
  52. arch/x86/lib/cmdline.c | 105 +++++++++++++++++++++++++++++++++++++++++
  53. 2 files changed, 107 insertions(+)
  54. diff --git a/arch/x86/include/asm/cmdline.h b/arch/x86/include/asm/cmdline.h
  55. index e01f7f7ccb0c..84ae170bc3d0 100644
  56. --- a/arch/x86/include/asm/cmdline.h
  57. +++ b/arch/x86/include/asm/cmdline.h
  58. @@ -2,5 +2,7 @@
  59. #define _ASM_X86_CMDLINE_H
  60. int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
  61. +int cmdline_find_option(const char *cmdline_ptr, const char *option,
  62. + char *buffer, int bufsize);
  63. #endif /* _ASM_X86_CMDLINE_H */
  64. diff --git a/arch/x86/lib/cmdline.c b/arch/x86/lib/cmdline.c
  65. index 5cc78bf57232..3261abb21ef4 100644
  66. --- a/arch/x86/lib/cmdline.c
  67. +++ b/arch/x86/lib/cmdline.c
  68. @@ -104,7 +104,112 @@ __cmdline_find_option_bool(const char *cmdline, int max_cmdline_size,
  69. return 0; /* Buffer overrun */
  70. }
  71. +/*
  72. + * Find a non-boolean option (i.e. option=argument). In accordance with
  73. + * standard Linux practice, if this option is repeated, this returns the
  74. + * last instance on the command line.
  75. + *
  76. + * @cmdline: the cmdline string
  77. + * @max_cmdline_size: the maximum size of cmdline
  78. + * @option: option string to look for
  79. + * @buffer: memory buffer to return the option argument
  80. + * @bufsize: size of the supplied memory buffer
  81. + *
  82. + * Returns the length of the argument (regardless of if it was
  83. + * truncated to fit in the buffer), or -1 on not found.
  84. + */
  85. +static int
  86. +__cmdline_find_option(const char *cmdline, int max_cmdline_size,
  87. + const char *option, char *buffer, int bufsize)
  88. +{
  89. + char c;
  90. + int pos = 0, len = -1;
  91. + const char *opptr = NULL;
  92. + char *bufptr = buffer;
  93. + enum {
  94. + st_wordstart = 0, /* Start of word/after whitespace */
  95. + st_wordcmp, /* Comparing this word */
  96. + st_wordskip, /* Miscompare, skip */
  97. + st_bufcpy, /* Copying this to buffer */
  98. + } state = st_wordstart;
  99. +
  100. + if (!cmdline)
  101. + return -1; /* No command line */
  102. +
  103. + /*
  104. + * This 'pos' check ensures we do not overrun
  105. + * a non-NULL-terminated 'cmdline'
  106. + */
  107. + while (pos++ < max_cmdline_size) {
  108. + c = *(char *)cmdline++;
  109. + if (!c)
  110. + break;
  111. +
  112. + switch (state) {
  113. + case st_wordstart:
  114. + if (myisspace(c))
  115. + break;
  116. +
  117. + state = st_wordcmp;
  118. + opptr = option;
  119. + /* fall through */
  120. +
  121. + case st_wordcmp:
  122. + if ((c == '=') && !*opptr) {
  123. + /*
  124. + * We matched all the way to the end of the
  125. + * option we were looking for, prepare to
  126. + * copy the argument.
  127. + */
  128. + len = 0;
  129. + bufptr = buffer;
  130. + state = st_bufcpy;
  131. + break;
  132. + } else if (c == *opptr++) {
  133. + /*
  134. + * We are currently matching, so continue
  135. + * to the next character on the cmdline.
  136. + */
  137. + break;
  138. + }
  139. + state = st_wordskip;
  140. + /* fall through */
  141. +
  142. + case st_wordskip:
  143. + if (myisspace(c))
  144. + state = st_wordstart;
  145. + break;
  146. +
  147. + case st_bufcpy:
  148. + if (myisspace(c)) {
  149. + state = st_wordstart;
  150. + } else {
  151. + /*
  152. + * Increment len, but don't overrun the
  153. + * supplied buffer and leave room for the
  154. + * NULL terminator.
  155. + */
  156. + if (++len < bufsize)
  157. + *bufptr++ = c;
  158. + }
  159. + break;
  160. + }
  161. + }
  162. +
  163. + if (bufsize)
  164. + *bufptr = '\0';
  165. +
  166. + return len;
  167. +}
  168. +
  169. int cmdline_find_option_bool(const char *cmdline, const char *option)
  170. {
  171. return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
  172. }
  173. +
  174. +int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
  175. + int bufsize)
  176. +{
  177. + return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
  178. + buffer, bufsize);
  179. +}
  180. --
  181. 2.14.2