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