forked from mirrors/linux
		
	ptr_ring: try vmalloc() when kmalloc() fails
This patch switch to use kvmalloc_array() for using a vmalloc()
fallback to help in case kmalloc() fails.
Reported-by: syzbot+e4d4f9ddd4295539735d@syzkaller.appspotmail.com
Fixes: 2e0ab8ca83 ("ptr_ring: array based FIFO for pointers")
Signed-off-by: Jason Wang <jasowang@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									6e6e41c311
								
							
						
					
					
						commit
						0bf7800f17
					
				
					 1 changed files with 8 additions and 5 deletions
				
			
		|  | @ -464,11 +464,14 @@ static inline int ptr_ring_consume_batched_bh(struct ptr_ring *r, | ||||||
| 	__PTR_RING_PEEK_CALL_v; \ | 	__PTR_RING_PEEK_CALL_v; \ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
|  | /* Not all gfp_t flags (besides GFP_KERNEL) are allowed. See
 | ||||||
|  |  * documentation for vmalloc for which of them are legal. | ||||||
|  |  */ | ||||||
| static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp) | static inline void **__ptr_ring_init_queue_alloc(unsigned int size, gfp_t gfp) | ||||||
| { | { | ||||||
| 	if (size * sizeof(void *) > KMALLOC_MAX_SIZE) | 	if (size * sizeof(void *) > KMALLOC_MAX_SIZE) | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	return kcalloc(size, sizeof(void *), gfp); | 	return kvmalloc_array(size, sizeof(void *), gfp | __GFP_ZERO); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) | static inline void __ptr_ring_set_size(struct ptr_ring *r, int size) | ||||||
|  | @ -603,7 +606,7 @@ static inline int ptr_ring_resize(struct ptr_ring *r, int size, gfp_t gfp, | ||||||
| 	spin_unlock(&(r)->producer_lock); | 	spin_unlock(&(r)->producer_lock); | ||||||
| 	spin_unlock_irqrestore(&(r)->consumer_lock, flags); | 	spin_unlock_irqrestore(&(r)->consumer_lock, flags); | ||||||
| 
 | 
 | ||||||
| 	kfree(old); | 	kvfree(old); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -643,7 +646,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < nrings; ++i) | 	for (i = 0; i < nrings; ++i) | ||||||
| 		kfree(queues[i]); | 		kvfree(queues[i]); | ||||||
| 
 | 
 | ||||||
| 	kfree(queues); | 	kfree(queues); | ||||||
| 
 | 
 | ||||||
|  | @ -651,7 +654,7 @@ static inline int ptr_ring_resize_multiple(struct ptr_ring **rings, | ||||||
| 
 | 
 | ||||||
| nomem: | nomem: | ||||||
| 	while (--i >= 0) | 	while (--i >= 0) | ||||||
| 		kfree(queues[i]); | 		kvfree(queues[i]); | ||||||
| 
 | 
 | ||||||
| 	kfree(queues); | 	kfree(queues); | ||||||
| 
 | 
 | ||||||
|  | @ -666,7 +669,7 @@ static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *)) | ||||||
| 	if (destroy) | 	if (destroy) | ||||||
| 		while ((ptr = ptr_ring_consume(r))) | 		while ((ptr = ptr_ring_consume(r))) | ||||||
| 			destroy(ptr); | 			destroy(ptr); | ||||||
| 	kfree(r->queue); | 	kvfree(r->queue); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #endif /* _LINUX_PTR_RING_H  */ | #endif /* _LINUX_PTR_RING_H  */ | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Jason Wang
						Jason Wang