aboutsummaryrefslogtreecommitdiffstats
path: root/debian/patches/ubuntu-backport-33-vhost-user-add-error-handling-for-fd-1023.patch
blob: dfad323cea95a58b2d00e682c7b7b609adff6d26 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
Description: backport of dpdk fix for LP: #1566874

Forwarded: n/a (already discussed upstream)
Author: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Last-Update: 2016-06-06

Extended by Christian Ehrhardt <christian.ehrhardt@canonical.com>
Close fd on vserver->listenfd (Part of the upstream discussion)

Original:
From: Patrik Andersson <patrik.r.andersson@ericsson.com>

Protect against DPDK crash when allocation of listen fd >= 1023.
For events on fd:s >1023, the current implementation will trigger
an abort due to access outside of allocated bit mask.

Corrections would include:

  * Match fdset_add() signature in fd_man.c to fd_man.h
  * Handling of return codes from fdset_add()
  * Addition of check of fd number in fdset_add_fd()

The rationale behind the suggested code change is that,
fdset_event_dispatch() could attempt access outside of the FD_SET
bitmask if there is an event on a file descriptor that in turn
looks up a virtio file descriptor with a value > 1023.
Such an attempt will lead to an abort() and a restart of any
vswitch using DPDK.

A discussion topic exist in the ovs-discuss mailing list that can
provide a little more background:

http://openvswitch.org/pipermail/discuss/2016-February/020243.html

Signed-off-by: Patrik Andersson <patrik.r.andersson@ericsson.com>
---
 fd_man.c         |   11 ++++++-----
 vhost-net-user.c |   23 +++++++++++++++++++++--
 2 files changed, 27 insertions(+), 7 deletions(-)

Index: deb_dpdk/lib/librte_vhost/vhost_user/fd_man.c
===================================================================
--- deb_dpdk.orig/lib/librte_vhost/vhost_user/fd_man.c
+++ deb_dpdk/lib/librte_vhost/vhost_user/fd_man.c
@@ -71,20 +71,22 @@ fdset_find_free_slot(struct fdset *pfdse
 	return fdset_find_fd(pfdset, -1);
 }
 
-static void
+static int
 fdset_add_fd(struct fdset  *pfdset, int idx, int fd,
 	fd_cb rcb, fd_cb wcb, void *dat)
 {
 	struct fdentry *pfdentry;
 
-	if (pfdset == NULL || idx >= MAX_FDS)
-		return;
+	if (pfdset == NULL || idx >= MAX_FDS || fd >= FD_SETSIZE)
+		return -1;
 
 	pfdentry = &pfdset->fd[idx];
 	pfdentry->fd = fd;
 	pfdentry->rcb = rcb;
 	pfdentry->wcb = wcb;
 	pfdentry->dat = dat;
+
+	return 0;
 }
 
 /**
@@ -150,12 +152,11 @@ fdset_add(struct fdset *pfdset, int fd,
 
 	/* Find a free slot in the list. */
 	i = fdset_find_free_slot(pfdset);
-	if (i == -1) {
+	if (i == -1 || fdset_add_fd(pfdset, i, fd, rcb, wcb, dat) < 0) {
 		pthread_mutex_unlock(&pfdset->fd_mutex);
 		return -2;
 	}
 
-	fdset_add_fd(pfdset, i, fd, rcb, wcb, dat);
 	pfdset->num++;
 
 	pthread_mutex_unlock(&pfdset->fd_mutex);
Index: deb_dpdk/lib/librte_vhost/vhost_user/vhost-net-user.c
===================================================================
--- deb_dpdk.orig/lib/librte_vhost/vhost_user/vhost-net-user.c
+++ deb_dpdk/lib/librte_vhost/vhost_user/vhost-net-user.c
@@ -257,6 +257,7 @@ vhost_user_add_connection(int fd, struct
 	int vid;
 	size_t size;
 	struct vhost_user_connection *conn;
+	int ret;
 
 	conn = malloc(sizeof(*conn));
 	if (conn == NULL) {
@@ -278,7 +279,15 @@ vhost_user_add_connection(int fd, struct
 
 	conn->vsocket = vsocket;
 	conn->vid = vid;
-	fdset_add(&vhost_user.fdset, fd, vhost_user_msg_handler, NULL, conn);
+	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_msg_handler,
+			NULL, conn);
+	if (ret < 0) {
+		free(conn);
+		close(fd);
+		RTE_LOG(ERR, VHOST_CONFIG,
+			"failed to add fd %d into vhost server fdset\n",
+			fd);
+	}
 }
 
 /* call back when there is new vhost-user connection from client  */
@@ -469,8 +478,14 @@ vhost_user_create_server(struct vhost_us
 		goto err;
 
 	vsocket->listenfd = fd;
-	fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
+	ret = fdset_add(&vhost_user.fdset, fd, vhost_user_server_new_connection,
 		  NULL, vsocket);
+	if (ret < 0) {
+		RTE_LOG(ERR, VHOST_CONFIG,
+			"failed to add listen fd %d to vhost server fdset\n",
+			fd);
+		goto err;
+	}
 
 	return 0;