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;
 | 
						*iovcount = seg;
 | 
				
			||||||
	if (unlikely(log))
 | 
						if (unlikely(log))
 | 
				
			||||||
		*log_num = nlogs;
 | 
							*log_num = nlogs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Detect overrun */
 | 
				
			||||||
 | 
						if (unlikely(datalen > 0)) {
 | 
				
			||||||
 | 
							r = UIO_MAXIOV + 1;
 | 
				
			||||||
 | 
							goto err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	return headcount;
 | 
						return headcount;
 | 
				
			||||||
err:
 | 
					err:
 | 
				
			||||||
	vhost_discard_vq_desc(vq, headcount);
 | 
						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. */
 | 
							/* On error, stop handling until the next kick. */
 | 
				
			||||||
		if (unlikely(headcount < 0))
 | 
							if (unlikely(headcount < 0))
 | 
				
			||||||
			break;
 | 
								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. */
 | 
							/* OK, now we need to know about added descriptors. */
 | 
				
			||||||
		if (!headcount) {
 | 
							if (!headcount) {
 | 
				
			||||||
			if (unlikely(vhost_enable_notify(&net->dev, vq))) {
 | 
								if (unlikely(vhost_enable_notify(&net->dev, vq))) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue