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

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
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -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,11 +1324,10 @@ 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);
		__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)