Re: [PATCH] staging: fbtft: fix unaligned access and buffer size when startbyte is used
David Laight <[email protected]>
| Newsgroups | org.kernel.vger.linux-fbdev,dev.linux.lists.linux-staging,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <20260626074810.433c4006@pumpkin> |
On Thu, 25 Jun 2026 18:30:41 +0800 suryasaimadhu <[email protected]> wrote: > When par->startbyte is non-zero, buf is advanced by one byte creating > an unaligned pointer for 16-bit types (u16, __be16). Dereferencing this > unaligned pointer can cause a kernel panic on strict-alignment > architectures. > > Fix by using put_unaligned() instead of direct pointer dereference. > > Also fix incorrect buffer size calculation in fbtft_write_buf_dc() call: > len * (sizeof(data_type) + offset) /* wrong: multiplies offset by len */ > len * sizeof(data_type) + offset /* correct: one startbyte + > len items */ That should probably be a separate patch. > > Signed-off-by: suryasaimadhu <[email protected]> > --- > drivers/staging/fbtft/fbtft-bus.c | 13 ++++++++----- > 1 file changed, 8 insertions(+), 5 deletions(-) > > diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c > index 2169f8d1d..cfcf4d7e7 100644 > --- a/drivers/staging/fbtft/fbtft-bus.c > +++ b/drivers/staging/fbtft/fbtft-bus.c > @@ -4,6 +4,7 @@ > #include <linux/gpio/consumer.h> > #include <linux/spi/spi.h> > #include "fbtft.h" > +#include <linux/unaligned.h> > > /***************************************************************************** > * > @@ -40,7 +41,7 @@ void func(struct fbtft_par *par, int len, ...) \ I'd consider changing that to: func(struct fbtft_par *par, int len, u8 cmd, ...) and probably reducing len by one. It makes it more obvious that the first parameter is mandatory and the ... is associated data. David > offset = 1; \ > } \ > \ > - *buf = modifier((data_type)va_arg(args, unsigned int)); \ > + put_unaligned(modifier((data_type)va_arg(args, unsigned int)), buf); \ > ret = fbtft_write_buf_dc(par, par->buf, sizeof(data_type) + offset, \ > 0); \ > if (ret < 0) \ > @@ -52,11 +53,13 @@ void func(struct fbtft_par *par, int len, ...) \ > \ > if (len) { \ > i = len; \ > - while (i--) \ > - *buf++ = modifier((data_type)va_arg(args, \ > - unsigned int)); \ > + while (i--) { \ > + put_unaligned(modifier((data_type)va_arg(args, \ > + unsigned int)), buf); \ > + buf++; \ > + } \ > fbtft_write_buf_dc(par, par->buf, \ > - len * (sizeof(data_type) + offset), 1); \ > + len * sizeof(data_type) + offset, 1); \ > } \ > out: \ > va_end(args); \