Re: [PATCH] staging: fbtft: fix unaligned access and buffer size when startbyte is used
From: David Laight <hidden>
Date: 2026-06-26 06:48:14
Also in:
dri-devel, linux-staging, lkml
On Thu, 25 Jun 2026 18:30:41 +0800 suryasaimadhu [off-list ref] 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.
quoted hunk ↗ jump to hunk
Signed-off-by: suryasaimadhu <redacted> --- 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
quoted hunk ↗ jump to hunk
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); \