forked from mirrors/linux
		
	vhost: fix total length when packets are too short
When mergeable buffers are disabled, and the incoming packet is too large for the rx buffer, get_rx_bufs returns success. This was intentional in order for make recvmsg truncate the packet and then handle_rx would detect err != sock_len and drop it. Unfortunately we pass the original sock_len to recvmsg - which means we use parts of iov not fully validated. Fix this up by detecting this overrun and doing packet drop immediately. CVE-2014-0077 Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									05efa8c943
								
							
						
					
					
						commit
						d8316f3991
					
				
					 1 changed files with 14 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -532,6 +532,12 @@ static int get_rx_bufs(struct vhost_virtqueue *vq,
 | 
			
		|||
	*iovcount = seg;
 | 
			
		||||
	if (unlikely(log))
 | 
			
		||||
		*log_num = nlogs;
 | 
			
		||||
 | 
			
		||||
	/* Detect overrun */
 | 
			
		||||
	if (unlikely(datalen > 0)) {
 | 
			
		||||
		r = UIO_MAXIOV + 1;
 | 
			
		||||
		goto err;
 | 
			
		||||
	}
 | 
			
		||||
	return headcount;
 | 
			
		||||
err:
 | 
			
		||||
	vhost_discard_vq_desc(vq, headcount);
 | 
			
		||||
| 
						 | 
				
			
			@ -587,6 +593,14 @@ static void handle_rx(struct vhost_net *net)
 | 
			
		|||
		/* On error, stop handling until the next kick. */
 | 
			
		||||
		if (unlikely(headcount < 0))
 | 
			
		||||
			break;
 | 
			
		||||
		/* On overrun, truncate and discard */
 | 
			
		||||
		if (unlikely(headcount > UIO_MAXIOV)) {
 | 
			
		||||
			msg.msg_iovlen = 1;
 | 
			
		||||
			err = sock->ops->recvmsg(NULL, sock, &msg,
 | 
			
		||||
						 1, MSG_DONTWAIT | MSG_TRUNC);
 | 
			
		||||
			pr_debug("Discarded rx packet: len %zd\n", sock_len);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		/* OK, now we need to know about added descriptors. */
 | 
			
		||||
		if (!headcount) {
 | 
			
		||||
			if (unlikely(vhost_enable_notify(&net->dev, vq))) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue