Skip to content

Commit 13817d4

Browse files
l1kbroonie
authored andcommitted
spi: bcm2835: Fix out-of-bounds access with more than 4 slaves
Commit 571e31f ("spi: bcm2835: Cache CS register value for ->prepare_message()") limited the number of slaves to 3 at compile-time. The limitation was necessitated by a statically-sized array prepare_cs[] in the driver private data which contains a per-slave register value. The commit sought to enforce the limitation at run-time by setting the controller's num_chipselect to 3: Slaves with a higher chipselect are rejected by spi_add_device(). However the commit neglected that num_chipselect only limits the number of *native* chipselects. If GPIO chipselects are specified in the device tree for more than 3 slaves, num_chipselect is silently raised by of_spi_get_gpio_numbers() and the result are out-of-bounds accesses to the statically-sized array prepare_cs[]. As a bandaid fix which is backportable to stable, raise the number of allowed slaves to 24 (which "ought to be enough for anybody"), enforce the limitation on slave ->setup and revert num_chipselect to 3 (which is the number of native chipselects supported by the controller). An upcoming for-next commit will allow an arbitrary number of slaves. Fixes: 571e31f ("spi: bcm2835: Cache CS register value for ->prepare_message()") Reported-by: Joe Burmeister <[email protected]> Signed-off-by: Lukas Wunner <[email protected]> Cc: [email protected] # v5.4+ Cc: Phil Elwell <[email protected]> Link: https://lore.kernel.org/r/75854affc1923309fde05e47494263bde73e5592.1621703210.git.lukas@wunner.de Signed-off-by: Mark Brown <[email protected]>
1 parent b4e46c9 commit 13817d4

File tree

1 file changed

+8
-2
lines changed

1 file changed

+8
-2
lines changed

drivers/spi/spi-bcm2835.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
#define BCM2835_SPI_FIFO_SIZE 64
6969
#define BCM2835_SPI_FIFO_SIZE_3_4 48
7070
#define BCM2835_SPI_DMA_MIN_LENGTH 96
71-
#define BCM2835_SPI_NUM_CS 4 /* raise as necessary */
71+
#define BCM2835_SPI_NUM_CS 24 /* raise as necessary */
7272
#define BCM2835_SPI_MODE_BITS (SPI_CPOL | SPI_CPHA | SPI_CS_HIGH \
7373
| SPI_NO_CS | SPI_3WIRE)
7474

@@ -1195,6 +1195,12 @@ static int bcm2835_spi_setup(struct spi_device *spi)
11951195
struct gpio_chip *chip;
11961196
u32 cs;
11971197

1198+
if (spi->chip_select >= BCM2835_SPI_NUM_CS) {
1199+
dev_err(&spi->dev, "only %d chip-selects supported\n",
1200+
BCM2835_SPI_NUM_CS - 1);
1201+
return -EINVAL;
1202+
}
1203+
11981204
/*
11991205
* Precalculate SPI slave's CS register value for ->prepare_message():
12001206
* The driver always uses software-controlled GPIO chip select, hence
@@ -1288,7 +1294,7 @@ static int bcm2835_spi_probe(struct platform_device *pdev)
12881294
ctlr->use_gpio_descriptors = true;
12891295
ctlr->mode_bits = BCM2835_SPI_MODE_BITS;
12901296
ctlr->bits_per_word_mask = SPI_BPW_MASK(8);
1291-
ctlr->num_chipselect = BCM2835_SPI_NUM_CS;
1297+
ctlr->num_chipselect = 3;
12921298
ctlr->setup = bcm2835_spi_setup;
12931299
ctlr->transfer_one = bcm2835_spi_transfer_one;
12941300
ctlr->handle_err = bcm2835_spi_handle_err;

0 commit comments

Comments
 (0)