Possible issue with rpc.idmapd and NFSv4.
Kevin Coffman
kwc at citi.umich.edu
Thu Dec 13 12:28:02 EST 2007
On Dec 13, 2007 12:10 PM, J. Bruce Fields <bfields at fieldses.org> wrote:
> On Thu, Dec 13, 2007 at 12:05:18PM -0500, Nathan Patwardhan wrote:
> > On Dec 12, 2007 8:06 PM, Nathan Patwardhan <noopy.org at gmail.com> wrote:
> > > On Dec 12, 2007 7:45 PM, Nathan Patwardhan <noopy.org at gmail.com> wrote:
> > > > > So you've determined that nfs4_gid_to_name is returning non-zero when
> > > > > given 600 as the gid? Then the bug is probably in libnfsidmap.
> > >
> > > b is correct. The issue is in libnfsidmap. I installed
> > > libnfsidmap-0.20 on our dev box just for kicks and the group issue
> > > seems to have gone away.
> >
> > I looked into the issue a little bit more last night and this morning.
> > The problem seems specific to nss.c and appears to exist in
> > libnfsidmap-0.12 through libnfsidmap-0.19 (or thereabouts).
> >
> > Specifically, there's a syconf(_SC_GETGR_R_SIZE_MAX) call in nss.c
> > that results in a buffer that's never resize if ERANGE.
>
> That sounds exactly right. Un, in fact, here's where that was found
> before:
>
> http://linux-nfs.org/pipermail/nfsv4/2007-April/005924.html
>
> but without the attached patch. It might also be possible to pull the
> same patch out of CVS.
>
> > I've written a patch for libnfsidmap-0.12 against libnfsidmap-0.20
> > that seems to correct this issue, but at this point maybe such a patch
> > is useless since libnfsidmap-0.12 is rather out of date.
>
> > Please advise.
>
> We don't maintain separate branches for older versions, so it's up to
> the distributor to either apply this patch or upgrade to 0.20.
>
> --b.
There were a couple of significant changes between 0.12 and 0.20.
Here is the cvs diff of them. I don't know if this would apply
cleanly to 0.12. (I can send as attachment if mailer destroys it.)
===================================================================
RCS file: /cvs/nfsv4/libnfsidmap/nss.c,v
retrieving revision 1.6
retrieving revision 1.10
diff -u -r1.6 -r1.10
--- nss.c 24 Feb 2006 14:29:27 -0000 1.6
+++ nss.c 5 Feb 2007 16:25:00 -0000 1.10
@@ -99,16 +99,25 @@
struct group grbuf;
char *buf;
size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
- int err = -ENOMEM;
+ int err;
- buf = malloc(buflen);
- if (!buf)
- goto out;
if (domain == NULL)
domain = get_default_domain();
- err = -getgrgid_r(gid, &grbuf, buf, buflen, &gr);
- if (gr == NULL)
- err = -ENOENT;
+
+ do {
+ err = -ENOMEM;
+ buf = malloc(buflen);
+ if (!buf)
+ goto out;
+ err = -getgrgid_r(gid, &grbuf, buf, buflen, &gr);
+ if (gr == NULL && !err)
+ err = -ENOENT;
+ if (err == -ERANGE) {
+ buflen *= 2;
+ free(buf);
+ }
+ } while (err == -ERANGE);
+
if (err)
goto out_buf;
err = write_name(name, gr->gr_name, domain, len);
@@ -127,11 +136,16 @@
int len;
c = strchr(name, '@');
- if (!c)
+ if (c == NULL && domain != NULL)
goto out;
- if (domain && strcmp(c + 1, domain) != 0)
- goto out;
- len = c - name;
+ if (c == NULL && domain == NULL) {
+ len = strlen(name) + 1;
+ } else {
+ if (domain && strcmp(c + 1, domain) != 0)
+ goto out;
+ len = c - name;
+ }
+
l = malloc(len + 1);
if (l == NULL)
goto out;
@@ -160,21 +174,27 @@
err = EINVAL;
localname = strip_domain(name, domain);
+ IDMAP_LOG(4, ("nss_getpwnam: name '%s' domain '%s': "
+ "resulting localname '%s'\n", name, domain, localname));
if (localname == NULL) {
IDMAP_LOG(0, ("nss_getpwnam: name '%s' does not map "
- "into domain '%s'\n", name, domain));
+ "into domain '%s'\n", name,
+ domain ? domain : "<not-provided>"));
goto err_free_buf;
}
err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw);
+ if (pw == NULL && domain != NULL)
+ IDMAP_LOG(0,
+ ("nss_getpwnam: name '%s' not found in domain '%s'\n",
+ localname, domain));
free(localname);
- if (err == 0) {
+ if (err == 0 && pw != NULL) {
*err_p = 0;
- return &buf->pwbuf;
+ return pw;
+ } else if (err == 0 && pw == NULL) {
+ err = ENOENT;
}
- IDMAP_LOG(0,
- ("nss_getpwnam: name '%s' not found in domain '%s'\n",
- localname, domain));
err_free_buf:
free(buf);
@@ -187,7 +207,7 @@
{
struct passwd *pw = NULL;
char *domain;
- int err = -EINVAL;
+ int err = -ENOENT;
domain = get_default_domain();
pw = nss_getpwnam(name, domain, &err);
@@ -195,6 +215,7 @@
goto out;
*uid = pw->pw_uid;
free(pw);
+ err = 0;
out:
return err;
}
@@ -205,26 +226,34 @@
struct group grbuf;
char *buf, *localname, *domain;
size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX);
- int err = -ENOMEM;
+ int err = -EINVAL;
- buf = malloc(buflen);
- if (!buf)
- goto out;
- err = -EINVAL;
domain = get_default_domain();
localname = strip_domain(name, domain);
if (!localname)
- goto out_buf;
- err = -getgrnam_r(localname, &grbuf, buf, buflen, &gr);
- if (gr == NULL)
- err = -ENOENT;
+ goto out;
+
+ do {
+ err = -ENOMEM;
+ buf = malloc(buflen);
+ if (!buf)
+ goto out_name;
+ err = -getgrnam_r(localname, &grbuf, buf, buflen, &gr);
+ if (gr == NULL && !err)
+ err = -ENOENT;
+ if (err == -ERANGE) {
+ buflen *= 2;
+ free(buf);
+ }
+ } while (err == -ERANGE);
+
if (err)
- goto out_name;
+ goto out_buf;
*gid = gr->gr_gid;
-out_name:
- free(localname);
out_buf:
free(buf);
+out_name:
+ free(localname);
out:
return err;
}
@@ -235,12 +264,15 @@
struct passwd *pw;
int err = 0;
- if (strcmp(secname, "krb5") != 0)
+ if (strcmp(secname, "krb5") != 0 && strcmp(secname, "spkm3") != 0)
return -EINVAL;
/* XXX: not quite right? Need to know default realm? */
+ /* XXX: this should call something like getgssauthnam instead? */
pw = nss_getpwnam(princ, NULL, &err);
- if (pw == NULL)
+ if (pw == NULL) {
+ err = -ENOENT;
goto out;
+ }
*uid = pw->pw_uid;
*gid = pw->pw_gid;
free(pw);
@@ -254,12 +286,15 @@
struct passwd *pw;
int ret = -EINVAL;
- if (strcmp(secname, "krb5") != 0)
+ if (strcmp(secname, "krb5") != 0 && strcmp(secname, "spkm3") != 0)
goto out;
/* XXX: not quite right? Need to know default realm? */
+ /* XXX: this should call something like getgssauthnam instead? */
pw = nss_getpwnam(princ, NULL, &ret);
- if (pw == NULL)
+ if (pw == NULL) {
+ ret = -ENOENT;
goto out;
+ }
if (getgrouplist(pw->pw_name, pw->pw_gid, groups, ngroups) < 0)
ret = -ERANGE;
free(pw);
More information about the NFSv4
mailing list