(linenum→info "unix/slp.c:2238")

glibc/2.7/nscd/nscd_helper.c

    1: /* Copyright (C) 1998-2002,2003,2004,2005,2006,2007
    2:    Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998.
    5: 
    6:    The GNU C Library is free software; you can redistribute it and/or
    7:    modify it under the terms of the GNU Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the License, or (at your option) any later version.
   10: 
   11:    The GNU C Library is distributed in the hope that it will be useful,
   12:    but WITHOUT ANY WARRANTY; without even the implied warranty of
   13:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #include <assert.h>
   22: #include <errno.h>
   23: #include <fcntl.h>
   24: #include <stdbool.h>
   25: #include <string.h>
   26: #include <time.h>
   27: #include <unistd.h>
   28: #include <sys/mman.h>
   29: #include <sys/poll.h>
   30: #include <sys/socket.h>
   31: #include <sys/stat.h>
   32: #include <sys/time.h>
   33: #include <sys/uio.h>
   34: #include <sys/un.h>
   35: #include <not-cancel.h>
   36: #include <nis/rpcsvc/nis.h>
   37: 
   38: #include "nscd-client.h"
   39: 
   40: 
   41: /* Extra time we wait if the socket is still receiving data.  This
   42:    value is in milliseconds.  Note that the other side is nscd on the
   43:    local machine and it is already transmitting data.  So the wait
   44:    time need not be long.  */
   45: #define EXTRA_RECEIVE_TIME 200
   46: 
   47: 
   48: static int
   49: wait_on_socket (int sock, long int usectmo)
   50: {
   51:   struct pollfd fds[1];
   52:   fds[0].fd = sock;
   53:   fds[0].events = POLLIN | POLLERR | POLLHUP;
   54:   int n = __poll (fds, 1, usectmo);
   55:   if (n == -1 && __builtin_expect (errno == EINTR, 0))
   56:     {
   57:       /* Handle the case where the poll() call is interrupted by a
   58:          signal.  We cannot just use TEMP_FAILURE_RETRY since it might
   59:          lead to infinite loops.  */
   60:       struct timeval now;
   61:       (void) __gettimeofday (&now, NULL);
   62:       long int end = now.tv_sec * 1000 + usectmo + (now.tv_usec + 500) / 1000;
   63:       long int timeout = usectmo;
   64:       while (1)
   65:         {
   66:           n = __poll (fds, 1, timeout);
   67:           if (n != -1 || errno != EINTR)
   68:             break;
   69: 
   70:           /* Recompute the timeout time.  */
   71:           (void) __gettimeofday (&now, NULL);
   72:           timeout = end - (now.tv_sec * 1000 + (now.tv_usec + 500) / 1000);
   73:         }
   74:     }
   75: 
   76:   return n;
   77: }
   78: 
   79: 
   80: ssize_t
   81: __readall (int fd, void *buf, size_t len)
   82: {
   83:   size_t n = len;
   84:   ssize_t ret;
   85:   do
   86:     {
   87:     again:
   88:       ret = TEMP_FAILURE_RETRY (__read (fd, buf, n));
   89:       if (ret <= 0)
   90:         {
   91:           if (__builtin_expect (ret < 0 && errno == EAGAIN, 0)
   92:               /* The socket is still receiving data.  Wait a bit more.  */
   93:               && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
   94:             goto again;
   95: 
   96:           break;
   97:         }
   98:       buf = (char *) buf + ret;
   99:       n -= ret;
  100:     }
  101:   while (n > 0);
  102:   return ret < 0 ? ret : len - n;
  103: }
  104: 
  105: 
  106: ssize_t
  107: __readvall (int fd, const struct iovec *iov, int iovcnt)
  108: {
  109:   ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt));
  110:   if (ret <= 0)
  111:     {
  112:       if (__builtin_expect (ret == 0 || errno != EAGAIN, 1))
  113:         /* A genuine error or no data to read.  */
  114:         return ret;
  115: 
  116:       /* The data has not all yet been received.  Do as if we have not
  117:          read anything yet.  */
  118:       ret = 0;
  119:     }
  120: 
  121:   size_t total = 0;
  122:   for (int i = 0; i < iovcnt; ++i)
  123:     total += iov[i].iov_len;
  124: 
  125:   if (ret < total)
  126:     {
  127:       struct iovec iov_buf[iovcnt];
  128:       ssize_t r = ret;
  129: 
  130:       struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov));
  131:       do
  132:         {
  133:           while (iovp->iov_len <= r)
  134:             {
  135:               r -= iovp->iov_len;
  136:               --iovcnt;
  137:               ++iovp;
  138:             }
  139:           iovp->iov_base = (char *) iovp->iov_base + r;
  140:           iovp->iov_len -= r;
  141:         again:
  142:           r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt));
  143:           if (r <= 0)
  144:             {
  145:               if (__builtin_expect (r < 0 && errno == EAGAIN, 0)
  146:                   /* The socket is still receiving data.  Wait a bit more.  */
  147:                   && wait_on_socket (fd, EXTRA_RECEIVE_TIME) > 0)
  148:                 goto again;
  149: 
  150:               break;
  151:             }
  152:           ret += r;
  153:         }
  154:       while (ret < total);
  155:       if (r < 0)
  156:         ret = r;
  157:     }
  158:   return ret;
  159: }
  160: 
  161: 
  162: static int
  163: open_socket (request_type type, const char *key, size_t keylen)
  164: {
  165:   int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
  166:   if (sock < 0)
  167:     return -1;
  168: 
  169:   struct
  170:   {
  171:     request_header req;
  172:     char key[keylen];
  173:   } reqdata;
  174:   size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
  175: 
  176:   /* Make socket non-blocking.  */
  177:   __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
  178: 
  179:   struct sockaddr_un sun;
  180:   sun.sun_family = AF_UNIX;
  181:   strcpy (sun.sun_path, _PATH_NSCDSOCKET);
  182:   if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
  183:       && errno != EINPROGRESS)
  184:     goto out;
  185: 
  186:   reqdata.req.version = NSCD_VERSION;
  187:   reqdata.req.type = type;
  188:   reqdata.req.key_len = keylen;
  189: 
  190:   memcpy (reqdata.key, key, keylen);
  191: 
  192:   bool first_try = true;
  193:   struct timeval tvend;
  194:   /* Fake initializing tvend.  */
  195:   asm ("" : "=m" (tvend));
  196:   while (1)
  197:     {
  198: #ifndef MSG_NOSIGNAL
  199: # define MSG_NOSIGNAL 0
  200: #endif
  201:       ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
  202:                                                  real_sizeof_reqdata,
  203:                                                  MSG_NOSIGNAL));
  204:       if (__builtin_expect (wres == (ssize_t) real_sizeof_reqdata, 1))
  205:         /* We managed to send the request.  */
  206:         return sock;
  207: 
  208:       if (wres != -1 || errno != EAGAIN)
  209:         /* Something is really wrong, no chance to continue.  */
  210:         break;
  211: 
  212:       /* The daemon is busy wait for it.  */
  213:       int to;
  214:       struct timeval now;
  215:       (void) __gettimeofday (&now, NULL);
  216:       if (first_try)
  217:         {
  218:           tvend.tv_usec = now.tv_usec;
  219:           tvend.tv_sec = now.tv_sec + 5;
  220:           to = 5 * 1000;
  221:           first_try = false;
  222:         }
  223:       else
  224:         to = ((tvend.tv_sec - now.tv_sec) * 1000
  225:               + (tvend.tv_usec - now.tv_usec) / 1000);
  226: 
  227:       struct pollfd fds[1];
  228:       fds[0].fd = sock;
  229:       fds[0].events = POLLOUT | POLLERR | POLLHUP;
  230:       if (__poll (fds, 1, to) <= 0)
  231:         /* The connection timed out or broke down.  */
  232:         break;
  233: 
  234:       /* We try to write again.  */
  235:     }
  236: 
  237:  out:
  238:   close_not_cancel_no_status (sock);
  239: 
  240:   return -1;
  241: }
  242: 
  243: 
  244: void
  245: __nscd_unmap (struct mapped_database *mapped)
  246: {
  247:   assert (mapped->counter == 0);
  248:   __munmap ((void *) mapped->head, mapped->mapsize);
  249:   free (mapped);
  250: }
  251: 
  252: 
  253: /* Try to get a file descriptor for the shared meory segment
  254:    containing the database.  */
  255: static struct mapped_database *
  256: get_mapping (request_type type, const char *key,
  257:              struct mapped_database **mappedp)
  258: {
  259:   struct mapped_database *result = NO_MAPPING;
  260: #ifdef SCM_RIGHTS
  261:   const size_t keylen = strlen (key) + 1;
  262:   int saved_errno = errno;
  263: 
  264:   int mapfd = -1;
  265:   char resdata[keylen];
  266: 
  267:   /* Open a socket and send the request.  */
  268:   int sock = open_socket (type, key, keylen);
  269:   if (sock < 0)
  270:     goto out;
  271: 
  272:   /* Room for the data sent along with the file descriptor.  We expect
  273:      the key name back.  */
  274:   uint64_t mapsize;
  275:   struct iovec iov[2];
  276:   iov[0].iov_base = resdata;
  277:   iov[0].iov_len = keylen;
  278:   iov[1].iov_base = &mapsize;
  279:   iov[1].iov_len = sizeof (mapsize);
  280: 
  281:   union
  282:   {
  283:     struct cmsghdr hdr;
  284:     char bytes[CMSG_SPACE (sizeof (int))];
  285:   } buf;
  286:   struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 2,
  287:                         .msg_control = buf.bytes,
  288:                         .msg_controllen = sizeof (buf) };
  289:   struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
  290: 
  291:   cmsg->cmsg_level = SOL_SOCKET;
  292:   cmsg->cmsg_type = SCM_RIGHTS;
  293:   cmsg->cmsg_len = CMSG_LEN (sizeof (int));
  294: 
  295:   /* This access is well-aligned since BUF is correctly aligned for an
  296:      int and CMSG_DATA preserves this alignment.  */
  297:   *(int *) CMSG_DATA (cmsg) = -1;
  298: 
  299:   msg.msg_controllen = cmsg->cmsg_len;
  300: 
  301:   if (wait_on_socket (sock, 5 * 1000) <= 0)
  302:     goto out_close2;
  303: 
  304: # ifndef MSG_CMSG_CLOEXEC
  305: #  define MSG_CMSG_CLOEXEC 0
  306: # endif
  307:   ssize_t n = TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, MSG_CMSG_CLOEXEC));
  308: 
  309:   if (__builtin_expect (CMSG_FIRSTHDR (&msg) == NULL
  310:                         || (CMSG_FIRSTHDR (&msg)->cmsg_len
  311:                             != CMSG_LEN (sizeof (int))), 0))
  312:     goto out_close2;
  313: 
  314:   mapfd = *(int *) CMSG_DATA (cmsg);
  315: 
  316:   if (__builtin_expect (n != keylen && n != keylen + sizeof (mapsize), 0))
  317:     goto out_close;
  318: 
  319:   if (__builtin_expect (strcmp (resdata, key) != 0, 0))
  320:     goto out_close;
  321: 
  322:   if (__builtin_expect (n == keylen, 0))
  323:     {
  324:       struct stat64 st;
  325:       if (__builtin_expect (fstat64 (mapfd, &st) != 0, 0)
  326:           || __builtin_expect (st.st_size < sizeof (struct database_pers_head),
  327:                                0))
  328:         goto out_close;
  329: 
  330:       mapsize = st.st_size;
  331:     }
  332: 
  333:   /* The file is large enough, map it now.  */
  334:   void *mapping = __mmap (NULL, mapsize, PROT_READ, MAP_SHARED, mapfd, 0);
  335:   if (__builtin_expect (mapping != MAP_FAILED, 1))
  336:     {
  337:       /* Check whether the database is correct and up-to-date.  */
  338:       struct database_pers_head *head = mapping;
  339: 
  340:       if (__builtin_expect (head->version != DB_VERSION, 0)
  341:           || __builtin_expect (head->header_size != sizeof (*head), 0)
  342:           /* This really should not happen but who knows, maybe the update
  343:              thread got stuck.  */
  344:           || __builtin_expect (! head->nscd_certainly_running
  345:                                && (head->timestamp + MAPPING_TIMEOUT
  346:                                    < time (NULL)), 0))
  347:         {
  348:         out_unmap:
  349:           __munmap (mapping, mapsize);
  350:           goto out_close;
  351:         }
  352: 
  353:       size_t size = (sizeof (*head) + roundup (head->module * sizeof (ref_t),
  354:                                                ALIGN)
  355:                      + head->data_size);
  356: 
  357:       if (__builtin_expect (mapsize < size, 0))
  358:         goto out_unmap;
  359: 
  360:       /* Allocate a record for the mapping.  */
  361:       struct mapped_database *newp = malloc (sizeof (*newp));
  362:       if (newp == NULL)
  363:         /* Ugh, after all we went through the memory allocation failed.  */
  364:         goto out_unmap;
  365: 
  366:       newp->head = mapping;
  367:       newp->data = ((char *) mapping + head->header_size
  368:                     + roundup (head->module * sizeof (ref_t), ALIGN));
  369:       newp->mapsize = size;
  370:       newp->datasize = head->data_size;
  371:       /* Set counter to 1 to show it is usable.  */
  372:       newp->counter = 1;
  373: 
  374:       result = newp;
  375:     }
  376: 
  377:  out_close:
  378:   __close (mapfd);
  379:  out_close2:
  380:   __close (sock);
  381:  out:
  382:   __set_errno (saved_errno);
  383: #endif  /* SCM_RIGHTS */
  384: 
  385:   struct mapped_database *oldval = *mappedp;
  386:   *mappedp = result;
  387: 
  388:   if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0)
  389:     __nscd_unmap (oldval);
  390: 
  391:   return result;
  392: }
  393: 
  394: 
  395: struct mapped_database *
  396: __nscd_get_map_ref (request_type type, const char *name,
  397:                     volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
  398: {
  399:   struct mapped_database *cur = mapptr->mapped;
  400:   if (cur == NO_MAPPING)
  401:     return cur;
  402: 
  403:   int cnt = 0;
  404:   while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
  405:                                                                 1, 0) != 0, 0))
  406:     {
  407:       // XXX Best number of rounds?
  408:       if (__builtin_expect (++cnt > 5, 0))
  409:         return NO_MAPPING;
  410: 
  411:       atomic_delay ();
  412:     }
  413: 
  414:   cur = mapptr->mapped;
  415: 
  416:   if (__builtin_expect (cur != NO_MAPPING, 1))
  417:     {
  418:       /* If not mapped or timestamp not updated, request new map.  */
  419:       if (cur == NULL
  420:           || (cur->head->nscd_certainly_running == 0
  421:               && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))
  422:           || cur->head->data_size > cur->datasize)
  423:         cur = get_mapping (type, name,
  424:                            (struct mapped_database **) &mapptr->mapped);
  425: 
  426:       if (__builtin_expect (cur != NO_MAPPING, 1))
  427:         {
  428:           if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0,
  429:                                 0))
  430:             cur = NO_MAPPING;
  431:           else
  432:             atomic_increment (&cur->counter);
  433:         }
  434:     }
  435: 
  436:   mapptr->lock = 0;
  437: 
  438:   return cur;
  439: }
  440: 
  441: 
  442: /* Don't return const struct datahead *, as eventhough the record
  443:    is normally constant, it can change arbitrarily during nscd
  444:    garbage collection.  */
  445: struct datahead *
  446: __nscd_cache_search (request_type type, const char *key, size_t keylen,
  447:                      const struct mapped_database *mapped)
  448: {
  449:   unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
  450:   size_t datasize = mapped->datasize;
  451: 
  452:   ref_t trail = mapped->head->array[hash];
  453:   ref_t work = trail;
  454:   int tick = 0;
  455: 
  456:   while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
  457:     {
  458:       struct hashentry *here = (struct hashentry *) (mapped->data + work);
  459: 
  460: #ifndef _STRING_ARCH_unaligned
  461:       /* Although during garbage collection when moving struct hashentry
  462:          records around we first copy from old to new location and then
  463:          adjust pointer from previous hashentry to it, there is no barrier
  464:          between those memory writes.  It is very unlikely to hit it,
  465:          so check alignment only if a misaligned load can crash the
  466:          application.  */
  467:       if ((uintptr_t) here & (__alignof__ (*here) - 1))
  468:         return NULL;
  469: #endif
  470: 
  471:       if (type == here->type
  472:           && keylen == here->len
  473:           && here->key + keylen <= datasize
  474:           && memcmp (key, mapped->data + here->key, keylen) == 0
  475:           && here->packet + sizeof (struct datahead) <= datasize)
  476:         {
  477:           /* We found the entry.  Increment the appropriate counter.  */
  478:           struct datahead *dh
  479:             = (struct datahead *) (mapped->data + here->packet);
  480: 
  481: #ifndef _STRING_ARCH_unaligned
  482:           if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
  483:             return NULL;
  484: #endif
  485: 
  486:           /* See whether we must ignore the entry or whether something
  487:              is wrong because garbage collection is in progress.  */
  488:           if (dh->usable && here->packet + dh->allocsize <= datasize)
  489:             return dh;
  490:         }
  491: 
  492:       work = here->next;
  493:       /* Prevent endless loops.  This should never happen but perhaps
  494:          the database got corrupted, accidentally or deliberately.  */
  495:       if (work == trail)
  496:         break;
  497:       if (tick)
  498:         {
  499:           struct hashentry *trailelem;
  500:           trailelem = (struct hashentry *) (mapped->data + trail);
  501: 
  502: #ifndef _STRING_ARCH_unaligned
  503:           /* We have to redo the checks.  Maybe the data changed.  */
  504:           if ((uintptr_t) trailelem & (__alignof__ (*trailelem) - 1))
  505:             return NULL;
  506: #endif
  507:           trail = trailelem->next;
  508:         }
  509:       tick = 1 - tick;
  510:     }
  511: 
  512:   return NULL;
  513: }
  514: 
  515: 
  516: /* Create a socket connected to a name. */
  517: int
  518: __nscd_open_socket (const char *key, size_t keylen, request_type type,
  519:                     void *response, size_t responselen)
  520: {
  521:   /* This should never happen and it is something the nscd daemon
  522:      enforces, too.  He it helps to limit the amount of stack
  523:      used.  */
  524:   if (keylen > MAXKEYLEN)
  525:     return -1;
  526: 
  527:   int saved_errno = errno;
  528: 
  529:   int sock = open_socket (type, key, keylen);
  530:   if (sock >= 0)
  531:     {
  532:       /* Wait for data.  */
  533:       if (wait_on_socket (sock, 5 * 1000) > 0)
  534:         {
  535:           ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
  536:                                                        responselen));
  537:           if (nbytes == (ssize_t) responselen)
  538:             return sock;
  539:         }
  540: 
  541:       close_not_cancel_no_status (sock);
  542:     }
  543: 
  544:   __set_errno (saved_errno);
  545: 
  546:   return -1;
  547: }
1
Syntax (Markdown)