SHA256
1
0
forked from pool/libtirpc

Accepting request 998199 from Base:System

- update to 1.3.3 (bsc#1201680, CVE-2021-46828):
  * Fix DoS vulnerability in libtirpc
  * _rpc_dtablesize: use portable system call
  * libtirpc: Fix use-after-free accessing the error number
  * Fix potential memory leak of parms.r_addr
  * rpcb_clnt.c add mechanism to try v2 protocol first
  * Eliminate deadlocks in connects with an MT environment
  * clnt_dg_freeres() uncleared set active state may deadlock
  * thread safe clnt destruction
  * SUNRPC: mutexed access blacklist_read state variable
  * SUNRPC: MT-safe overhaul of address cache management in rpcb_clnt.c
- drop 0001-Fix-DoS-vulnerability-in-libtirpc.patch (upstream)

OBS-URL: https://build.opensuse.org/request/show/998199
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/libtirpc?expand=0&rev=59
This commit is contained in:
Dominique Leuenberger 2022-08-21 12:10:46 +00:00 committed by Git OBS Bridge
commit aeb89c110a
5 changed files with 21 additions and 186 deletions

View File

@ -1,180 +0,0 @@
From 86529758570cef4c73fb9b9c4104fdc510f701ed Mon Sep 17 00:00:00 2001
From: Dai Ngo <dai.ngo@oracle.com>
Date: Sat, 21 Aug 2021 13:16:23 -0400
Subject: [PATCH] Fix DoS vulnerability in libtirpc
Currently svc_run does not handle poll timeout and rendezvous_request
does not handle EMFILE error returned from accept(2 as it used to.
These two missing functionality were removed by commit b2c9430f46c4.
The effect of not handling poll timeout allows idle TCP conections
to remain ESTABLISHED indefinitely. When the number of connections
reaches the limit of the open file descriptors (ulimit -n) then
accept(2) fails with EMFILE. Since there is no handling of EMFILE
error this causes svc_run() to get in a tight loop calling accept(2).
This resulting in the RPC service of svc_run is being down, it's
no longer able to service any requests.
RPC service rpcbind, statd and mountd are effected by this
problem.
Fix by enhancing rendezvous_request to keep the number of
SVCXPRT conections to 4/5 of the size of the file descriptor
table. When this thresold is reached, it destroys the idle
TCP connections or destroys the least active connection if
no idle connnction was found.
Fixes: 44bf15b8 rpcbind: don't use obsolete svc_fdset interface of libtirpc
Signed-off-by: dai.ngo@oracle.com
Signed-off-by: Steve Dickson <steved@redhat.com>
[ pvorel: removed INSTALL file change as not related ]
Signed-off-by: Petr Vorel <pvorel@suse.cz>
[ upstream status: 8652975 ("Fix DoS vulnerability in libtirpc") ]
---
src/svc.c | 17 ++-
src/svc_vc.c | 62 ++++++++-
3 files changed, 78 insertions(+), 372 deletions(-)
mode change 100644 => 120000 INSTALL
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 f1d9f00..3dc8a75 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;
@@ -313,13 +316,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;
@@ -379,6 +383,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 */
}
@@ -820,3 +834,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.33.0

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e24eb88b8ce7db3b7ca6eb80115dd1284abc5ec32a8deccfed2224fc2532b9fd
size 513151

BIN
libtirpc-1.3.3.tar.bz2 (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,3 +1,19 @@
-------------------------------------------------------------------
Fri Aug 19 15:27:29 UTC 2022 - Dirk Müller <dmueller@suse.com>
- update to 1.3.3 (bsc#1201680, CVE-2021-46828):
* Fix DoS vulnerability in libtirpc
* _rpc_dtablesize: use portable system call
* libtirpc: Fix use-after-free accessing the error number
* Fix potential memory leak of parms.r_addr
* rpcb_clnt.c add mechanism to try v2 protocol first
* Eliminate deadlocks in connects with an MT environment
* clnt_dg_freeres() uncleared set active state may deadlock
* thread safe clnt destruction
* SUNRPC: mutexed access blacklist_read state variable
* SUNRPC: MT-safe overhaul of address cache management in rpcb_clnt.c
- drop 0001-Fix-DoS-vulnerability-in-libtirpc.patch (upstream)
-------------------------------------------------------------------
Wed Sep 15 05:35:58 UTC 2021 - Petr Vorel <pvorel@suse.cz>

View File

@ -1,7 +1,7 @@
#
# spec file for package libtirpc
#
# Copyright (c) 2021 SUSE LLC
# Copyright (c) 2022 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -18,7 +18,7 @@
%define debug_package_requires libtirpc3 = %{version}-%{release}
Name: libtirpc
Version: 1.3.2
Version: 1.3.3
Release: 0
Summary: Transport Independent RPC Library
License: BSD-3-Clause
@ -26,7 +26,6 @@ Group: Development/Libraries/C and C++
URL: https://sourceforge.net/projects/libtirpc/
Source: https://download.sourceforge.net/libtirpc/%{name}-%{version}.tar.bz2
Source1: baselibs.conf
Patch1: 0001-Fix-DoS-vulnerability-in-libtirpc.patch
BuildRequires: pkgconfig
BuildRequires: pkgconfig(krb5)