parisc: Fix locking in pdc_iodc_print() firmware call
Utilize pdc_lock spinlock to protect parallel modifications of the iodc_dbuf[] buffer, check length to prevent buffer overflow of iodc_dbuf[], drop the iodc_retbuf[] buffer and fix some wrong indentings. Signed-off-by: Helge Deller <deller@gmx.de> Cc: <stable@vger.kernel.org> # 6.0+
This commit is contained in:
parent
fe94cb1a61
commit
7236aae5f8
|
@ -1288,9 +1288,8 @@ void pdc_io_reset_devices(void)
|
|||
|
||||
#endif /* defined(BOOTLOADER) */
|
||||
|
||||
/* locked by pdc_console_lock */
|
||||
static int __attribute__((aligned(8))) iodc_retbuf[32];
|
||||
static char __attribute__((aligned(64))) iodc_dbuf[4096];
|
||||
/* locked by pdc_lock */
|
||||
static char iodc_dbuf[4096] __page_aligned_bss;
|
||||
|
||||
/**
|
||||
* pdc_iodc_print - Console print using IODC.
|
||||
|
@ -1307,6 +1306,9 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
|
|||
unsigned int i;
|
||||
unsigned long flags;
|
||||
|
||||
count = min_t(unsigned int, count, sizeof(iodc_dbuf));
|
||||
|
||||
spin_lock_irqsave(&pdc_lock, flags);
|
||||
for (i = 0; i < count;) {
|
||||
switch(str[i]) {
|
||||
case '\n':
|
||||
|
@ -1322,12 +1324,11 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
|
|||
}
|
||||
|
||||
print:
|
||||
spin_lock_irqsave(&pdc_lock, flags);
|
||||
real32_call(PAGE0->mem_cons.iodc_io,
|
||||
(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
|
||||
PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
|
||||
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0);
|
||||
spin_unlock_irqrestore(&pdc_lock, flags);
|
||||
real32_call(PAGE0->mem_cons.iodc_io,
|
||||
(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
|
||||
PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
|
||||
__pa(pdc_result), 0, __pa(iodc_dbuf), i, 0);
|
||||
spin_unlock_irqrestore(&pdc_lock, flags);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
@ -1354,10 +1355,11 @@ int pdc_iodc_getc(void)
|
|||
real32_call(PAGE0->mem_kbd.iodc_io,
|
||||
(unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
|
||||
PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
|
||||
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
|
||||
__pa(pdc_result), 0, __pa(iodc_dbuf), 1, 0);
|
||||
|
||||
ch = *iodc_dbuf;
|
||||
status = *iodc_retbuf;
|
||||
/* like convert_to_wide() but for first return value only: */
|
||||
status = *(int *)&pdc_result;
|
||||
spin_unlock_irqrestore(&pdc_lock, flags);
|
||||
|
||||
if (status == 0)
|
||||
|
|
Loading…
Reference in New Issue