As found by syzkaller, malicious users can set whatever tx_queue_len on a tun device and eventually crash the kernel. Lets remove the ALIGN(XXX, SMP_CACHE_BYTES) thing since a small ring buffer is not fast anyway.
Showing the changes to include/linux (2 of 2 files). Show all
Unified · Split
| @@ -436,9 +436,9 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r, · 435 unmodified lines | ||
| 436 | 436 | __PTR_RING_PEEK_CALL_v; \ |
| 437 | 437 | }) |
| 438 | 438 | |
| 439 | −static inline void **__ptr_ring_init_queue_alloc(int size, gfp_t gfp) | |
| 439 | +static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp) | |
| 440 | 440 | { |
| 441 | − return kzalloc(ALIGN(size * sizeof(void *), SMP_CACHE_BYTES), gfp); | |
| 441 | + return kcalloc(size, sizeof(void *), gfp); | |
| 442 | 442 | } |
| 443 | 443 | |
| 444 | 444 | static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) |
| @@ -582,7 +582,8 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, · 137 unmodified lines | ||
| 582 | 582 | * In particular if you consume ring in interrupt or BH context, you must |
| 583 | 583 | * disable interrupts/BH when doing so. |
| 584 | 584 | */ |
| 585 | −static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, | |
| 585 | +static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, | |
| 586 | + unsigned int nrings, | |
| 586 | 587 | int size, |
| 587 | 588 | gfp_t gfp, void (*destroy)(void *)) |
| 588 | 589 | { |
| @@ -590,7 +591,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, int nrings, · 1 unmodified line | ||
| 590 | 591 | void ***queues; |
| 591 | 592 | int i; |
| 592 | 593 | |
| 593 | − queues = kmalloc(nrings * sizeof *queues, gfp); | |
| 594 | + queues = kmalloc_array(nrings, sizeof(*queues), gfp); | |
| 594 | 595 | if (!queues) |
| 595 | 596 | goto noqueues; |
| 596 | 597 | |
| @@ -193,7 +193,8 @@ static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp) · 192 unmodified lines | ||
| 193 | 193 | } |
| 194 | 194 | |
| 195 | 195 | static inline int skb_array_resize_multiple(struct skb_array **rings, |
| 196 | − int nrings, int size, gfp_t gfp) | |
| 196 | + int nrings, unsigned int size, | |
| 197 | + gfp_t gfp) | |
| 197 | 198 | { |
| 198 | 199 | BUILD_BUG_ON(offsetof(struct skb_array, ring)); |
| 199 | 200 | return ptr_ring_resize_multiple((struct ptr_ring **)rings, |