rpc.statd in the package nfs-utils does not use the specified "-o" command line argument if the port so specified is > 1023. Instead it uses a randomly chosen port < 1024. If a user specified a port greater than 1023 using "-o", and firewalled that port, his/her system might still be open to compromise. I have contacted all four authors twice since September, and have only received a single "got your email" response from one of them (juphoff@nrao.edu). The problem is in both the 1.0.6 and the new 1.0.7 versions of nfs-utils. Reproducible: Always Steps to Reproduce: 1. specify a "-o" port for rpc.statd to use in the file /etc/conf.d/nfs. the port should be > 1024 (eg. RPCSTATDOPTS="-p 32765 -o 32766"). 2. type "/etc/init.d/nfs restart". 3. type "lsof | grep statd". Actual Results: ... rpc.statd 13505 nobody 4u IPv4 3824945 UDP *:32765 rpc.statd 13505 nobody 5u IPv4 3824938 UDP *:961 rpc.statd 13505 nobody 6u IPv4 3824948 TCP *:32765 (LISTEN) Expected Results: ... rpc.statd 11359 nobody 4u IPv4 3478786 UDP *:32765 rpc.statd 11359 nobody 5u IPv4 3478779 UDP *:32766 rpc.statd 11359 nobody 6u IPv4 3478789 TCP *:32765 (LISTEN) The problem is in nfs-utils/utils/statd/rmtcall.c The code in the function statd_get_socket() should be changed so as not to call bindresvport() if the port > 1024. bindresvport() will _always_ return a port < 1024, unless there are no available privileged ports left at all (in which case it returns < 0 to indicate an error). Either an error should be returned, or another function, such as bind(), should be called to return an unprivileged port. The following patch to nfs-utils/utils/statd/rmtcall.c works for me: statd_get_socket(int port) { ... memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; - sin.sin_port = port; - - if (bindresvport(sockfd, &sin) < 0) { - dprintf(N_WARNING, "process_hosts: can't bind to reserved port\n"); - } + sin.sin_port = htons(port); + + if (port > 1024) { + if (bind(sockfd, &sin, sizeof(struct sockaddr_in)) < 0) { + dprintf(N_WARNING, "process_hosts: can't bind to unreserved port\n"); + } + } else { + if (bindresvport(sockfd, &sin) < 0) { + dprintf(N_WARNING, "process_hosts: can't bind to reserved port\n"); + } + } return sockfd; ...
unless there's some known exploit in statd, i dont see how this could lead to system compromise, especially since we pass '--enable-secure-statd' to the nfs configure script
please test with nfs-utils-1.0.10 and reopen if needed with answers to spanky's question.
still broken
i just looked through the code and it appears to handle this properly now: if (port != 0) { sin.sin_port = htons(port); if (bind(sockfd, &sin, sizeof(sin)) == 0) goto out_success; note(N_CRIT, "statd: failed to bind to outgoing port, %d\n" " falling back on randomly chosen port\n", port); } if (bindresvport(sockfd, &sin) < 0) { dprintf(N_WARNING, "process_hosts: can't bind to reserved port\n"); } out_success: return sockfd;