Hi,
so here is the second patch that i'd recommend to put into the release.
It has to be applied on top of the first one.
Ingo Schwarze wrote on Wed, Feb 19, 2014 at 05:57:13PM +0100:
> C. No matter whether they succeed or fail,
> both functions may clobber errno with irrelevant errors.
> This affects all cases.
> For the file only case, we can fix this for release if we want to.
That's exactly what this patch does:
Completely fix errno handling for the non-YP case,
including setting ERANGE for the non-YP case.
> For the YP case, there is no way to fix this before release.
> The YP code calls lots and lots of library functions, and some
> of these clobber errno. Fixing all of that looks like a
> hackathon-sized task to me, at least if i were to work on it.
In so far as the YP code also calls __hashpw(), the patch also
partially improves the YP case, but not very much. The main
issues with the YP case are not addressed by this patch;
it touches no code that runs in the YP case only.
As all the chunks shown here have already been proposed by guenther@,
ok schwarze@ if guenther@ wants to commit this after my other patch.
Otherwise, i'm obviously taking OKs to commit this myself after my
other patch.
Yours,
Ingo
--- getpwent.c.retval Wed Feb 19 19:25:33 2014
+++ getpwent.c Wed Feb 19 20:13:34 2014
@@ -709,7 +709,7 @@ getpwnam_r(const char *name, struct passwd *pw, char *
struct passwd *pwret = NULL;
int flags = 0, *flagsp;
int my_errno = 0;
- int saved_errno;
+ int saved_errno, tmp_errno;
_THREAD_PRIVATE_MUTEX_LOCK(pw);
saved_errno = errno;
@@ -731,8 +731,10 @@ getpwnam_r(const char *name, struct passwd *pw, char *
pwret = _pwhashbyname(name, buf, buflen, pw, flagsp);
if (!_pw_stayopen) {
+ tmp_errno = errno;
(void)(_pw_db->close)(_pw_db);
_pw_db = NULL;
+ errno = tmp_errno;
}
fail:
if (pwretp)
@@ -762,7 +764,7 @@ getpwuid_r(uid_t uid, struct passwd *pw, char *buf, si
struct passwd *pwret = NULL;
int flags = 0, *flagsp;
int my_errno = 0;
- int saved_errno;
+ int saved_errno, tmp_errno;
_THREAD_PRIVATE_MUTEX_LOCK(pw);
saved_errno = errno;
@@ -784,8 +786,10 @@ getpwuid_r(uid_t uid, struct passwd *pw, char *buf, si
pwret = _pwhashbyuid(uid, buf, buflen, pw, flagsp);
if (!_pw_stayopen) {
+ tmp_errno = errno;
(void)(_pw_db->close)(_pw_db);
_pw_db = NULL;
+ errno = tmp_errno;
}
fail:
if (pwretp)
@@ -867,9 +871,12 @@ __initdb(void)
errno = saved_errno;
return (1);
}
- if (!warned)
+ if (!warned) {
+ saved_errno = errno;
syslog(LOG_ERR, "%s: %m", _PATH_MP_DB);
- warned = 1;
+ errno = saved_errno;
+ warned = 1;
+ }
return (0);
}
@@ -883,8 +890,10 @@ __hashpw(DBT *key, char *buf, size_t buflen, struct pa
if ((_pw_db->get)(_pw_db, key, &data, 0))
return (0);
p = (char *)data.data;
- if (data.size > buflen)
+ if (data.size > buflen) {
+ errno = ERANGE;
return (0);
+ }
t = buf;
#define EXPAND(e) e = t; while ((*t++ = *p++));