Re: [PATCH 1/2] serial: sprd: Assign sprd_port after initialized to avoid wrong access

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 10 Jul 2023 at 17:57, Baolin Wang <baolin.wang@xxxxxxxxxxxxxxxxx> wrote:
>
>
>
> On 7/10/2023 4:03 PM, Chunyan Zhang wrote:
> > The global pointer 'sprd_port' maybe not zero when sprd_probe returns
> > fail, that is a risk for sprd_port to be accessed afterward, and will
> > lead unexpected errors.
> >
> > For example:
> >
> > There're two UART ports, UART1 is used for console and configured in kernel
> > command line, i.e. "console=";
> >
> > The UART1 probe fail and the memory allocated to sprd_port[1] was released,
> > but sprd_port[1] was not set to NULL;
>
> IMO, we should just set sprd_port[1] to be NULL, which seems simpler?

This patch just does like this indeed, in the label of 'clean_port'.
Adding a local variable instead of using global pointer (sprd_port[])
to store the virtual address allocated for sprd_port can avoid
overmany goto labels.

>
> >
> > In UART2 probe, the same virtual address was allocated to sprd_port[2],
> > and UART2 probe process finally will go into sprd_console_setup() to
> > register UART1 as console since it is configured as preferred console
> > (filled to console_cmdline[]), but the console parameters (sprd_port[1])
> > actually belongs to UART2.
>
> I'm confusing why the console parameters belongs to UART2? Since the
> console_cmdline[] will specify the serial index, that belongs to UART1.

The same virtual address stored in sprd_port[1] was reallocated to
sprd_port[2] after the UART1 probe returned failure.

Thanks for the review,
Chunyan


> Please correct me if I miss something.
>
> > So move the sprd_port[] assignment to where the port already initialized
> > can avoid the above issue.
> >
> > Fixes: b7396a38fb28 ("tty/serial: Add Spreadtrum sc9836-uart driver support")
> > Signed-off-by: Chunyan Zhang <chunyan.zhang@xxxxxxxxxx>
> > ---
> >   drivers/tty/serial/sprd_serial.c | 24 ++++++++++++++++--------
> >   1 file changed, 16 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
> > index b58f51296ace..942808517393 100644
> > --- a/drivers/tty/serial/sprd_serial.c
> > +++ b/drivers/tty/serial/sprd_serial.c
> > @@ -1106,7 +1106,7 @@ static bool sprd_uart_is_console(struct uart_port *uport)
> >   static int sprd_clk_init(struct uart_port *uport)
> >   {
> >       struct clk *clk_uart, *clk_parent;
> > -     struct sprd_uart_port *u = sprd_port[uport->line];
> > +     struct sprd_uart_port *u = container_of(uport, struct sprd_uart_port, port);
> >
> >       clk_uart = devm_clk_get(uport->dev, "uart");
> >       if (IS_ERR(clk_uart)) {
> > @@ -1149,22 +1149,22 @@ static int sprd_probe(struct platform_device *pdev)
> >   {
> >       struct resource *res;
> >       struct uart_port *up;
> > +     struct sprd_uart_port *sport;
> >       int irq;
> >       int index;
> >       int ret;
> >
> >       index = of_alias_get_id(pdev->dev.of_node, "serial");
> > -     if (index < 0 || index >= ARRAY_SIZE(sprd_port)) {
> > +     if (index < 0 || index >= UART_NR_MAX) {
> >               dev_err(&pdev->dev, "got a wrong serial alias id %d\n", index);
> >               return -EINVAL;
> >       }
> >
> > -     sprd_port[index] = devm_kzalloc(&pdev->dev, sizeof(*sprd_port[index]),
> > -                                     GFP_KERNEL);
> > -     if (!sprd_port[index])
> > +     sport = devm_kzalloc(&pdev->dev, sizeof(*sport), GFP_KERNEL);
> > +     if (!sport)
> >               return -ENOMEM;
> >
> > -     up = &sprd_port[index]->port;
> > +     up = &sport->port;
> >       up->dev = &pdev->dev;
> >       up->line = index;
> >       up->type = PORT_SPRD;
> > @@ -1195,7 +1195,7 @@ static int sprd_probe(struct platform_device *pdev)
> >        * Allocate one dma buffer to prepare for receive transfer, in case
> >        * memory allocation failure at runtime.
> >        */
> > -     ret = sprd_rx_alloc_buf(sprd_port[index]);
> > +     ret = sprd_rx_alloc_buf(sport);
> >       if (ret)
> >               return ret;
> >
> > @@ -1208,12 +1208,20 @@ static int sprd_probe(struct platform_device *pdev)
> >       }
> >       sprd_ports_num++;
> >
> > +     sprd_port[index] = sport;
> > +
> >       ret = uart_add_one_port(&sprd_uart_driver, up);
> >       if (ret)
> > -             sprd_remove(pdev);
> > +             goto clean_port;
> >
> >       platform_set_drvdata(pdev, up);
> >
> > +     return 0;
> > +
> > +clean_port:
> > +     sprd_port[index] = NULL;
> > +     sprd_ports_num--;
> > +     uart_unregister_driver(&sprd_uart_driver);
> >       return ret;
> >   }
> >



[Index of Archives]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Linux PPP]     [Linux FS]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Linmodem]     [Device Mapper]     [Linux Kernel for ARM]

  Powered by Linux