mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-26 17:35:17 +07:00
934bda59f2
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 <dja@axtens.net> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
89 lines
2.5 KiB
C
89 lines
2.5 KiB
C
/*
|
|
* hvconsole.c
|
|
* Copyright (C) 2004 Hollis Blanchard, IBM Corporation
|
|
* Copyright (C) 2004 IBM Corporation
|
|
*
|
|
* Additional Author(s):
|
|
* Ryan S. Arnold <rsa@us.ibm.com>
|
|
*
|
|
* LPAR console support.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/export.h>
|
|
#include <linux/errno.h>
|
|
#include <asm/hvcall.h>
|
|
#include <asm/hvconsole.h>
|
|
#include <asm/plpar_wrappers.h>
|
|
|
|
/**
|
|
* hvc_get_chars - retrieve characters from firmware for denoted vterm adapter
|
|
* @vtermno: The vtermno or unit_address of the adapter from which to fetch the
|
|
* data.
|
|
* @buf: The character buffer into which to put the character data fetched from
|
|
* firmware.
|
|
* @count: not used?
|
|
*/
|
|
int hvc_get_chars(uint32_t vtermno, char *buf, int count)
|
|
{
|
|
long ret;
|
|
unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
|
|
unsigned long *lbuf = (unsigned long *)buf;
|
|
|
|
ret = plpar_hcall(H_GET_TERM_CHAR, retbuf, vtermno);
|
|
lbuf[0] = be64_to_cpu(retbuf[1]);
|
|
lbuf[1] = be64_to_cpu(retbuf[2]);
|
|
|
|
if (ret == H_SUCCESS)
|
|
return retbuf[0];
|
|
|
|
return 0;
|
|
}
|
|
|
|
EXPORT_SYMBOL(hvc_get_chars);
|
|
|
|
|
|
/**
|
|
* hvc_put_chars: send characters to firmware for denoted vterm adapter
|
|
* @vtermno: The vtermno or unit_address of the adapter from which the data
|
|
* originated.
|
|
* @buf: The character buffer that contains the character data to send to
|
|
* firmware. Must be at least 16 bytes, even if count is less than 16.
|
|
* @count: Send this number of characters.
|
|
*/
|
|
int hvc_put_chars(uint32_t vtermno, const char *buf, int count)
|
|
{
|
|
unsigned long *lbuf = (unsigned long *) buf;
|
|
long ret;
|
|
|
|
|
|
/* hcall will ret H_PARAMETER if 'count' exceeds firmware max.*/
|
|
if (count > MAX_VIO_PUT_CHARS)
|
|
count = MAX_VIO_PUT_CHARS;
|
|
|
|
ret = plpar_hcall_norets(H_PUT_TERM_CHAR, vtermno, count,
|
|
cpu_to_be64(lbuf[0]),
|
|
cpu_to_be64(lbuf[1]));
|
|
if (ret == H_SUCCESS)
|
|
return count;
|
|
if (ret == H_BUSY)
|
|
return -EAGAIN;
|
|
return -EIO;
|
|
}
|
|
|
|
EXPORT_SYMBOL(hvc_put_chars);
|