Bugzilla – Bug 291870
VUL-0: CVE-2007-4135: bug in nfsidmap 0.12
Last modified: 2021-09-27 08:48:03 UTC
SuSE ships libnfsidmap based on version 0.12 which has a flaw in it's name-->uid translations. This as it is causing problems in NFSv4 name lookups. # rpm -q nfsidmap nfsidmap-0.12-16.12 This is a bug in the version of nfsidmap that ships with SLES10 SP1. idmapd will eventually call nfs4_name_to_uid which will eventually work it's way to this code: static struct passwd *nss_getpwnam(const char *name, const char *domain, int *err_p) { struct passwd *pw; struct pwbuf *buf; size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); char *localname; int err = ENOMEM; buf = malloc(sizeof(*buf) + buflen); if (buf == NULL) goto err; err = EINVAL; localname = strip_domain(name, domain); if (localname == NULL) goto err_free_buf; err = getpwnam_r(localname, &buf->pwbuf, buf->buf, buflen, &pw); ^------will be 0 when name not found ^ will be NULL when name not found------------| free(localname); if (err == 0 && pw != NULL) { <---notice no handling for err==0 && pw==NULL *err_p = 0; return pw; } err_free_buf: free(buf); err: *err_p = -err; <---here's the problem, -0 is still 0 return NULL; } So the problem is that this version of getpwnam_r does not return an error code if the requested name does not exist in /etc/passwd, it sets pw to NULL. This code tries to account for that but obviously forgets that the error code will still be zero in that case. So the calling routine is this: static int nss_name_to_uid(char *name, uid_t *uid) { struct passwd *pw = NULL; char *domain; int err = -EINVAL; domain = get_default_domain(); pw = nss_getpwnam(name, domain, &err); if (pw == NULL) <--correctly detects we didn't get anything back from getpwnam_r goto out; <---oops, this will make us return with the current value of err, which is 0 *uid = pw->pw_uid; free(pw); err = 0; out: return err; } So all the higher layers think everything went fine and use the bogus data in the pw struct, which happens to be 0 in this case which causes it to be mapped to root. Please note that this could have security implications. CITI has fixed this in version 0.17.
First, getpwnam_r returns 0 on success. check the manpage. 0.20 has this hunk: + } else if (err == 0 && pw == NULL) { + err = ENOENT; additionaly.
SWAMPID is 11215
>First, getpwnam_r returns 0 on success. check the manpage. Yes it does. And the manpage also points out: "The formulation given above under "RETURN VALUE" is from POSIX.1-2001. It does not call "not found" an error, and hence does not specify what value errno might have in this situation. But that makes it impossible to recognize errors. One might argue that according to POSIX errno should be left unchanged if an entry is not found. Experiments on various Unix-like systems show that lots of different values occur in this situation: 0, ENOENT, EBADF, ESRCH, EWOULDBLOCK, EPERM and probably others." Which experiment shows SP1 returns 0 when it can not find an entry as well as setting pwbufp to NULL. So obviously both need to be checked for the case of an entry not existing, which the 0.12 version does not do correctly. The fix mentioned above first went in in version 0.17 but 0.20 is the current and should be used as the new basis.
we usually do not do version updates in between service packs. I have added the 2 lines shown in comment #c1 to the package.
in qa
could you provide me an bug fix test to this bug? To reproduce the bug for qa maintenance reasons.
server and client. client is sles10sp1 test target. "rcidmap start" on both. On server (setup once): /etc/exports contains a NFSv4 export: /foo *.suse.de(rw,fsid=0) A new user was created which does NOT exist on client. useradd -m tux2 touch /foo/foo chown tux2:users /foo/foo On the client: mkdir /test mount -t nfs4 server:/foo /test BEFORE (BROKEN): ls -l /test -rw-r--r-- 1 root users .... foo AFTER (GOOD): -rw-r--r-- 1 nobody users .... fooo (non existing users should be shown as nobody) You can use "grape.suse.de" as already setup server so you just need to do the client testing: mkdir /test mount -t nfs4 grape.suse.de:/foo /test ls -la /test to check whether its ok.
make that: mkdir /test mount -t nfs4 grape.suse.de:/ /test ls -la /test
thanks that helped a lot. for start see comment #10 use: rcidmapd start
released
CVE-2007-4135
CVE-2007-4135: CVSS v2 Base Score: 6.2 (AV:L/AC:H/Au:N/C:C/I:C/A:C)