Skip to content

Commit 70b0b33

Browse files
daxtensgregkh
authored andcommitted
powerpc/pseries/hvconsole: Fix stack overread via udbg
[ Upstream commit 934bda5 ] While developing KASAN for 64-bit book3s, I hit the following stack over-read. It occurs because the hypercall to put characters onto the terminal takes 2 longs (128 bits/16 bytes) of characters at a time, and so hvc_put_chars() would unconditionally copy 16 bytes from the argument buffer, regardless of supplied length. However, udbg_hvc_putc() can call hvc_put_chars() with a single-byte buffer, leading to the error. ================================================================== BUG: KASAN: stack-out-of-bounds in hvc_put_chars+0xdc/0x110 Read of size 8 at addr c0000000023e7a90 by task swapper/0 CPU: 0 PID: 0 Comm: swapper Not tainted 5.2.0-rc2-next-20190528-02824-g048a6ab4835b #113 Call Trace: dump_stack+0x104/0x154 (unreliable) print_address_description+0xa0/0x30c __kasan_report+0x20c/0x224 kasan_report+0x18/0x30 __asan_report_load8_noabort+0x24/0x40 hvc_put_chars+0xdc/0x110 hvterm_raw_put_chars+0x9c/0x110 udbg_hvc_putc+0x154/0x200 udbg_write+0xf0/0x240 console_unlock+0x868/0xd30 register_console+0x970/0xe90 register_early_udbg_console+0xf8/0x114 setup_arch+0x108/0x790 start_kernel+0x104/0x784 start_here_common+0x1c/0x534 Memory state around the buggy address: c0000000023e7980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0000000023e7a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 >c0000000023e7a80: f1 f1 01 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 ^ c0000000023e7b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c0000000023e7b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ================================================================== Document that a 16-byte buffer is requred, and provide it in udbg. Signed-off-by: Daniel Axtens <[email protected]> Signed-off-by: Michael Ellerman <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent ff23a27 commit 70b0b33

File tree

2 files changed

+16
-2
lines changed

2 files changed

+16
-2
lines changed

arch/powerpc/platforms/pseries/hvconsole.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ EXPORT_SYMBOL(hvc_get_chars);
6262
* @vtermno: The vtermno or unit_address of the adapter from which the data
6363
* originated.
6464
* @buf: The character buffer that contains the character data to send to
65-
* firmware.
65+
* firmware. Must be at least 16 bytes, even if count is less than 16.
6666
* @count: Send this number of characters.
6767
*/
6868
int hvc_put_chars(uint32_t vtermno, const char *buf, int count)

drivers/tty/hvc/hvc_vio.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,14 @@ static int hvterm_raw_get_chars(uint32_t vtermno, char *buf, int count)
120120
return got;
121121
}
122122

123+
/**
124+
* hvterm_raw_put_chars: send characters to firmware for given vterm adapter
125+
* @vtermno: The virtual terminal number.
126+
* @buf: The characters to send. Because of the underlying hypercall in
127+
* hvc_put_chars(), this buffer must be at least 16 bytes long, even if
128+
* you are sending fewer chars.
129+
* @count: number of chars to send.
130+
*/
123131
static int hvterm_raw_put_chars(uint32_t vtermno, const char *buf, int count)
124132
{
125133
struct hvterm_priv *pv = hvterm_privs[vtermno];
@@ -232,6 +240,7 @@ static const struct hv_ops hvterm_hvsi_ops = {
232240
static void udbg_hvc_putc(char c)
233241
{
234242
int count = -1;
243+
unsigned char bounce_buffer[16];
235244

236245
if (!hvterm_privs[0])
237246
return;
@@ -242,7 +251,12 @@ static void udbg_hvc_putc(char c)
242251
do {
243252
switch(hvterm_privs[0]->proto) {
244253
case HV_PROTOCOL_RAW:
245-
count = hvterm_raw_put_chars(0, &c, 1);
254+
/*
255+
* hvterm_raw_put_chars requires at least a 16-byte
256+
* buffer, so go via the bounce buffer
257+
*/
258+
bounce_buffer[0] = c;
259+
count = hvterm_raw_put_chars(0, bounce_buffer, 1);
246260
break;
247261
case HV_PROTOCOL_HVSI:
248262
count = hvterm_hvsi_put_chars(0, &c, 1);

0 commit comments

Comments
 (0)