xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-extended/libtirpc/libtirpc/CVE-2021-46828.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1From 3ee23a0a5a8c2261e788acbee67722fcbecbea28 Mon Sep 17 00:00:00 2001
2From: Hitendra Prajapati <hprajapati@mvista.com>
3Date: Wed, 27 Jul 2022 17:34:21 +0530
4Subject: [PATCH] CVE-2021-46828
5
6Upstream-Status: Backport [http://git.linux-nfs.org/?p=steved/libtirpc.git;a=commit;h=86529758570cef4c73fb9b9c4104fdc510f701ed}
7CVE: CVE-2021-46828
8Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
9---
10 src/svc.c    | 17 +++++++++++++-
11 src/svc_vc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++-
12 2 files changed, 77 insertions(+), 2 deletions(-)
13
14diff --git a/src/svc.c b/src/svc.c
15index 6db164b..3a8709f 100644
16--- a/src/svc.c
17+++ b/src/svc.c
18@@ -57,7 +57,7 @@
19
20 #define max(a, b) (a > b ? a : b)
21
22-static SVCXPRT **__svc_xports;
23+SVCXPRT **__svc_xports;
24 int __svc_maxrec;
25
26 /*
27@@ -194,6 +194,21 @@ __xprt_do_unregister (xprt, dolock)
28     rwlock_unlock (&svc_fd_lock);
29 }
30
31+int
32+svc_open_fds()
33+{
34+	int ix;
35+	int nfds = 0;
36+
37+	rwlock_rdlock (&svc_fd_lock);
38+	for (ix = 0; ix < svc_max_pollfd; ++ix) {
39+		if (svc_pollfd[ix].fd != -1)
40+			nfds++;
41+	}
42+	rwlock_unlock (&svc_fd_lock);
43+	return (nfds);
44+}
45+
46 /*
47  * Add a service program to the callout list.
48  * The dispatch routine will be called when a rpc request for this
49diff --git a/src/svc_vc.c b/src/svc_vc.c
50index f1d9f00..3dc8a75 100644
51--- a/src/svc_vc.c
52+++ b/src/svc_vc.c
53@@ -64,6 +64,8 @@
54
55
56 extern rwlock_t svc_fd_lock;
57+extern SVCXPRT **__svc_xports;
58+extern int svc_open_fds();
59
60 static SVCXPRT *makefd_xprt(int, u_int, u_int);
61 static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
62@@ -82,6 +84,7 @@ static void svc_vc_ops(SVCXPRT *);
63 static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
64 static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
65 				   	     void *in);
66+static int __svc_destroy_idle(int timeout);
67
68 struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
69 	u_int sendsize;
70@@ -313,13 +316,14 @@ done:
71 	return (xprt);
72 }
73
74+
75 /*ARGSUSED*/
76 static bool_t
77 rendezvous_request(xprt, msg)
78 	SVCXPRT *xprt;
79 	struct rpc_msg *msg;
80 {
81-	int sock, flags;
82+	int sock, flags, nfds, cnt;
83 	struct cf_rendezvous *r;
84 	struct cf_conn *cd;
85 	struct sockaddr_storage addr;
86@@ -379,6 +383,16 @@ again:
87
88 	gettimeofday(&cd->last_recv_time, NULL);
89
90+	nfds = svc_open_fds();
91+	if (nfds >= (_rpc_dtablesize() / 5) * 4) {
92+		/* destroy idle connections */
93+		cnt = __svc_destroy_idle(15);
94+		if (cnt == 0) {
95+			/* destroy least active */
96+			__svc_destroy_idle(0);
97+		}
98+	}
99+
100 	return (FALSE); /* there is never an rpc msg to be processed */
101 }
102
103@@ -820,3 +834,49 @@ __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
104 {
105 	return FALSE;
106 }
107+
108+static int
109+__svc_destroy_idle(int timeout)
110+{
111+	int i, ncleaned = 0;
112+	SVCXPRT *xprt, *least_active;
113+	struct timeval tv, tdiff, tmax;
114+	struct cf_conn *cd;
115+
116+	gettimeofday(&tv, NULL);
117+	tmax.tv_sec = tmax.tv_usec = 0;
118+	least_active = NULL;
119+	rwlock_wrlock(&svc_fd_lock);
120+
121+	for (i = 0; i <= svc_max_pollfd; i++) {
122+		if (svc_pollfd[i].fd == -1)
123+			continue;
124+		xprt = __svc_xports[i];
125+		if (xprt == NULL || xprt->xp_ops == NULL ||
126+			xprt->xp_ops->xp_recv != svc_vc_recv)
127+			continue;
128+		cd = (struct cf_conn *)xprt->xp_p1;
129+		if (!cd->nonblock)
130+			continue;
131+		if (timeout == 0) {
132+			timersub(&tv, &cd->last_recv_time, &tdiff);
133+			if (timercmp(&tdiff, &tmax, >)) {
134+				tmax = tdiff;
135+				least_active = xprt;
136+			}
137+			continue;
138+		}
139+		if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
140+			__xprt_unregister_unlocked(xprt);
141+			__svc_vc_dodestroy(xprt);
142+			ncleaned++;
143+		}
144+	}
145+	if (timeout == 0 && least_active != NULL) {
146+		__xprt_unregister_unlocked(least_active);
147+		__svc_vc_dodestroy(least_active);
148+		ncleaned++;
149+	}
150+	rwlock_unlock(&svc_fd_lock);
151+	return (ncleaned);
152+}
153--
1542.25.1
155
156