Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: pse-pd: fix out-of-bounds bitmap access in pse_isr() on 32-bit

In pse_isr(), notifs_mask was declared as a single unsigned long on the
stack (32 bits on 32-bit architectures). For PSE controllers with more
than 32 ports, this causes two problems:

- map_event callbacks could wrote bit positions >= 32 via
*notifs_mask |= BIT(i), which is undefined behaviour on a 32-bit
unsigned long and corrupts adjacent stack memory.

- for_each_set_bit(i, &notifs_mask, pcdev->nr_lines) treats
&notifs_mask as a multi-word bitmap and reads beyond the single
unsigned long when nr_lines > BITS_PER_LONG.

Fix this by moving notifs_mask out of the stack and into struct pse_irq
as a dynamically allocated bitmap. It is sized with
BITS_TO_LONGS(pcdev->nr_lines) words in devm_pse_irq_helper(), so it
is always wide enough regardless of the host word size.

[Jakub]: No upstream driver currently supports >=32 ports.

Signed-off-by: Kory Maincent <kory.maincent@bootlin.com>
Link: https://patch.msgid.link/20260415130300.806152-1-kory.maincent@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Kory Maincent and committed by
Jakub Kicinski
5099807f 0f99e0c3

+9 -4
+9 -4
drivers/net/pse-pd/pse_core.c
··· 1170 1170 struct pse_controller_dev *pcdev; 1171 1171 struct pse_irq_desc desc; 1172 1172 unsigned long *notifs; 1173 + unsigned long *notifs_mask; 1173 1174 }; 1174 1175 1175 1176 /** ··· 1248 1247 static irqreturn_t pse_isr(int irq, void *data) 1249 1248 { 1250 1249 struct pse_controller_dev *pcdev; 1251 - unsigned long notifs_mask = 0; 1252 1250 struct pse_irq_desc *desc; 1253 1251 struct pse_irq *h = data; 1254 1252 int ret, i; ··· 1257 1257 1258 1258 /* Clear notifs mask */ 1259 1259 memset(h->notifs, 0, pcdev->nr_lines * sizeof(*h->notifs)); 1260 + bitmap_zero(h->notifs_mask, pcdev->nr_lines); 1260 1261 mutex_lock(&pcdev->lock); 1261 - ret = desc->map_event(irq, pcdev, h->notifs, &notifs_mask); 1262 - if (ret || !notifs_mask) { 1262 + ret = desc->map_event(irq, pcdev, h->notifs, h->notifs_mask); 1263 + if (ret || bitmap_empty(h->notifs_mask, pcdev->nr_lines)) { 1263 1264 mutex_unlock(&pcdev->lock); 1264 1265 return IRQ_NONE; 1265 1266 } 1266 1267 1267 - for_each_set_bit(i, &notifs_mask, pcdev->nr_lines) { 1268 + for_each_set_bit(i, h->notifs_mask, pcdev->nr_lines) { 1268 1269 unsigned long notifs, rnotifs; 1269 1270 struct pse_ntf ntf = {}; 1270 1271 ··· 1339 1338 h->notifs = devm_kcalloc(dev, pcdev->nr_lines, 1340 1339 sizeof(*h->notifs), GFP_KERNEL); 1341 1340 if (!h->notifs) 1341 + return -ENOMEM; 1342 + 1343 + h->notifs_mask = devm_bitmap_zalloc(dev, pcdev->nr_lines, GFP_KERNEL); 1344 + if (!h->notifs_mask) 1342 1345 return -ENOMEM; 1343 1346 1344 1347 ret = devm_request_threaded_irq(dev, irq, NULL, pse_isr,