(open_socket): Don't send padding bytes from reqdata.
[kopensolaris-gnu/glibc.git] / 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 ssize_t
42 __readall (int fd, void *buf, size_t len)
43 {
44   size_t n = len;
45   ssize_t ret;
46   do
47     {
48       ret = TEMP_FAILURE_RETRY (__read (fd, buf, n));
49       if (ret <= 0)
50         break;
51       buf = (char *) buf + ret;
52       n -= ret;
53     }
54   while (n > 0);
55   return ret < 0 ? ret : len - n;
56 }
57
58
59 ssize_t
60 __readvall (int fd, const struct iovec *iov, int iovcnt)
61 {
62   ssize_t ret = TEMP_FAILURE_RETRY (__readv (fd, iov, iovcnt));
63   if (ret <= 0)
64     return ret;
65
66   size_t total = 0;
67   for (int i = 0; i < iovcnt; ++i)
68     total += iov[i].iov_len;
69
70   if (ret < total)
71     {
72       struct iovec iov_buf[iovcnt];
73       ssize_t r = ret;
74
75       struct iovec *iovp = memcpy (iov_buf, iov, iovcnt * sizeof (*iov));
76       do
77         {
78           while (iovp->iov_len <= r)
79             {
80               r -= iovp->iov_len;
81               --iovcnt;
82               ++iovp;
83             }
84           iovp->iov_base = (char *) iovp->iov_base + r;
85           iovp->iov_len -= r;
86           r = TEMP_FAILURE_RETRY (__readv (fd, iovp, iovcnt));
87           if (r <= 0)
88             break;
89           ret += r;
90         }
91       while (ret < total);
92       if (r < 0)
93         ret = r;
94     }
95   return ret;
96 }
97
98
99 static int
100 open_socket (request_type type, const char *key, size_t keylen)
101 {
102   int sock = __socket (PF_UNIX, SOCK_STREAM, 0);
103   if (sock < 0)
104     return -1;
105
106   struct
107   {
108     request_header req;
109     char key[keylen];
110   } reqdata;
111   size_t real_sizeof_reqdata = sizeof (request_header) + keylen;
112
113   /* Make socket non-blocking.  */
114   __fcntl (sock, F_SETFL, O_RDWR | O_NONBLOCK);
115
116   struct sockaddr_un sun;
117   sun.sun_family = AF_UNIX;
118   strcpy (sun.sun_path, _PATH_NSCDSOCKET);
119   if (__connect (sock, (struct sockaddr *) &sun, sizeof (sun)) < 0
120       && errno != EINPROGRESS)
121     goto out;
122
123   reqdata.req.version = NSCD_VERSION;
124   reqdata.req.type = type;
125   reqdata.req.key_len = keylen;
126
127   memcpy (reqdata.key, key, keylen);
128
129   bool first_try = true;
130   struct timeval tvend;
131   /* Fake initializing tvend.  */
132   asm ("" : "=m" (tvend));
133   while (1)
134     {
135 #ifndef MSG_NOSIGNAL
136 # define MSG_NOSIGNAL 0
137 #endif
138       ssize_t wres = TEMP_FAILURE_RETRY (__send (sock, &reqdata,
139                                                  real_sizeof_reqdata,
140                                                  MSG_NOSIGNAL));
141       if (__builtin_expect (wres == (ssize_t) real_sizeof_reqdata, 1))
142         /* We managed to send the request.  */
143         return sock;
144
145       if (wres != -1 || errno != EAGAIN)
146         /* Something is really wrong, no chance to continue.  */
147         break;
148
149       /* The daemon is busy wait for it.  */
150       int to;
151       struct timeval now;
152       (void) __gettimeofday (&now, NULL);
153       if (first_try)
154         {
155           tvend.tv_usec = now.tv_usec;
156           tvend.tv_sec = now.tv_sec + 5;
157           to = 5 * 1000;
158           first_try = false;
159         }
160       else
161         to = ((tvend.tv_sec - now.tv_sec) * 1000
162               + (tvend.tv_usec - now.tv_usec) / 1000);
163
164       struct pollfd fds[1];
165       fds[0].fd = sock;
166       fds[0].events = POLLOUT | POLLERR | POLLHUP;
167       if (__poll (fds, 1, to) <= 0)
168         /* The connection timed out or broke down.  */
169         break;
170
171       /* We try to write again.  */
172     }
173
174  out:
175   close_not_cancel_no_status (sock);
176
177   return -1;
178 }
179
180
181 void
182 __nscd_unmap (struct mapped_database *mapped)
183 {
184   assert (mapped->counter == 0);
185   __munmap ((void *) mapped->head, mapped->mapsize);
186   free (mapped);
187 }
188
189
190 static int
191 wait_on_socket (int sock)
192 {
193   struct pollfd fds[1];
194   fds[0].fd = sock;
195   fds[0].events = POLLIN | POLLERR | POLLHUP;
196   int n = __poll (fds, 1, 5 * 1000);
197   if (n == -1 && __builtin_expect (errno == EINTR, 0))
198     {
199       /* Handle the case where the poll() call is interrupted by a
200          signal.  We cannot just use TEMP_FAILURE_RETRY since it might
201          lead to infinite loops.  */
202       struct timeval now;
203       (void) __gettimeofday (&now, NULL);
204       long int end = (now.tv_sec + 5) * 1000 + (now.tv_usec + 500) / 1000;
205       while (1)
206         {
207           long int timeout = end - (now.tv_sec * 1000
208                                     + (now.tv_usec + 500) / 1000);
209           n = __poll (fds, 1, timeout);
210           if (n != -1 || errno != EINTR)
211             break;
212           (void) __gettimeofday (&now, NULL);
213         }
214     }
215
216   return n;
217 }
218
219
220 /* Try to get a file descriptor for the shared meory segment
221    containing the database.  */
222 static struct mapped_database *
223 get_mapping (request_type type, const char *key,
224              struct mapped_database **mappedp)
225 {
226   struct mapped_database *result = NO_MAPPING;
227 #ifdef SCM_RIGHTS
228   const size_t keylen = strlen (key) + 1;
229   int saved_errno = errno;
230
231   int mapfd = -1;
232   char resdata[keylen];
233
234   /* Open a socket and send the request.  */
235   int sock = open_socket (type, key, keylen);
236   if (sock < 0)
237     goto out;
238
239   /* Room for the data sent along with the file descriptor.  We expect
240      the key name back.  */
241   struct iovec iov[1];
242   iov[0].iov_base = resdata;
243   iov[0].iov_len = keylen;
244
245   union
246   {
247     struct cmsghdr hdr;
248     char bytes[CMSG_SPACE (sizeof (int))];
249   } buf;
250   struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1,
251                         .msg_control = buf.bytes,
252                         .msg_controllen = sizeof (buf) };
253   struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg);
254
255   cmsg->cmsg_level = SOL_SOCKET;
256   cmsg->cmsg_type = SCM_RIGHTS;
257   cmsg->cmsg_len = CMSG_LEN (sizeof (int));
258
259   /* This access is well-aligned since BUF is correctly aligned for an
260      int and CMSG_DATA preserves this alignment.  */
261   *(int *) CMSG_DATA (cmsg) = -1;
262
263   msg.msg_controllen = cmsg->cmsg_len;
264
265   if (wait_on_socket (sock) <= 0)
266     goto out_close2;
267
268   if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, 0))
269                         != keylen, 0))
270     goto out_close2;
271
272   mapfd = *(int *) CMSG_DATA (cmsg);
273
274   if (__builtin_expect (CMSG_FIRSTHDR (&msg)->cmsg_len
275                         != CMSG_LEN (sizeof (int)), 0))
276     goto out_close;
277
278   struct stat64 st;
279   if (__builtin_expect (strcmp (resdata, key) != 0, 0)
280       || __builtin_expect (fstat64 (mapfd, &st) != 0, 0)
281       || __builtin_expect (st.st_size < sizeof (struct database_pers_head), 0))
282     goto out_close;
283
284   struct database_pers_head head;
285   if (__builtin_expect (TEMP_FAILURE_RETRY (__pread (mapfd, &head,
286                                                      sizeof (head), 0))
287                         != sizeof (head), 0))
288     goto out_close;
289
290   if (__builtin_expect (head.version != DB_VERSION, 0)
291       || __builtin_expect (head.header_size != sizeof (head), 0)
292       /* This really should not happen but who knows, maybe the update
293          thread got stuck.  */
294       || __builtin_expect (! head.nscd_certainly_running
295                            && head.timestamp + MAPPING_TIMEOUT < time (NULL),
296                            0))
297     goto out_close;
298
299   size_t size = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN)
300                  + head.data_size);
301
302   if (__builtin_expect (st.st_size < size, 0))
303     goto out_close;
304
305   /* The file is large enough, map it now.  */
306   void *mapping = __mmap (NULL, size, PROT_READ, MAP_SHARED, mapfd, 0);
307   if (__builtin_expect (mapping != MAP_FAILED, 1))
308     {
309       /* Allocate a record for the mapping.  */
310       struct mapped_database *newp = malloc (sizeof (*newp));
311       if (newp == NULL)
312         {
313           /* Ugh, after all we went through the memory allocation failed.  */
314           __munmap (mapping, size);
315           goto out_close;
316         }
317
318       newp->head = mapping;
319       newp->data = ((char *) mapping + head.header_size
320                     + roundup (head.module * sizeof (ref_t), ALIGN));
321       newp->mapsize = size;
322       newp->datasize = head.data_size;
323       /* Set counter to 1 to show it is usable.  */
324       newp->counter = 1;
325
326       result = newp;
327     }
328
329  out_close:
330   __close (mapfd);
331  out_close2:
332   __close (sock);
333  out:
334   __set_errno (saved_errno);
335 #endif  /* SCM_RIGHTS */
336
337   struct mapped_database *oldval = *mappedp;
338   *mappedp = result;
339
340   if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0)
341     __nscd_unmap (oldval);
342
343   return result;
344 }
345
346
347 struct mapped_database *
348 __nscd_get_map_ref (request_type type, const char *name,
349                     volatile struct locked_map_ptr *mapptr, int *gc_cyclep)
350 {
351   struct mapped_database *cur = mapptr->mapped;
352   if (cur == NO_MAPPING)
353     return cur;
354
355   int cnt = 0;
356   while (__builtin_expect (atomic_compare_and_exchange_val_acq (&mapptr->lock,
357                                                                 1, 0) != 0, 0))
358     {
359       // XXX Best number of rounds?
360       if (__builtin_expect (++cnt > 5, 0))
361         return NO_MAPPING;
362
363       atomic_delay ();
364     }
365
366   cur = mapptr->mapped;
367
368   if (__builtin_expect (cur != NO_MAPPING, 1))
369     {
370       /* If not mapped or timestamp not updated, request new map.  */
371       if (cur == NULL
372           || (cur->head->nscd_certainly_running == 0
373               && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))
374           || cur->head->data_size > cur->datasize)
375         cur = get_mapping (type, name,
376                            (struct mapped_database **) &mapptr->mapped);
377
378       if (__builtin_expect (cur != NO_MAPPING, 1))
379         {
380           if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0,
381                                 0))
382             cur = NO_MAPPING;
383           else
384             atomic_increment (&cur->counter);
385         }
386     }
387
388   mapptr->lock = 0;
389
390   return cur;
391 }
392
393
394 /* Don't return const struct datahead *, as eventhough the record
395    is normally constant, it can change arbitrarily during nscd
396    garbage collection.  */
397 struct datahead *
398 __nscd_cache_search (request_type type, const char *key, size_t keylen,
399                      const struct mapped_database *mapped)
400 {
401   unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module;
402   size_t datasize = mapped->datasize;
403
404   ref_t work = mapped->head->array[hash];
405   while (work != ENDREF && work + sizeof (struct hashentry) <= datasize)
406     {
407       struct hashentry *here = (struct hashentry *) (mapped->data + work);
408
409 #ifndef _STRING_ARCH_unaligned
410       /* Although during garbage collection when moving struct hashentry
411          records around we first copy from old to new location and then
412          adjust pointer from previous hashentry to it, there is no barrier
413          between those memory writes.  It is very unlikely to hit it,
414          so check alignment only if a misaligned load can crash the
415          application.  */
416       if ((uintptr_t) here & (__alignof__ (*here) - 1))
417         return NULL;
418 #endif
419
420       if (type == here->type
421           && keylen == here->len
422           && here->key + keylen <= datasize
423           && memcmp (key, mapped->data + here->key, keylen) == 0
424           && here->packet + sizeof (struct datahead) <= datasize)
425         {
426           /* We found the entry.  Increment the appropriate counter.  */
427           struct datahead *dh
428             = (struct datahead *) (mapped->data + here->packet);
429
430 #ifndef _STRING_ARCH_unaligned
431           if ((uintptr_t) dh & (__alignof__ (*dh) - 1))
432             return NULL;
433 #endif
434
435           /* See whether we must ignore the entry or whether something
436              is wrong because garbage collection is in progress.  */
437           if (dh->usable && here->packet + dh->allocsize <= datasize)
438             return dh;
439         }
440
441       work = here->next;
442     }
443
444   return NULL;
445 }
446
447
448 /* Create a socket connected to a name. */
449 int
450 __nscd_open_socket (const char *key, size_t keylen, request_type type,
451                     void *response, size_t responselen)
452 {
453   /* This should never happen and it is something the nscd daemon
454      enforces, too.  He it helps to limit the amount of stack
455      used.  */
456   if (keylen > MAXKEYLEN)
457     return -1;
458
459   int saved_errno = errno;
460
461   int sock = open_socket (type, key, keylen);
462   if (sock >= 0)
463     {
464       /* Wait for data.  */
465       if (wait_on_socket (sock) > 0)
466         {
467           ssize_t nbytes = TEMP_FAILURE_RETRY (__read (sock, response,
468                                                        responselen));
469           if (nbytes == (ssize_t) responselen)
470             return sock;
471         }
472
473       close_not_cancel_no_status (sock);
474     }
475
476   __set_errno (saved_errno);
477
478   return -1;
479 }