Control: forwarded -1 
https://sourceforge.net/p/libtirpc/mailman/message/36184164/

Hi!

On Mon, 2011-08-22 at 04:32:58 +0100, Ben Hutchings wrote:
> This depends on eglibc being patched as in #638810.

TBH, I find having to use an additional registry of ports a bit
annoying, when /etc/services is already there. In any case rpc.statd
from upstream nfs-utils already honors /etc/services, so here's a
patch doing something similar for libtirpc users. Which I've also
submitted upstream because at least this can be supported everywhere,
compared with the local patch for the blacklist.

Ideally to have all implementations be consistent, libtirpc would
switch to the libc bindresvport() implementation, and that one would
honor /etc/services. Maybe glibc upstream is now more amenable to such
change. :/

Attached the patch we are using locally.

Thanks,
Guillem
From 92e293bdf1b940cfc6deb8a5475eaddb24612140 Mon Sep 17 00:00:00 2001
From: Guillem Jover <gjo...@sipwise.com>
Date: Fri, 5 Jan 2018 14:33:06 +0100
Subject: [PATCH] Do not bind to reserved ports registered in /etc/services

When using the bindresvport() function a privileged port will be looked
for and bound to a socket. The problem is that any service using a static
privileged port registered in the /etc/services file, can get its port
taken over by libtirpc users, making the other service fail to start.

Starting the other service before libtircp users is not an option as
this does not cover restart situations, for example during package
upgrades or HA switchovers and similar.

In addition honoring the /etc/services registry is already done for
example by rpc.statd, so it seems obvious to make libtirpc follow this
same pattern too.

Signed-off-by: Guillem Jover <gjo...@sipwise.com>
---
 src/bindresvport.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/src/bindresvport.c b/src/bindresvport.c
index 2d8f2bc..98e5f40 100644
--- a/src/bindresvport.c
+++ b/src/bindresvport.c
@@ -40,6 +40,7 @@
 #include <netinet/in.h>
 
 #include <errno.h>
+#include <netdb.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -73,12 +74,15 @@ bindresvport_sa(sd, sa)
         int sd;
         struct sockaddr *sa;
 {
-        int res, af;
+        int res, af, so_proto;
+        socklen_t so_proto_len;
         struct sockaddr_storage myaddr;
 	struct sockaddr_in *sin;
 #ifdef INET6
 	struct sockaddr_in6 *sin6;
 #endif
+	struct servent *se;
+	const char *se_proto;
 	u_int16_t *portp;
 	static u_int16_t port;
 	static short startport = STARTPORT;
@@ -125,6 +129,25 @@ bindresvport_sa(sd, sa)
         }
         sa->sa_family = af;
 
+        so_proto_len = sizeof(so_proto);
+        if (getsockopt(sd, SOL_SOCKET, SO_PROTOCOL, &so_proto, &so_proto_len) == -1) {
+                mutex_unlock(&port_lock);
+                return -1;      /* errno is correctly set */
+        }
+        switch (so_proto) {
+        case IPPROTO_UDP:
+        case IPPROTO_UDPLITE:
+                se_proto = "udp";
+                break;
+        case IPPROTO_TCP:
+                se_proto = "tcp";
+                break;
+        default:
+                errno = ENOPROTOOPT;
+                mutex_unlock(&port_lock);
+                return -1;
+        }
+
         if (port == 0) {
                 port = (getpid() % NPORTS) + STARTPORT;
         }
@@ -135,6 +158,9 @@ bindresvport_sa(sd, sa)
                 *portp = htons(port++);
                  if (port > endport) 
                         port = startport;
+                se = getservbyport(*portp, se_proto);
+                if (se != NULL)
+                        continue;
                 res = bind(sd, sa, salen);
 		if (res >= 0 || errno != EADDRINUSE)
 	                break;
-- 
2.15.1

Reply via email to