Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 76191 - rpc.statd does not respect the "-o" option
Summary: rpc.statd does not respect the "-o" option
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: x86 Linux
: High major (vote)
Assignee: Network Filesystems
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-12-30 17:39 UTC by Mike Nemeth
Modified: 2006-10-05 19:07 UTC (History)
0 users

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mike Nemeth 2004-12-30 17:39:32 UTC
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;
    ...
Comment 1 SpanKY gentoo-dev 2004-12-30 22:25:35 UTC
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
Comment 2 Robin Johnson archtester Gentoo Infrastructure gentoo-dev Security 2006-10-05 17:53:10 UTC
please test with nfs-utils-1.0.10 and reopen if needed with answers to spanky's question.
Comment 3 SpanKY gentoo-dev 2006-10-05 18:59:57 UTC
still broken
Comment 4 SpanKY gentoo-dev 2006-10-05 19:07:57 UTC
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;