aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-extended/libtirpc/libtirpc/CVE-2021-46828.patch
blob: c78e7ef4d5ad108cb6c04263835413bbbee98d29 (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
From 48309e7cb230fc539c3edab0b3363f8ce973194f Mon Sep 17 00:00:00 2001
From: Hitendra Prajapati <hprajapati@mvista.com>
Date: Thu, 28 Jul 2022 09:11:04 +0530
Subject: [PATCH] CVE-2021-46828

Upstream-Status: Backport [http://git.linux-nfs.org/?p=steved/libtirpc.git;a=commit;h=86529758570cef4c73fb9b9c4104fdc510f701ed}
CVE: CVE-2021-46828
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
 src/svc.c    | 17 +++++++++++++-
 src/svc_vc.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 77 insertions(+), 2 deletions(-)

diff --git a/src/svc.c b/src/svc.c
index 6db164b..3a8709f 100644
--- a/src/svc.c
+++ b/src/svc.c
@@ -57,7 +57,7 @@
 
 #define max(a, b) (a > b ? a : b)
 
-static SVCXPRT **__svc_xports;
+SVCXPRT **__svc_xports;
 int __svc_maxrec;
 
 /*
@@ -194,6 +194,21 @@ __xprt_do_unregister (xprt, dolock)
     rwlock_unlock (&svc_fd_lock);
 }
 
+int
+svc_open_fds()
+{
+	int ix;
+	int nfds = 0;
+
+	rwlock_rdlock (&svc_fd_lock);
+	for (ix = 0; ix < svc_max_pollfd; ++ix) {
+		if (svc_pollfd[ix].fd != -1)
+			nfds++;
+	}
+	rwlock_unlock (&svc_fd_lock);
+	return (nfds);
+}
+
 /*
  * Add a service program to the callout list.
  * The dispatch routine will be called when a rpc request for this
diff --git a/src/svc_vc.c b/src/svc_vc.c
index c23cd36..1729963 100644
--- a/src/svc_vc.c
+++ b/src/svc_vc.c
@@ -64,6 +64,8 @@
 
 
 extern rwlock_t svc_fd_lock;
+extern SVCXPRT **__svc_xports;
+extern int svc_open_fds();
 
 static SVCXPRT *makefd_xprt(int, u_int, u_int);
 static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
@@ -82,6 +84,7 @@ static void svc_vc_ops(SVCXPRT *);
 static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
 static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
 				   	     void *in);
+static int __svc_destroy_idle(int timeout);
 
 struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
 	u_int sendsize;
@@ -312,13 +315,14 @@ done:
 	return (xprt);
 }
 
+
 /*ARGSUSED*/
 static bool_t
 rendezvous_request(xprt, msg)
 	SVCXPRT *xprt;
 	struct rpc_msg *msg;
 {
-	int sock, flags;
+	int sock, flags, nfds, cnt;
 	struct cf_rendezvous *r;
 	struct cf_conn *cd;
 	struct sockaddr_storage addr;
@@ -378,6 +382,16 @@ again:
 
 	gettimeofday(&cd->last_recv_time, NULL);
 
+	nfds = svc_open_fds();
+	if (nfds >= (_rpc_dtablesize() / 5) * 4) {
+		/* destroy idle connections */
+		cnt = __svc_destroy_idle(15);
+		if (cnt == 0) {
+			/* destroy least active */
+			__svc_destroy_idle(0);
+		}
+	}
+
 	return (FALSE); /* there is never an rpc msg to be processed */
 }
 
@@ -819,3 +833,49 @@ __svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
 {
 	return FALSE;
 }
+
+static int
+__svc_destroy_idle(int timeout)
+{
+	int i, ncleaned = 0;
+	SVCXPRT *xprt, *least_active;
+	struct timeval tv, tdiff, tmax;
+	struct cf_conn *cd;
+
+	gettimeofday(&tv, NULL);
+	tmax.tv_sec = tmax.tv_usec = 0;
+	least_active = NULL;
+	rwlock_wrlock(&svc_fd_lock);
+
+	for (i = 0; i <= svc_max_pollfd; i++) {
+		if (svc_pollfd[i].fd == -1)
+			continue;
+		xprt = __svc_xports[i];
+		if (xprt == NULL || xprt->xp_ops == NULL ||
+			xprt->xp_ops->xp_recv != svc_vc_recv)
+			continue;
+		cd = (struct cf_conn *)xprt->xp_p1;
+		if (!cd->nonblock)
+			continue;
+		if (timeout == 0) {
+			timersub(&tv, &cd->last_recv_time, &tdiff);
+			if (timercmp(&tdiff, &tmax, >)) {
+				tmax = tdiff;
+				least_active = xprt;
+			}
+			continue;
+		}
+		if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
+			__xprt_unregister_unlocked(xprt);
+			__svc_vc_dodestroy(xprt);
+			ncleaned++;
+		}
+	}
+	if (timeout == 0 && least_active != NULL) {
+		__xprt_unregister_unlocked(least_active);
+		__svc_vc_dodestroy(least_active);
+		ncleaned++;
+	}
+	rwlock_unlock(&svc_fd_lock);
+	return (ncleaned);
+}
-- 
2.25.1