Back to index

glibc  2.9
nscd_helper.c
Go to the documentation of this file.
00001 /* Copyright (C) 1998-2007, 2008 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <errno.h>
00022 #include <fcntl.h>
00023 #include <stdbool.h>
00024 #include <string.h>
00025 #include <time.h>
00026 #include <unistd.h>
00027 #include <sys/mman.h>
00028 #include <sys/poll.h>
00029 #include <sys/socket.h>
00030 #include <sys/stat.h>
00031 #include <sys/time.h>
00032 #include <sys/uio.h>
00033 #include <sys/un.h>
00034 #include <not-cancel.h>
00035 #include <nis/rpcsvc/nis.h>
00036 #include <kernel-features.h>
00037 
00038 #include "nscd-client.h"
00039 
00040 
00041 /* Extra time we wait if the socket is still receiving data.  This
00042    value is in milliseconds.  Note that the other side is nscd on the
00043    local machine and it is already transmitting data.  So the wait
00044    time need not be long.  */
00045 #define EXTRA_RECEIVE_TIME 200
00046 
00047 
00048 static int
00049 wait_on_socket (int sock, long int usectmo)
00050 {
00051   struct pollfd fds[1];
00052   fds[0].fd = sock;
00053   fds[0].events = POLLIN | POLLERR | POLLHUP;
00054   int n = __poll (fds, 1, usectmo);
00055   if (n == -1 && __builtin_expect (errno == EINTR, 0))
00056     {
00057       /* Handle the case where the poll() call is interrupted by a
00058         signal.  We cannot just use TEMP_FAILURE_RETRY since it might
00059         lead to infinite loops.  */
00060       struct timeval now;
00061       (void) __gettimeofday (&now, NULL);
00062       long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000;
00063       long int timeout = usectmo;
00064       while (1)
00065        {
00066          n = __poll (fds, 1, timeout);
00067          if (n != -1 || errno != EINTR)
00068            break;
00069 
00070          /* Recompute the timeout time.  */
00071          (void) __gettimeofday (&now, NULL);
00072          timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000);
00073        }
00074     }
00075 
00076   return n;
00077 }
00078 
00079 
00080 ssize_t
00081 __readall (int fd, void *buf, size_t len)
00082 {
00083   size_t n = len;
00084   ssize_t ret;
00085   do
00086     {
00087     again:
00088       ret = TEMP_FAILURE_RETRY (__read (fd, buf, n));
00089       if (ret <= 0)
00090        {
00091          if (__builtin_expect (ret < 0 && errno == EAGAIN, 0)
00092              /* The socket is still receiving data.  Wait a bit more.  */
00093              && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
00094            goto again;
00095 
00096          break;
00097        }
00098       buf = (char *) buf + ret;
00099       n -= ret;
00100     }
00101   while (n > 0);
00102   return ret < 0 ? ret : len - n;
00103 }
00104 
00105 
00106 ssize_t
00107 __readvall (int fd, const struct iovec *iov, int iovcnt)
00108 {
00109   ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt));
00110   if (ret <= 0)
00111     {
00112       if (__builtin_expect (ret == 0 || errno != EAGAIN, 1))
00113        /* A genuine error or no data to read.  */
00114        return ret;
00115 
00116       /* The data has not all yet been received.  Do as if we have not
00117         read anything yet.  */
00118       ret = 0;
00119     }
00120 
00121   size_t total = 0;
00122   for (int i = 0; i < iovcnt; ++i)
00123     total += iov[i].iov_len;
00124 
00125   if (ret < total)
00126     {
00127       struct iovec iov_buf[iovcnt];
00128       ssize_t r = ret;
00129 
00130       struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov));
00131       do
00132        {
00133          while (iovp->iov_len <= r)
00134            {
00135              r -= iovp->iov_len;
00136              --iovcnt;
00137              ++iovp;
00138            }
00139          iovp->iov_base = (char *) iovp->iov_base + r;
00140          iovp->iov_len -= r;
00141        again:
00142          r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt));
00143          if (r <= 0)
00144            {
00145              if (__builtin_expect (r < 0 && errno == EAGAIN, 0)
00146                 /* The socket is still receiving data.  Wait a bit more.  */
00147                 && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
00148               goto again;
00149 
00150              break;
00151            }
00152          ret += r;
00153        }
00154       while (ret < total);
00155       if (r < 0)
00156        ret = r;
00157     }
00158   return ret;
00159 }
00160 
00161 
00162 static int
00163 open_socket (request_type type, const char *key, size_t keylen)
00164 {
00165   int sock;
00166 
00167 #ifdef SOCK_CLOEXEC
00168 # ifndef __ASSUME_SOCK_CLOEXEC
00169   if (__have_sock_cloexec >= 0)
00170 # endif
00171     {
00172       sock = __socket (PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
00173 # ifndef __ASSUME_SOCK_CLOEXEC
00174       if (__have_sock_cloexec == 0)
00175        __have_sock_cloexec = sock != -1 || errno != EINVAL ? 1 : -1;
00176 # endif
00177     }
00178 #endif
00179 #ifndef __ASSUME_SOCK_CLOEXEC
00180 # ifdef SOCK_CLOEXEC
00181   if (__have_sock_cloexec < 0)
00182 # endif
00183     sock = __socket (PF_UNIX, SOCK_STREAM, 0);
00184 #endif
00185   if (sock < 0)
00186     return -1;
00187 
00188   struct
00189   {
00190     request_header req;
00191     char key[keylen];
00192   } reqdata;
00193   size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
00194 
00195 #ifndef __ASSUME_SOCK_CLOEXEC
00196 # ifdef SOCK_NONBLOCK
00197   if (__have_sock_cloexec < 0)
00198 # endif
00199     /* Make socket non-blocking.  */
00200     __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
00201 #endif
00202 
00203   struct sockaddr_un sun;
00204   sun.sun_family = AF_UNIX;
00205   strcpy (sun.sun_path, _PATH_NSCDSOCKET);
00206   if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
00207       && errno != EINPROGRESS)
00208     goto out;
00209 
00210   reqdata.req.version = NSCD_VERSION;
00211   reqdata.req.type = type;
00212   reqdata.req.key_len = keylen;
00213 
00214   memcpy (reqdata.key, key, keylen);
00215 
00216   bool first_try = true;
00217   struct timeval tvend;
00218   /* Fake initializing tvend.  */
00219   asm ("" : "=m" (tvend));
00220   while (1)
00221     {
00222 #ifndef MSG_NOSIGNAL
00223 # define MSG_NOSIGNAL 0
00224 #endif
00225       ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
00226                                            real_sizeof_reqdata,
00227                                            MSG_NOSIGNAL));
00228       if (__builtin_expect (wres == (ssize_t) real_sizeof_reqdata, 1))
00229        /* We managed to send the request.  */
00230        return sock;
00231 
00232       if (wres != -1 || errno != EAGAIN)
00233        /* Something is really wrong, no chance to continue.  */
00234        break;
00235 
00236       /* The daemon is busy wait for it.  */
00237       int to;
00238       struct timeval now;
00239       (void) __gettimeofday (&now, NULL);
00240       if (first_try)
00241        {
00242          tvend.tv_usec = now.tv_usec;
00243          tvend.tv_sec = now.tv_sec + 5;
00244          to = 5 * 1000;
00245          first_try = false;
00246        }
00247       else
00248        to = ((tvend.tv_sec - now.tv_sec) * 1000
00249              + (tvend.tv_usec - now.tv_usec) / 1000);
00250 
00251       struct pollfd fds[1];
00252       fds[0].fd = sock;
00253       fds[0].events = POLLOUT | POLLERR | POLLHUP;
00254       if (__poll (fds, 1, to) <= 0)
00255        /* The connection timed out or broke down.  */
00256        break;
00257 
00258       /* We try to write again.  */
00259     }
00260 
00261  out:
00262   close_not_cancel_no_status (sock);
00263 
00264   return -1;
00265 }
00266 
00267 
00268 void
00269 __nscd_unmap (struct mapped_database *mapped)
00270 {
00271   assert (mapped->counter == 0);
00272   __munmap ((void *) mapped->head, mapped->mapsize);
00273   free (mapped);
00274 }
00275 
00276 
00277 /* Try to get a file descriptor for the shared meory segment
00278    containing the database.  */
00279 static struct mapped_database *
00280 get_mapping (request_type type, const char *key,
00281             struct mapped_database **mappedp)
00282 {
00283   struct mapped_database *result = NO_MAPPING;
00284 #ifdef SCM_RIGHTS
00285   const size_t keylen = strlen (key) + 1;
00286   int saved_errno = errno;
00287 
00288   int mapfd = -1;
00289   char resdata[keylen];
00290 
00291   /* Open a socket and send the request.  */
00292   int sock = open_socket (type, key, keylen);
00293   if (sock < 0)
00294     goto out;
00295 
00296   /* Room for the data sent along with the file descriptor.  We expect
00297      the key name back.  */
00298   uint64_t mapsize;
00299   struct iovec iov[2];
00300   iov[0].iov_base = resdata;
00301   iov[0].iov_len = keylen;
00302   iov[1].iov_base = &mapsize;
00303   iov[1].iov_len = sizeof (mapsize);
00304 
00305   union
00306   {
00307     struct cmsghdr hdr;
00308     char bytes[CMSG_SPACE (sizeof (int))];
00309   } buf;
00310   struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 2,
00311                      .msg_control = buf.bytes,
00312                      .msg_controllen = sizeof (buf) };
00313   struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
00314 
00315   cmsg->cmsg_level = SOL_SOCKET;
00316   cmsg->cmsg_type = SCM_RIGHTS;
00317   cmsg->cmsg_len = CMSG_LEN (sizeof (int));
00318 
00319   /* This access is well-aligned since BUF is correctly aligned for an
00320      int and CMSG_DATA preserves this alignment.  */
00321   *(int *) CMSG_DATA (cmsg) = -1;
00322 
00323   msg.msg_controllen = cmsg->cmsg_len;
00324 
00325   if (wait_on_socket (sock, 5 * 1000) <= 0)
00326     goto out_close2;
00327 
00328 # ifndef MSG_CMSG_CLOEXEC
00329 #  define MSG_CMSG_CLOEXEC 0
00330 # endif
00331   ssize_t n = TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, MSG_CMSG_CLOEXEC));
00332 
00333   if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL
00334                      || (CMSG_FIRSTHDR (&msg)->cmsg_len
00335                          != CMSG_LEN (sizeof (int))), 0))
00336     goto out_close2;
00337 
00338   mapfd = *(int *) CMSG_DATA (cmsg);
00339 
00340   if (__builtin_expect (n != keylen && n != keylen + sizeof (mapsize), 0))
00341     goto out_close;
00342 
00343   if (__builtin_expect (strcmp (resdata, key) != 0, 0))
00344     goto out_close;
00345 
00346   if (__builtin_expect (n == keylen, 0))
00347     {
00348       struct stat64 st;
00349       if (__builtin_expect (fstat64 (mapfd, &st) != 0, 0)
00350          || __builtin_expect (st.st_size < sizeof (struct database_pers_head),
00351                             0))
00352        goto out_close;
00353 
00354       mapsize = st.st_size;
00355     }
00356 
00357   /* The file is large enough, map it now.  */
00358   void *mapping = __mmap (NULL, mapsize, PROT_READ, MAP_SHARED, mapfd, 0);
00359   if (__builtin_expect (mapping != MAP_FAILED, 1))
00360     {
00361       /* Check whether the database is correct and up-to-date.  */
00362       struct database_pers_head *head = mapping;
00363 
00364       if (__builtin_expect (head->version != DB_VERSION, 0)
00365          || __builtin_expect (head->header_size != sizeof (*head), 0)
00366          /* Catch some misconfiguration.  The server should catch
00367             them now but some older versions did not.  */
00368          || __builtin_expect (head->module == 0, 0)
00369          /* This really should not happen but who knows, maybe the update
00370             thread got stuck.  */
00371          || __builtin_expect (! head->nscd_certainly_running
00372                             && (head->timestamp + MAPPING_TIMEOUT
00373                                < time (NULL)), 0))
00374        {
00375        out_unmap:
00376          __munmap (mapping, mapsize);
00377          goto out_close;
00378        }
00379 
00380       size_t size = (sizeof (*head) + roundup (head->module * sizeof (ref_t),
00381                                           ALIGN)
00382                    + head->data_size);
00383 
00384       if (__builtin_expect (mapsize < size, 0))
00385        goto out_unmap;
00386 
00387       /* Allocate a record for the mapping.  */
00388       struct mapped_database *newp = malloc (sizeof (*newp));
00389       if (newp == NULL)
00390        /* Ugh, after all we went through the memory allocation failed.  */
00391        goto out_unmap;
00392 
00393       newp->head = mapping;
00394       newp->data = ((char *) mapping + head->header_size
00395                   + roundup (head->module * sizeof (ref_t), ALIGN));
00396       newp->mapsize = size;
00397       newp->datasize = head->data_size;
00398       /* Set counter to 1 to show it is usable.  */
00399       newp->counter = 1;
00400 
00401       result = newp;
00402     }
00403 
00404  out_close:
00405   __close (mapfd);
00406  out_close2:
00407   __close (sock);
00408  out:
00409   __set_errno (saved_errno);
00410 #endif /* SCM_RIGHTS */
00411 
00412   struct mapped_database *oldval = *mappedp;
00413   *mappedp = result;
00414 
00415   if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0)
00416     __nscd_unmap (oldval);
00417 
00418   return result;
00419 }
00420 
00421 
00422 struct mapped_database *
00423 __nscd_get_map_ref (request_type type, const char *name,
00424                   volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
00425 {
00426   struct mapped_database *cur = mapptr->mapped;
00427   if (cur == NO_MAPPING)
00428     return cur;
00429 
00430   int cnt = 0;
00431   while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
00432                                                         1, 0) != 0, 0))
00433     {
00434       // XXX Best number of rounds?
00435       if (__builtin_expect (++cnt > 5, 0))
00436        return NO_MAPPING;
00437 
00438       atomic_delay ();
00439     }
00440 
00441   cur = mapptr->mapped;
00442 
00443   if (__builtin_expect (cur != NO_MAPPING, 1))
00444     {
00445       /* If not mapped or timestamp not updated, request new map.  */
00446       if (cur == NULL
00447          || (cur->head->nscd_certainly_running == 0
00448              && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))
00449          || cur->head->data_size > cur->datasize)
00450        cur = get_mapping (type, name,
00451                         (struct mapped_database **) &mapptr->mapped);
00452 
00453       if (__builtin_expect (cur != NO_MAPPING, 1))
00454        {
00455          if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0,
00456                             0))
00457            cur = NO_MAPPING;
00458          else
00459            atomic_increment (&cur->counter);
00460        }
00461     }
00462 
00463   mapptr->lock = 0;
00464 
00465   return cur;
00466 }
00467 
00468 
00469 /* Don't return const struct datahead *, as eventhough the record
00470    is normally constant, it can change arbitrarily during nscd
00471    garbage collection.  */
00472 struct datahead *
00473 __nscd_cache_search (request_type type, const char *key, size_t keylen,
00474                    const struct mapped_database *mapped)
00475 {
00476   unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
00477   size_t datasize = mapped->datasize;
00478 
00479   ref_t trail = mapped->head->array[hash];
00480   ref_t work = trail;
00481   int tick = 0;
00482 
00483   while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
00484     {
00485       struct hashentry *here = (struct hashentry *) (mapped->data + work);
00486 
00487 #ifndef _STRING_ARCH_unaligned
00488       /* Although during garbage collection when moving struct hashentry
00489         records around we first copy from old to new location and then
00490         adjust pointer from previous hashentry to it, there is no barrier
00491         between those memory writes.  It is very unlikely to hit it,
00492         so check alignment only if a misaligned load can crash the
00493         application.  */
00494       if ((uintptr_t) here & (__alignof__ (*here) - 1))
00495        return NULL;
00496 #endif
00497 
00498       if (type == here->type
00499          && keylen == here->len
00500          && here->key + keylen <= datasize
00501          && memcmp (key, mapped->data + here->key, keylen) == 0
00502          && here->packet + sizeof (struct datahead) <= datasize)
00503        {
00504          /* We found the entry.  Increment the appropriate counter.  */
00505          struct datahead *dh
00506            = (struct datahead *) (mapped->data + here->packet);
00507 
00508 #ifndef _STRING_ARCH_unaligned
00509          if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
00510            return NULL;
00511 #endif
00512 
00513          /* See whether we must ignore the entry or whether something
00514             is wrong because garbage collection is in progress.  */
00515          if (dh->usable && here->packet + dh->allocsize <= datasize)
00516            return dh;
00517        }
00518 
00519       work = here->next;
00520       /* Prevent endless loops.  This should never happen but perhaps
00521         the database got corrupted, accidentally or deliberately.  */
00522       if (work == trail)
00523        break;
00524       if (tick)
00525        {
00526          struct hashentry *trailelem;
00527          trailelem = (struct hashentry *) (mapped->data + trail);
00528 
00529 #ifndef _STRING_ARCH_unaligned
00530          /* We have to redo the checks.  Maybe the data changed.  */
00531          if ((uintptr_t) trailelem & (__alignof__ (*trailelem) - 1))
00532            return NULL;
00533 #endif
00534          trail = trailelem->next;
00535        }
00536       tick = 1 - tick;
00537     }
00538 
00539   return NULL;
00540 }
00541 
00542 
00543 /* Create a socket connected to a name. */
00544 int
00545 __nscd_open_socket (const char *key, size_t keylen, request_type type,
00546                   void *response, size_t responselen)
00547 {
00548   /* This should never happen and it is something the nscd daemon
00549      enforces, too.  He it helps to limit the amount of stack
00550      used.  */
00551   if (keylen > MAXKEYLEN)
00552     return -1;
00553 
00554   int saved_errno = errno;
00555 
00556   int sock = open_socket (type, key, keylen);
00557   if (sock >= 0)
00558     {
00559       /* Wait for data.  */
00560       if (wait_on_socket (sock, 5 * 1000) > 0)
00561        {
00562          ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
00563                                                  responselen));
00564          if (nbytes == (ssize_t) responselen)
00565            return sock;
00566        }
00567 
00568       close_not_cancel_no_status (sock);
00569     }
00570 
00571   __set_errno (saved_errno);
00572 
00573   return -1;
00574 }