Message ID | 20160610085406.E6ECF4010A4C9@oldenburg.str.redhat.com |
---|---|
State | New |
Headers | show |
On 06/10/2016 04:54 AM, Florian Weimer wrote: > When get*ent is called without a preceding set*ent, we need > to set the initial iteration position in get*ent. > > Reproducer: Add “services: db files” to /etc/nsswitch.conf, then run > “perl -e getservent”. It will segfault before this change, and exit > silently after it. > > 2016-06-10 Florian Weimer <fweimer@redhat.com> > > [BZ #20237] > * nss/nss_db/db-XXX.c (set*ent): Reset entidx to NULL. > (get*ent): Set entidx to NULL during initialization. If entidx is > NULL, start iteration from the beginning. The fix looks good, but surely this needs a regression test? > diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c > index 125a5e9..2d13edd 100644 > --- a/nss/nss_db/db-XXX.c > +++ b/nss/nss_db/db-XXX.c > @@ -77,7 +77,7 @@ CONCAT(_nss_db_set,ENTNAME) (int stayopen) > keep_db |= stayopen; > > /* Reset the sequential index. */ > - entidx = (const char *) state.header + state.header->valstroffset; > + entidx = NULL; > } > > __libc_lock_unlock (lock); > @@ -253,8 +253,14 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, > H_ERRNO_SET (NETDB_INTERNAL); > goto out; > } > + entidx = NULL; > } > > + /* Start from the beginning if freshly initialized or reset > + requested by set*ent. */ > + if (entidx == NULL) > + entidx = (const char *) state.header + state.header->valstroffset; > + > status = NSS_STATUS_UNAVAIL; > if (state.header != MAP_FAILED) > { >
On 06/10/2016 05:44 PM, Carlos O'Donell wrote: > On 06/10/2016 04:54 AM, Florian Weimer wrote: >> When get*ent is called without a preceding set*ent, we need >> to set the initial iteration position in get*ent. >> >> Reproducer: Add “services: db files” to /etc/nsswitch.conf, then run >> “perl -e getservent”. It will segfault before this change, and exit >> silently after it. >> >> 2016-06-10 Florian Weimer <fweimer@redhat.com> >> >> [BZ #20237] >> * nss/nss_db/db-XXX.c (set*ent): Reset entidx to NULL. >> (get*ent): Set entidx to NULL during initialization. If entidx is >> NULL, start iteration from the beginning. > > The fix looks good, but surely this needs a regression test? The problems are quite similar to nss_files testing: https://sourceware.org/ml/libc-alpha/2016-04/msg00392.html Build-time testing is only possible with chroot and (user) namespaces. Thanks, Florian
On 06/10/2016 11:55 AM, Florian Weimer wrote: > On 06/10/2016 05:44 PM, Carlos O'Donell wrote: >> On 06/10/2016 04:54 AM, Florian Weimer wrote: >>> When get*ent is called without a preceding set*ent, we need >>> to set the initial iteration position in get*ent. >>> >>> Reproducer: Add “services: db files” to /etc/nsswitch.conf, then run >>> “perl -e getservent”. It will segfault before this change, and exit >>> silently after it. >>> >>> 2016-06-10 Florian Weimer <fweimer@redhat.com> >>> >>> [BZ #20237] >>> * nss/nss_db/db-XXX.c (set*ent): Reset entidx to NULL. >>> (get*ent): Set entidx to NULL during initialization. If entidx is >>> NULL, start iteration from the beginning. >> >> The fix looks good, but surely this needs a regression test? > > The problems are quite similar to nss_files testing: > > https://sourceware.org/ml/libc-alpha/2016-04/msg00392.html > > Build-time testing is only possible with chroot and (user) namespaces. I have now reviewed nss_files. I think you should be moving forward with checking that in, the code is elegant and allows for easy to write compositional tests that run in a chroot or namespace.
diff --git a/nss/nss_db/db-XXX.c b/nss/nss_db/db-XXX.c index 125a5e9..2d13edd 100644 --- a/nss/nss_db/db-XXX.c +++ b/nss/nss_db/db-XXX.c @@ -77,7 +77,7 @@ CONCAT(_nss_db_set,ENTNAME) (int stayopen) keep_db |= stayopen; /* Reset the sequential index. */ - entidx = (const char *) state.header + state.header->valstroffset; + entidx = NULL; } __libc_lock_unlock (lock); @@ -253,8 +253,14 @@ CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, H_ERRNO_SET (NETDB_INTERNAL); goto out; } + entidx = NULL; } + /* Start from the beginning if freshly initialized or reset + requested by set*ent. */ + if (entidx == NULL) + entidx = (const char *) state.header + state.header->valstroffset; + status = NSS_STATUS_UNAVAIL; if (state.header != MAP_FAILED) {