Commit 7236aae5 authored by Helge Deller's avatar Helge Deller

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: default avatarHelge Deller <deller@gmx.de>
Cc: <stable@vger.kernel.org> # 6.0+
parent fe94cb1a
...@@ -1288,9 +1288,8 @@ void pdc_io_reset_devices(void) ...@@ -1288,9 +1288,8 @@ void pdc_io_reset_devices(void)
#endif /* defined(BOOTLOADER) */ #endif /* defined(BOOTLOADER) */
/* locked by pdc_console_lock */ /* locked by pdc_lock */
static int __attribute__((aligned(8))) iodc_retbuf[32]; static char iodc_dbuf[4096] __page_aligned_bss;
static char __attribute__((aligned(64))) iodc_dbuf[4096];
/** /**
* pdc_iodc_print - Console print using IODC. * pdc_iodc_print - Console print using IODC.
...@@ -1307,6 +1306,9 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) ...@@ -1307,6 +1306,9 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
unsigned int i; unsigned int i;
unsigned long flags; unsigned long flags;
count = min_t(unsigned int, count, sizeof(iodc_dbuf));
spin_lock_irqsave(&pdc_lock, flags);
for (i = 0; i < count;) { for (i = 0; i < count;) {
switch(str[i]) { switch(str[i]) {
case '\n': case '\n':
...@@ -1322,12 +1324,11 @@ int pdc_iodc_print(const unsigned char *str, unsigned count) ...@@ -1322,12 +1324,11 @@ int pdc_iodc_print(const unsigned char *str, unsigned count)
} }
print: print:
spin_lock_irqsave(&pdc_lock, flags); real32_call(PAGE0->mem_cons.iodc_io,
real32_call(PAGE0->mem_cons.iodc_io, (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT, PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers), __pa(pdc_result), 0, __pa(iodc_dbuf), i, 0);
__pa(iodc_retbuf), 0, __pa(iodc_dbuf), i, 0); spin_unlock_irqrestore(&pdc_lock, flags);
spin_unlock_irqrestore(&pdc_lock, flags);
return i; return i;
} }
...@@ -1354,10 +1355,11 @@ int pdc_iodc_getc(void) ...@@ -1354,10 +1355,11 @@ int pdc_iodc_getc(void)
real32_call(PAGE0->mem_kbd.iodc_io, real32_call(PAGE0->mem_kbd.iodc_io,
(unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN, (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), 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; 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); spin_unlock_irqrestore(&pdc_lock, flags);
if (status == 0) if (status == 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment