forked from Minki/linux
TTY/Serial fixes for 5.9-rc3
Here are a few small TTY/Serial/vt fixes for 5.9-rc3 Included in here are: - qcom serial fixes - vt ioctl and core bugfixes - pl011 serial driver fixes - 8250 serial driver fixes - other misc serial driver fixes and for good measure: - fbcon fix for syzbot found problem. All of these have been in linux-next for a while with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCX0Zl1w8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+ykh0wCgicGyVAq3OUH9iTlgYqdkFHL1FWoAnAtP/jot dB0yRgk2r+RvDL9Odb2u =x5GL -----END PGP SIGNATURE----- Merge tag 'tty-5.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty Pull tty/serial fixes from Greg KH: "Here are a few small TTY/Serial/vt fixes for 5.9-rc3 Included in here are: - qcom serial fixes - vt ioctl and core bugfixes - pl011 serial driver fixes - 8250 serial driver fixes - other misc serial driver fixes and for good measure: - fbcon fix for syzbot found problem. All of these have been in linux-next for a while with no reported issues" * tag 'tty-5.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: tty: serial: imx: add dependence and build for earlycon serial: samsung: Removes the IRQ not found warning serial: 8250: change lock order in serial8250_do_startup() serial: stm32: avoid kernel warning on absence of optional IRQ serial: pl011: Fix oops on -EPROBE_DEFER serial: pl011: Don't leak amba_ports entry on driver register error serial: 8250_exar: Fix number of ports for Commtech PCIe cards tty: serial: qcom_geni_serial: Drop __init from qcom_geni_console_setup serial: qcom_geni_serial: Fix recent kdb hang vt_ioctl: change VT_RESIZEX ioctl to check for error return from vc_resize() fbcon: prevent user font height or width change from causing potential out-of-bounds access vt: defer kfree() of vc_screenbuf in vc_do_resize()
This commit is contained in:
commit
15bc20c6af
@ -744,6 +744,24 @@ static const struct exar8250_board pbn_exar_XR17V35x = {
|
||||
.exit = pci_xr17v35x_exit,
|
||||
};
|
||||
|
||||
static const struct exar8250_board pbn_fastcom35x_2 = {
|
||||
.num_ports = 2,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
.exit = pci_xr17v35x_exit,
|
||||
};
|
||||
|
||||
static const struct exar8250_board pbn_fastcom35x_4 = {
|
||||
.num_ports = 4,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
.exit = pci_xr17v35x_exit,
|
||||
};
|
||||
|
||||
static const struct exar8250_board pbn_fastcom35x_8 = {
|
||||
.num_ports = 8,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
.exit = pci_xr17v35x_exit,
|
||||
};
|
||||
|
||||
static const struct exar8250_board pbn_exar_XR17V4358 = {
|
||||
.num_ports = 12,
|
||||
.setup = pci_xr17v35x_setup,
|
||||
@ -811,9 +829,9 @@ static const struct pci_device_id exar_pci_tbl[] = {
|
||||
EXAR_DEVICE(EXAR, XR17V358, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(EXAR, XR17V4358, pbn_exar_XR17V4358),
|
||||
EXAR_DEVICE(EXAR, XR17V8358, pbn_exar_XR17V8358),
|
||||
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_exar_XR17V35x),
|
||||
EXAR_DEVICE(COMMTECH, 4222PCIE, pbn_fastcom35x_2),
|
||||
EXAR_DEVICE(COMMTECH, 4224PCIE, pbn_fastcom35x_4),
|
||||
EXAR_DEVICE(COMMTECH, 4228PCIE, pbn_fastcom35x_8),
|
||||
|
||||
EXAR_DEVICE(COMMTECH, 4222PCI335, pbn_fastcom335_2),
|
||||
EXAR_DEVICE(COMMTECH, 4224PCI335, pbn_fastcom335_4),
|
||||
|
@ -2275,6 +2275,10 @@ int serial8250_do_startup(struct uart_port *port)
|
||||
|
||||
if (port->irq && !(up->port.flags & UPF_NO_THRE_TEST)) {
|
||||
unsigned char iir1;
|
||||
|
||||
if (port->irqflags & IRQF_SHARED)
|
||||
disable_irq_nosync(port->irq);
|
||||
|
||||
/*
|
||||
* Test for UARTs that do not reassert THRE when the
|
||||
* transmitter is idle and the interrupt has already
|
||||
@ -2284,8 +2288,6 @@ int serial8250_do_startup(struct uart_port *port)
|
||||
* allow register changes to become visible.
|
||||
*/
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
if (up->port.irqflags & IRQF_SHARED)
|
||||
disable_irq_nosync(port->irq);
|
||||
|
||||
wait_for_xmitr(up, UART_LSR_THRE);
|
||||
serial_port_out_sync(port, UART_IER, UART_IER_THRI);
|
||||
@ -2297,9 +2299,10 @@ int serial8250_do_startup(struct uart_port *port)
|
||||
iir = serial_port_in(port, UART_IIR);
|
||||
serial_port_out(port, UART_IER, 0);
|
||||
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
if (port->irqflags & IRQF_SHARED)
|
||||
enable_irq(port->irq);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
/*
|
||||
* If the interrupt is not reasserted, or we otherwise
|
||||
|
@ -517,6 +517,7 @@ config SERIAL_IMX_CONSOLE
|
||||
|
||||
config SERIAL_IMX_EARLYCON
|
||||
bool "Earlycon on IMX serial port"
|
||||
depends on ARCH_MXC || COMPILE_TEST
|
||||
depends on OF
|
||||
select SERIAL_EARLYCON
|
||||
help
|
||||
|
@ -43,6 +43,7 @@ obj-$(CONFIG_SERIAL_ZS) += zs.o
|
||||
obj-$(CONFIG_SERIAL_SH_SCI) += sh-sci.o
|
||||
obj-$(CONFIG_SERIAL_CPM) += cpm_uart/
|
||||
obj-$(CONFIG_SERIAL_IMX) += imx.o
|
||||
obj-$(CONFIG_SERIAL_IMX_EARLYCON) += imx_earlycon.o
|
||||
obj-$(CONFIG_SERIAL_MPC52xx) += mpc52xx_uart.o
|
||||
obj-$(CONFIG_SERIAL_ICOM) += icom.o
|
||||
obj-$(CONFIG_SERIAL_MESON) += meson_uart.o
|
||||
|
@ -2241,9 +2241,8 @@ pl011_console_write(struct console *co, const char *s, unsigned int count)
|
||||
clk_disable(uap->clk);
|
||||
}
|
||||
|
||||
static void __init
|
||||
pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
int *parity, int *bits)
|
||||
static void pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
int *parity, int *bits)
|
||||
{
|
||||
if (pl011_read(uap, REG_CR) & UART01x_CR_UARTEN) {
|
||||
unsigned int lcr_h, ibrd, fbrd;
|
||||
@ -2276,7 +2275,7 @@ pl011_console_get_options(struct uart_amba_port *uap, int *baud,
|
||||
}
|
||||
}
|
||||
|
||||
static int __init pl011_console_setup(struct console *co, char *options)
|
||||
static int pl011_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_amba_port *uap;
|
||||
int baud = 38400;
|
||||
@ -2344,8 +2343,8 @@ static int __init pl011_console_setup(struct console *co, char *options)
|
||||
*
|
||||
* Returns 0 if console matches; otherwise non-zero to use default matching
|
||||
*/
|
||||
static int __init pl011_console_match(struct console *co, char *name, int idx,
|
||||
char *options)
|
||||
static int pl011_console_match(struct console *co, char *name, int idx,
|
||||
char *options)
|
||||
{
|
||||
unsigned char iotype;
|
||||
resource_size_t addr;
|
||||
@ -2615,7 +2614,7 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap,
|
||||
|
||||
static int pl011_register_port(struct uart_amba_port *uap)
|
||||
{
|
||||
int ret;
|
||||
int ret, i;
|
||||
|
||||
/* Ensure interrupts from this UART are masked and cleared */
|
||||
pl011_write(0, uap, REG_IMSC);
|
||||
@ -2626,6 +2625,9 @@ static int pl011_register_port(struct uart_amba_port *uap)
|
||||
if (ret < 0) {
|
||||
dev_err(uap->port.dev,
|
||||
"Failed to register AMBA-PL011 driver\n");
|
||||
for (i = 0; i < ARRAY_SIZE(amba_ports); i++)
|
||||
if (amba_ports[i] == uap)
|
||||
amba_ports[i] = NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
@ -361,11 +361,16 @@ static int qcom_geni_serial_get_char(struct uart_port *uport)
|
||||
return NO_POLL_CHAR;
|
||||
|
||||
if (word_cnt == 1 && (status & RX_LAST))
|
||||
/*
|
||||
* NOTE: If RX_LAST_BYTE_VALID is 0 it needs to be
|
||||
* treated as if it was BYTES_PER_FIFO_WORD.
|
||||
*/
|
||||
private_data->poll_cached_bytes_cnt =
|
||||
(status & RX_LAST_BYTE_VALID_MSK) >>
|
||||
RX_LAST_BYTE_VALID_SHFT;
|
||||
else
|
||||
private_data->poll_cached_bytes_cnt = 4;
|
||||
|
||||
if (private_data->poll_cached_bytes_cnt == 0)
|
||||
private_data->poll_cached_bytes_cnt = BYTES_PER_FIFO_WORD;
|
||||
|
||||
private_data->poll_cached_bytes =
|
||||
readl(uport->membase + SE_GENI_RX_FIFOn);
|
||||
@ -1098,7 +1103,7 @@ static unsigned int qcom_geni_serial_tx_empty(struct uart_port *uport)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SERIAL_QCOM_GENI_CONSOLE
|
||||
static int __init qcom_geni_console_setup(struct console *co, char *options)
|
||||
static int qcom_geni_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *uport;
|
||||
struct qcom_geni_serial_port *port;
|
||||
|
@ -1905,9 +1905,11 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport,
|
||||
ourport->tx_irq = ret + 1;
|
||||
}
|
||||
|
||||
ret = platform_get_irq(platdev, 1);
|
||||
if (ret > 0)
|
||||
ourport->tx_irq = ret;
|
||||
if (!s3c24xx_serial_has_interrupt_mask(port)) {
|
||||
ret = platform_get_irq(platdev, 1);
|
||||
if (ret > 0)
|
||||
ourport->tx_irq = ret;
|
||||
}
|
||||
/*
|
||||
* DMA is currently supported only on DT platforms, if DMA properties
|
||||
* are specified.
|
||||
|
@ -970,7 +970,7 @@ static int stm32_init_port(struct stm32_port *stm32port,
|
||||
return ret;
|
||||
|
||||
if (stm32port->info->cfg.has_wakeup) {
|
||||
stm32port->wakeirq = platform_get_irq(pdev, 1);
|
||||
stm32port->wakeirq = platform_get_irq_optional(pdev, 1);
|
||||
if (stm32port->wakeirq <= 0 && stm32port->wakeirq != -ENXIO)
|
||||
return stm32port->wakeirq ? : -ENODEV;
|
||||
}
|
||||
|
@ -1201,7 +1201,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
||||
unsigned int old_rows, old_row_size, first_copied_row;
|
||||
unsigned int new_cols, new_rows, new_row_size, new_screen_size;
|
||||
unsigned int user;
|
||||
unsigned short *newscreen;
|
||||
unsigned short *oldscreen, *newscreen;
|
||||
struct uni_screen *new_uniscr = NULL;
|
||||
|
||||
WARN_CONSOLE_UNLOCKED();
|
||||
@ -1299,10 +1299,11 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
|
||||
if (new_scr_end > new_origin)
|
||||
scr_memsetw((void *)new_origin, vc->vc_video_erase_char,
|
||||
new_scr_end - new_origin);
|
||||
kfree(vc->vc_screenbuf);
|
||||
oldscreen = vc->vc_screenbuf;
|
||||
vc->vc_screenbuf = newscreen;
|
||||
vc->vc_screenbuf_size = new_screen_size;
|
||||
set_origin(vc);
|
||||
kfree(oldscreen);
|
||||
|
||||
/* do part of a reset_terminal() */
|
||||
vc->vc_top = 0;
|
||||
|
@ -806,12 +806,22 @@ static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
|
||||
console_lock();
|
||||
vcp = vc_cons[i].d;
|
||||
if (vcp) {
|
||||
int ret;
|
||||
int save_scan_lines = vcp->vc_scan_lines;
|
||||
int save_font_height = vcp->vc_font.height;
|
||||
|
||||
if (v.v_vlin)
|
||||
vcp->vc_scan_lines = v.v_vlin;
|
||||
if (v.v_clin)
|
||||
vcp->vc_font.height = v.v_clin;
|
||||
vcp->vc_resize_user = 1;
|
||||
vc_resize(vcp, v.v_cols, v.v_rows);
|
||||
ret = vc_resize(vcp, v.v_cols, v.v_rows);
|
||||
if (ret) {
|
||||
vcp->vc_scan_lines = save_scan_lines;
|
||||
vcp->vc_font.height = save_font_height;
|
||||
console_unlock();
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
console_unlock();
|
||||
}
|
||||
|
@ -2191,6 +2191,9 @@ static void updatescrollmode(struct fbcon_display *p,
|
||||
}
|
||||
}
|
||||
|
||||
#define PITCH(w) (((w) + 7) >> 3)
|
||||
#define CALC_FONTSZ(h, p, c) ((h) * (p) * (c)) /* size = height * pitch * charcount */
|
||||
|
||||
static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
||||
unsigned int height, unsigned int user)
|
||||
{
|
||||
@ -2200,6 +2203,24 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width,
|
||||
struct fb_var_screeninfo var = info->var;
|
||||
int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
|
||||
|
||||
if (ops->p && ops->p->userfont && FNTSIZE(vc->vc_font.data)) {
|
||||
int size;
|
||||
int pitch = PITCH(vc->vc_font.width);
|
||||
|
||||
/*
|
||||
* If user font, ensure that a possible change to user font
|
||||
* height or width will not allow a font data out-of-bounds access.
|
||||
* NOTE: must use original charcount in calculation as font
|
||||
* charcount can change and cannot be used to determine the
|
||||
* font data allocated size.
|
||||
*/
|
||||
if (pitch <= 0)
|
||||
return -EINVAL;
|
||||
size = CALC_FONTSZ(vc->vc_font.height, pitch, FNTCHARCNT(vc->vc_font.data));
|
||||
if (size > FNTSIZE(vc->vc_font.data))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
virt_w = FBCON_SWAP(ops->rotate, width, height);
|
||||
virt_h = FBCON_SWAP(ops->rotate, height, width);
|
||||
virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width,
|
||||
@ -2652,7 +2673,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
||||
int size;
|
||||
int i, csum;
|
||||
u8 *new_data, *data = font->data;
|
||||
int pitch = (font->width+7) >> 3;
|
||||
int pitch = PITCH(font->width);
|
||||
|
||||
/* Is there a reason why fbconsole couldn't handle any charcount >256?
|
||||
* If not this check should be changed to charcount < 256 */
|
||||
@ -2668,7 +2689,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font,
|
||||
if (fbcon_invalid_charcount(info, charcount))
|
||||
return -EINVAL;
|
||||
|
||||
size = h * pitch * charcount;
|
||||
size = CALC_FONTSZ(h, pitch, charcount);
|
||||
|
||||
new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size, GFP_USER);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user