Be more cautious about use for privilege ports (<1024).
authorNeil Brown <neilb@suse.de>
Mon, 16 Apr 2007 01:15:40 +0000 (11:15 +1000)
committerNeil Brown <neilb@suse.de>
Mon, 16 Apr 2007 01:15:40 +0000 (11:15 +1000)
Ports < 1024 are a scarce resource and should not be used
carelessly.  Technically they should be not used at all without
registration with IANA, but sometimes we need them despite that.

So: for the socket that RPC services listen on, don't use a <1024 port
by default.  There is no need.

For sockets that we send messages on, that are long-lived, and that might
need to appear 'privileged', avoid using a number that is registered in
/etc/services if possible.

support/nfs/svc_socket.c
utils/statd/rmtcall.c
utils/statd/sm-notify.c

index 6799d16..f44217a 100644 (file)
@@ -101,8 +101,6 @@ svc_socket (u_long number, int type, int protocol, int reuse)
     }
   else
     {
-      if (bindresvport (sock, &addr))
-       {
          addr.sin_port = 0;
          if (bind (sock, (struct sockaddr *) &addr, len) < 0)
            {
@@ -110,7 +108,6 @@ svc_socket (u_long number, int type, int protocol, int reuse)
              (void) __close (sock);
              sock = -1;
            }
-       }
     }
 
   if (sock >= 0)
index 816a6f3..eb1919a 100644 (file)
@@ -62,25 +62,37 @@ int
 statd_get_socket(void)
 {
        struct sockaddr_in      sin;
+       struct servent *se;
+       int loopcnt = 100;
 
        if (sockfd >= 0)
                return sockfd;
 
-       if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
-               note(N_CRIT, "Can't create socket: %m");
-               return -1;
-       }
+       while (loopcnt-- > 0) {
 
-       FD_SET(sockfd, &SVC_FDSET);
+               if (sockfd >= 0) close(sockfd);
 
-       memset(&sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = INADDR_ANY;
+               if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+                       note(N_CRIT, "Can't create socket: %m");
+                       return -1;
+               }
 
-       if (bindresvport(sockfd, &sin) < 0) {
-               dprintf(N_WARNING,
-                       "process_hosts: can't bind to reserved port\n");
+
+               memset(&sin, 0, sizeof(sin));
+               sin.sin_family = AF_INET;
+               sin.sin_addr.s_addr = INADDR_ANY;
+
+               if (bindresvport(sockfd, &sin) < 0) {
+                       dprintf(N_WARNING,
+                               "process_hosts: can't bind to reserved port\n");
+                       break;
+               }
+               se = getservbyport(sin.sin_port, "udp");
+               if (se == NULL)
+                       break;
+               /* rather not use that port, try again */
        }
+       FD_SET(sockfd, &SVC_FDSET);
        return sockfd;
 }
 
index bb6c2ef..1059a88 100644 (file)
@@ -215,7 +215,9 @@ notify(void)
        nsm_address local_addr;
        time_t  failtime = 0;
        int     sock = -1;
+       int retry_cnt = 0;
 
+ retry:
        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (sock < 0) {
                perror("socket");
@@ -248,7 +250,15 @@ notify(void)
                        exit(1);
                }
        } else {
+               struct servent *se;
                (void) bindresvport(sock, (struct sockaddr_in *) &local_addr);
+               /* try to avoid known ports */
+               se = getservbyport(local_addr.sin_port, "udp");
+               if (se && retry_cnt < 100) {
+                       retry_cnt++;
+                       close(sock);
+                       goto retry;
+               }
        }
 
        if (opt_max_retry)