From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/7086 Path: news.gmane.org!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: [PATCH] support alternate backends for the passwd and group dbs Date: Mon, 23 Feb 2015 01:08:40 -0500 Message-ID: <20150223060840.GB23507@brightrain.aerifal.cx> References: <1424658940-16635-1-git-send-email-josiahw@gmail.com> <1424660290-25921-1-git-send-email-josiahw@gmail.com> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="Uwl7UQhJk99r8jnw" X-Trace: ger.gmane.org 1424671747 19776 80.91.229.3 (23 Feb 2015 06:09:07 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 23 Feb 2015 06:09:07 +0000 (UTC) To: musl@lists.openwall.com Original-X-From: musl-return-7099-gllmg-musl=m.gmane.org@lists.openwall.com Mon Feb 23 07:09:00 2015 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by plane.gmane.org with smtp (Exim 4.69) (envelope-from ) id 1YPmCR-0005Fw-W9 for gllmg-musl@m.gmane.org; Mon, 23 Feb 2015 07:09:00 +0100 Original-Received: (qmail 8128 invoked by uid 550); 23 Feb 2015 06:08:58 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Original-Received: (qmail 8081 invoked from network); 23 Feb 2015 06:08:53 -0000 Content-Disposition: inline In-Reply-To: <1424660290-25921-1-git-send-email-josiahw@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:7086 Archived-At: --Uwl7UQhJk99r8jnw Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Sun, Feb 22, 2015 at 08:58:10PM -0600, Josiah Worcester wrote: > when we fail to find the entry in the commonly accepted files, we > query a server over a Unix domain socket on /var/run/nscd/socket. > the protocol used here is compatible with glibc's nscd protocol on > most systems (all that use 32-bit numbers for all the protocol fields, > which appears to be everything but Alpha). I'm committing with the attached additional changes amended in as discussed on #musl. With these changes it at least passes the following checks: - With no nscd running, lookups return negative with no error. - With bad nscd running and dropping connections with no reply, reverse-endian fallback code retries the query and then fails with EIO indicating inability to provide a definitive negative answer. - Replies that don't match the query produce EIO. - Replies that do match the query produce successful results. Tested using the attached fake-nscd.c. This code still needs further testing before release to ensure that we're not introducing significant bugs. Rich --Uwl7UQhJk99r8jnw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="nscd-addl-changes.diff" diff --git a/src/passwd/getgr_a.c b/src/passwd/getgr_a.c index 2d3ed1d..7738c3c 100644 --- a/src/passwd/getgr_a.c +++ b/src/passwd/getgr_a.c @@ -96,7 +96,7 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t grlist_len += name_len; } - if (len > *size) { + if (len > *size || !*buf) { char *tmp = realloc(*buf, len); if (!tmp) { rv = errno; @@ -106,7 +106,7 @@ int __getgr_a(const char *name, gid_t gid, struct group *gr, char **buf, size_t *size = len; } - if (fread(*buf, 1, len, f) < len) { + if (!fread(*buf, len, 1, f)) { rv = ferror(f) ? errno : EIO; goto cleanup_f; } diff --git a/src/passwd/getpw_a.c b/src/passwd/getpw_a.c index 9af6cab..b04663d 100644 --- a/src/passwd/getpw_a.c +++ b/src/passwd/getpw_a.c @@ -90,7 +90,7 @@ int __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf, size_t + passwdbuf[PWGECOSLEN] + passwdbuf[PWDIRLEN] + passwdbuf[PWSHELLLEN]; - if (len > *size) { + if (len > *size || !*buf) { char *tmp = realloc(*buf, len); if (!tmp) { rv = errno; @@ -100,7 +100,7 @@ int __getpw_a(const char *name, uid_t uid, struct passwd *pw, char **buf, size_t *size = len; } - if (fread(*buf, 1, len, f) < len) { + if (!fread(*buf, len, 1, f)) { rv = ferror(f) ? errno : EIO; goto cleanup_f; } diff --git a/src/passwd/nscd_query.c b/src/passwd/nscd_query.c index 539cc2a..f8d0fc1 100644 --- a/src/passwd/nscd_query.c +++ b/src/passwd/nscd_query.c @@ -14,34 +14,10 @@ static const struct { "/var/run/nscd/socket" }; -static ssize_t full_sendmsg(int fd, struct msghdr *m, int flags) -{ - ssize_t n, count = 0; - - while (m->msg_iovlen) { - n = sendmsg(fd, m, flags); - if(n < 0) return n; - count += n; - - while (n) { - if (n >= m->msg_iov[0].iov_len) { - n -= m->msg_iov[0].iov_len; - m->msg_iov++; - m->msg_iovlen--; - } else { - m->msg_iov[0].iov_len -= n; - n = 0; - } - } - } - return count; -} - FILE *__nscd_query(int32_t req, const char *key, int32_t *buf, size_t len, int *swap) { size_t i; int fd; - int res = 0; FILE *f = 0; int32_t req_buf[REQ_LEN] = { NSCDVERSION, @@ -71,23 +47,24 @@ retry: * that is precisely what happened */ if (errno == EACCES || errno == ECONNREFUSED || errno == ENOENT) { - res = -1; + close(fd); + return (FILE *)-1; } goto error; } - if (full_sendmsg(fd, &msg, MSG_NOSIGNAL) < 0) + if (sendmsg(fd, &msg, MSG_NOSIGNAL) < 0) goto error; - f = fdopen(fd, "r"); + if(!(f = fdopen(fd, "r"))) goto error; - if (fread(buf, 1, len, f) < len) { + if (!fread(buf, len, 1, f)) { /* If the VERSION entry mismatches nscd will disconnect. The * most likely cause is that the endianness mismatched. So, we * byteswap and try once more. (if we already swapped, just * fail out) */ - if (!feof(f)) goto error; + if (ferror(f)) goto error; if (!*swap) { fclose(f); for (i = 0; i < sizeof(req_buf)/sizeof(req_buf[0]); i++) { @@ -96,8 +73,7 @@ retry: *swap = 1; goto retry; } else { - fclose(f); - res = -1; + errno = EIO; goto error; } } @@ -113,13 +89,12 @@ retry: * response. */ if(buf[0] != NSCDVERSION) { - res = -1; errno = EIO; goto error; } return f; error: - fclose(f); - return (FILE*)res; + if (f) fclose(f); else close(fd); + return 0; } --Uwl7UQhJk99r8jnw Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="fake-nscd.c" #include #include #include #include #define STRINGS "foobar\0\0\0/\0/bin/sh" static const struct reply { uint32_t header[9]; char strings[sizeof STRINGS]; } reply = { { 2, 1, 7, 1, 12345, 678910, 1, 2, 8 }, STRINGS }; int main() { struct sockaddr_un sun = { .sun_family = AF_UNIX, .sun_path = "/var/run/nscd/socket" }; int s = socket(AF_UNIX, SOCK_STREAM, 0); umask(0); bind(s, (void *)&sun, sizeof sun); listen(s, 1); for (;;) { char buf[256]; int c = accept(s, (void *)&(struct sockaddr_un){0}, &(socklen_t){sizeof sun}); read(c, buf, sizeof buf); write(c, &reply, sizeof reply); close(c); } } --Uwl7UQhJk99r8jnw--