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