mountd: fix --manage-gids hang due to int/uint bug
authorSteve Dickson <steved@redhat.com>
Mon, 8 Mar 2010 16:22:46 +0000 (11:22 -0500)
committerSteve Dickson <steved@redhat.com>
Mon, 8 Mar 2010 16:22:46 +0000 (11:22 -0500)
A uid or gid should be represented as unsigned, not signed.

The conversion to signed here could cause a hang on access by an unknown
user to a server running mountd with --manage-gids; such a user is
likely to be mapped to 232-1, which may be converted to 231-1 when
represented as an int, resulting in a downcall for uid 231-1, hence the
original rpc hanging forever waiting for a cache downcall for 232-1.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Steve Dickson <steved@redhat.com>
support/nfs/cacheio.c
utils/mountd/cache.c

index bdf5d84..0587ecb 100644 (file)
@@ -148,6 +148,11 @@ void qword_printint(FILE *f, int num)
        fprintf(f, "%d ", num);
 }
 
+void qword_printuint(FILE *f, unsigned int num)
+{
+       fprintf(f, "%u ", num);
+}
+
 int qword_eol(FILE *f)
 {
        int err;
@@ -236,6 +241,20 @@ int qword_get_int(char **bpp, int *anint)
        return 0;
 }
 
+int qword_get_uint(char *bpp, unsigned int *anint)
+{
+       char buf[50];
+       char *ep;
+       unsigned int rv;
+       int len = qword_get(bpp, buf, 50);
+       if (len < 0) return -1;
+       if (len ==0) return -1;
+       rv = strtoul(buf, &ep, 0);
+       if (*ep) return -1;
+       *anint = rv;
+       return 0;
+}
+
 #define READLINE_BUFFER_INCREMENT 2048
 
 int readline(int fd, char **buf, int *lenp)
index d63e10a..b6c148f 100644 (file)
@@ -125,7 +125,7 @@ void auth_unix_gid(FILE *f)
         * reply is
         *  uid expiry count list of group ids
         */
-       int uid;
+       uid_t uid;
        struct passwd *pw;
        gid_t glist[100], *groups = glist;
        int ngroups = 100;
@@ -136,7 +136,7 @@ void auth_unix_gid(FILE *f)
                return;
 
        cp = lbuf;
-       if (qword_get_int(&cp, &uid) != 0)
+       if (qword_get_uint(&cp, &uid) != 0)
                return;
 
        pw = getpwuid(uid);
@@ -153,14 +153,14 @@ void auth_unix_gid(FILE *f)
                                                  groups, &ngroups);
                }
        }
-       qword_printint(f, uid);
-       qword_printint(f, time(0)+30*60);
+       qword_printuint(f, uid);
+       qword_printuint(f, time(0)+30*60);
        if (rv >= 0) {
-               qword_printint(f, ngroups);
+               qword_printuint(f, ngroups);
                for (i=0; i<ngroups; i++)
-                       qword_printint(f, groups[i]);
+                       qword_printuint(f, groups[i]);
        } else
-               qword_printint(f, 0);
+               qword_printuint(f, 0);
        qword_eol(f);
 
        if (groups != glist)