Re: [CHECKER] repetitive/contradictory comparison bugs for 2.4.7

Russell King (rmk@arm.linux.org.uk)
Thu, 26 Jul 2001 21:15:58 +0100


On Thu, Jul 26, 2001 at 08:54:48PM +0100, Alex Bligh - linux-kernel wrote:
> May be I'm being dumb here, and without wishing to open the 'volatile'
> can of worms elsewhere, but:
>
> static char * tmp_buf;

Here is the fix... I've updated it a bit to plug another small race in
rs_write as well.

The following code uses the tmp_buf_sem to lock the creation and freeing
of the tmp_buf page. This same lock is used to prevent concurrent accesses
to this very same page in rs_write().

--
Russell King (rmk@arm.linux.org.uk)                The developer of ARM Linux
             http://www.arm.linux.org.uk/personal/aboutme.html

--- orig/drivers/char/serial.c Sat Jul 21 10:46:42 2001 +++ linux/drivers/char/serial.c Thu Jul 26 21:14:12 2001 @@ -1848,12 +1848,17 @@ if (serial_paranoia_check(info, tty->device, "rs_write")) return 0; - if (!tty || !info->xmit.buf || !tmp_buf) + if (!tty || !info->xmit.buf) return 0; save_flags(flags); if (from_user) { down(&tmp_buf_sem); + if (!tmp_buf) { + up(&tmp_buf_sem); + restore_flags(flags); + return 0; + } while (1) { int c1; c = CIRC_SPACE_TO_END(info->xmit.head, @@ -3129,7 +3134,6 @@ { struct async_struct *info; int retval, line; - unsigned long page; MOD_INC_USE_COUNT; line = MINOR(tty->device) - tty->driver.minor_start; @@ -3157,17 +3161,16 @@ info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0; #endif + down(&tmp_buf_sem); if (!tmp_buf) { - page = get_zeroed_page(GFP_KERNEL); - if (!page) { + tmp_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL); + if (!tmp_buf) { + up(&tmp_buf_sem); MOD_DEC_USE_COUNT; return -ENOMEM; } - if (tmp_buf) - free_page(page); - else - tmp_buf = (unsigned char *) page; } + up(&tmp_buf_sem); /* * If the port is the middle of closing, bail out now @@ -5666,12 +5669,13 @@ if (DEACTIVATE_FUNC(brd->dev)) (DEACTIVATE_FUNC(brd->dev))(brd->dev); } -#endif +#endif + down(&tmp_buf_sem); if (tmp_buf) { - unsigned long pg = (unsigned long) tmp_buf; + free_page(tmp_buf); tmp_buf = NULL; - free_page(pg); } + up(&tmp_buf_sem); #ifdef ENABLE_SERIAL_PCI if (serial_pci_driver.name[0]) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/