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

dbus/1.0.2/dbus/dbus-sysdeps-unix.c

    1: /* -*- mode: C; c-file-style: "gnu" -*- */
    2: /* dbus-sysdeps-unix.c Wrappers around UNIX system/libc features (internal to D-Bus implementation)
    3:  * 
    4:  * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
    5:  * Copyright (C) 2003 CodeFactory AB
    6:  *
    7:  * Licensed under the Academic Free License version 2.1
    8:  * 
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 2 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  * 
   19:  * You should have received a copy of the GNU General Public License
   20:  * along with this program; if not, write to the Free Software
   21:  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22:  *
   23:  */
   24: 
   25: #include "dbus-internals.h"
   26: #include "dbus-sysdeps.h"
   27: #include "dbus-sysdeps-unix.h"
   28: #include "dbus-threads.h"
   29: #include "dbus-protocol.h"
   30: #include "dbus-transport.h"
   31: #include "dbus-string.h"
   32: #include "dbus-userdb.h"
   33: #include "dbus-list.h"
   34: #include <sys/types.h>
   35: #include <stdlib.h>
   36: #include <string.h>
   37: #include <signal.h>
   38: #include <unistd.h>
   39: #include <stdio.h>
   40: #include <fcntl.h>
   41: #include <sys/socket.h>
   42: #include <dirent.h>
   43: #include <sys/un.h>
   44: #include <pwd.h>
   45: #include <time.h>
   46: #include <locale.h>
   47: #include <sys/time.h>
   48: #include <sys/stat.h>
   49: #include <sys/wait.h>
   50: #include <netinet/in.h>
   51: #include <netdb.h>
   52: #include <grp.h>
   53: 
   54: #ifdef HAVE_ERRNO_H
   55: #include <errno.h>
   56: #endif
   57: #ifdef HAVE_WRITEV
   58: #include <sys/uio.h>
   59: #endif
   60: #ifdef HAVE_POLL
   61: #include <sys/poll.h>
   62: #endif
   63: #ifdef HAVE_BACKTRACE
   64: #include <execinfo.h>
   65: #endif
   66: #ifdef HAVE_GETPEERUCRED
   67: #include <ucred.h>
   68: #endif
   69: 
   70: #ifndef O_BINARY
   71: #define O_BINARY 0
   72: #endif
   73: 
   74: #ifndef HAVE_SOCKLEN_T
   75: #define socklen_t int
   76: #endif
   77: 
   78: static dbus_bool_t
   79: _dbus_open_socket (int              *fd,
   80:                    int               domain,
   81:                    int               type,
   82:                    int               protocol,
   83:                    DBusError        *error)
   84: {
   85:   *fd = socket (domain, type, protocol);
   86:   if (fd >= 0)
   87:     {
   88:       return TRUE;
   89:     }
   90:   else
   91:     {
   92:       dbus_set_error(error,
   93:                      _dbus_error_from_errno (errno),
   94:                      "Failed to open socket: %s",
   95:                      _dbus_strerror (errno));
   96:       return FALSE;
   97:     }
   98: }
   99: 
  100: dbus_bool_t
  101: _dbus_open_tcp_socket (int              *fd,
  102:                        DBusError        *error)
  103: {
  104:   return _dbus_open_socket(fd, AF_INET, SOCK_STREAM, 0, error);
  105: }
  106: 
  107: /**
  108:  * Opens a UNIX domain socket (as in the socket() call).
  109:  * Does not bind the socket.
  110:  * @param fd return location for socket descriptor
  111:  * @param error return location for an error
  112:  * @returns #FALSE if error is set
  113:  */
  114: dbus_bool_t
  115: _dbus_open_unix_socket (int              *fd,
  116:                         DBusError        *error)
  117: {
  118:   return _dbus_open_socket(fd, PF_UNIX, SOCK_STREAM, 0, error);
  119: }
  120: 
  121: /**
  122:  * Closes a socket. Should not be used on non-socket
  123:  * file descriptors or handles.
  124:  *
  125:  * @param fd the socket
  126:  * @param error return location for an error
  127:  * @returns #FALSE if error is set
  128:  */
  129: dbus_bool_t 
  130: _dbus_close_socket (int               fd,
  131:                     DBusError        *error)
  132: {
  133:   return _dbus_close (fd, error);
  134: }
  135: 
  136: /**
  137:  * Like _dbus_read(), but only works on sockets so is
  138:  * available on Windows.
  139:  *
  140:  * @param fd the socket
  141:  * @param buffer string to append data to
  142:  * @param count max amount of data to read
  143:  * @returns number of bytes appended to the string
  144:  */
  145: int
  146: _dbus_read_socket (int               fd,
  147:                    DBusString       *buffer,
  148:                    int               count)
  149: {
  150:   return _dbus_read (fd, buffer, count);
  151: }
  152: 
  153: /**
  154:  * Like _dbus_write(), but only supports sockets
  155:  * and is thus available on Windows.
  156:  *
  157:  * @param fd the file descriptor to write
  158:  * @param buffer the buffer to write data from
  159:  * @param start the first byte in the buffer to write
  160:  * @param len the number of bytes to try to write
  161:  * @returns the number of bytes written or -1 on error
  162:  */
  163: int
  164: _dbus_write_socket (int               fd,
  165:                     const DBusString *buffer,
  166:                     int               start,
  167:                     int               len)
  168: {
  169:   return _dbus_write (fd, buffer, start, len);
  170: }
  171: 
  172: /**
  173:  * Like _dbus_write_two() but only works on sockets and is thus
  174:  * available on Windows.
  175:  * 
  176:  * @param fd the file descriptor
  177:  * @param buffer1 first buffer
  178:  * @param start1 first byte to write in first buffer
  179:  * @param len1 number of bytes to write from first buffer
  180:  * @param buffer2 second buffer, or #NULL
  181:  * @param start2 first byte to write in second buffer
  182:  * @param len2 number of bytes to write in second buffer
  183:  * @returns total bytes written from both buffers, or -1 on error
  184:  */
  185: int
  186: _dbus_write_socket_two (int               fd,
  187:                         const DBusString *buffer1,
  188:                         int               start1,
  189:                         int               len1,
  190:                         const DBusString *buffer2,
  191:                         int               start2,
  192:                         int               len2)
  193: {
  194:   return _dbus_write_two (fd, buffer1, start1, len1,
  195:                           buffer2, start2, len2);
  196: }
  197: 
  198: 
  199: /**
  200:  * Thin wrapper around the read() system call that appends
  201:  * the data it reads to the DBusString buffer. It appends
  202:  * up to the given count, and returns the same value
  203:  * and same errno as read(). The only exception is that
  204:  * _dbus_read() handles EINTR for you. Also, _dbus_read() can
  205:  * return ENOMEM, even though regular UNIX read doesn't.
  206:  *
  207:  * Unlike _dbus_read_socket(), _dbus_read() is not available
  208:  * on Windows.
  209:  * 
  210:  * @param fd the file descriptor to read from
  211:  * @param buffer the buffer to append data to
  212:  * @param count the amount of data to read
  213:  * @returns the number of bytes read or -1
  214:  */
  215: int
  216: _dbus_read (int               fd,
  217:             DBusString       *buffer,
  218:             int               count)
  219: {
  220:   int bytes_read;
  221:   int start;
  222:   char *data;
  223: 
  224:   _dbus_assert (count >= 0);
  225:   
  226:   start = _dbus_string_get_length (buffer);
  227: 
  228:   if (!_dbus_string_lengthen (buffer, count))
  229:     {
  230:       errno = ENOMEM;
  231:       return -1;
  232:     }
  233: 
  234:   data = _dbus_string_get_data_len (buffer, start, count);
  235: 
  236:  again:
  237:   
  238:   bytes_read = read (fd, data, count);
  239: 
  240:   if (bytes_read < 0)
  241:     {
  242:       if (errno == EINTR)
  243:         goto again;
  244:       else
  245:         {
  246:           /* put length back (note that this doesn't actually realloc anything) */
  247:           _dbus_string_set_length (buffer, start);
  248:           return -1;
  249:         }
  250:     }
  251:   else
  252:     {
  253:       /* put length back (doesn't actually realloc) */
  254:       _dbus_string_set_length (buffer, start + bytes_read);
  255: 
  256: #if 0
  257:       if (bytes_read > 0)
  258:         _dbus_verbose_bytes_of_string (buffer, start, bytes_read);
  259: #endif
  260:       
  261:       return bytes_read;
  262:     }
  263: }
  264: 
  265: /**
  266:  * Thin wrapper around the write() system call that writes a part of a
  267:  * DBusString and handles EINTR for you.
  268:  * 
  269:  * @param fd the file descriptor to write
  270:  * @param buffer the buffer to write data from
  271:  * @param start the first byte in the buffer to write
  272:  * @param len the number of bytes to try to write
  273:  * @returns the number of bytes written or -1 on error
  274:  */
  275: int
  276: _dbus_write (int               fd,
  277:              const DBusString *buffer,
  278:              int               start,
  279:              int               len)
  280: {
  281:   const char *data;
  282:   int bytes_written;
  283:   
  284:   data = _dbus_string_get_const_data_len (buffer, start, len);
  285:   
  286:  again:
  287: 
  288:   bytes_written = write (fd, data, len);
  289: 
  290:   if (bytes_written < 0 && errno == EINTR)
  291:     goto again;
  292: 
  293: #if 0
  294:   if (bytes_written > 0)
  295:     _dbus_verbose_bytes_of_string (buffer, start, bytes_written);
  296: #endif
  297:   
  298:   return bytes_written;
  299: }
  300: 
  301: /**
  302:  * Like _dbus_write() but will use writev() if possible
  303:  * to write both buffers in sequence. The return value
  304:  * is the number of bytes written in the first buffer,
  305:  * plus the number written in the second. If the first
  306:  * buffer is written successfully and an error occurs
  307:  * writing the second, the number of bytes in the first
  308:  * is returned (i.e. the error is ignored), on systems that
  309:  * don't have writev. Handles EINTR for you.
  310:  * The second buffer may be #NULL.
  311:  *
  312:  * @param fd the file descriptor
  313:  * @param buffer1 first buffer
  314:  * @param start1 first byte to write in first buffer
  315:  * @param len1 number of bytes to write from first buffer
  316:  * @param buffer2 second buffer, or #NULL
  317:  * @param start2 first byte to write in second buffer
  318:  * @param len2 number of bytes to write in second buffer
  319:  * @returns total bytes written from both buffers, or -1 on error
  320:  */
  321: int
  322: _dbus_write_two (int               fd,
  323:                  const DBusString *buffer1,
  324:                  int               start1,
  325:                  int               len1,
  326:                  const DBusString *buffer2,
  327:                  int               start2,
  328:                  int               len2)
  329: {
  330:   _dbus_assert (buffer1 != NULL);
  331:   _dbus_assert (start1 >= 0);
  332:   _dbus_assert (start2 >= 0);
  333:   _dbus_assert (len1 >= 0);
  334:   _dbus_assert (len2 >= 0);
  335:   
  336: #ifdef HAVE_WRITEV
  337:   {
  338:     struct iovec vectors[2];
  339:     const char *data1;
  340:     const char *data2;
  341:     int bytes_written;
  342: 
  343:     data1 = _dbus_string_get_const_data_len (buffer1, start1, len1);
  344: 
  345:     if (buffer2 != NULL)
  346:       data2 = _dbus_string_get_const_data_len (buffer2, start2, len2);
  347:     else
  348:       {
  349:         data2 = NULL;
  350:         start2 = 0;
  351:         len2 = 0;
  352:       }
  353:    
  354:     vectors[0].iov_base = (char*) data1;
  355:     vectors[0].iov_len = len1;
  356:     vectors[1].iov_base = (char*) data2;
  357:     vectors[1].iov_len = len2;
  358: 
  359:   again:
  360:    
  361:     bytes_written = writev (fd,
  362:                             vectors,
  363:                             data2 ? 2 : 1);
  364: 
  365:     if (bytes_written < 0 && errno == EINTR)
  366:       goto again;
  367:    
  368:     return bytes_written;
  369:   }
  370: #else /* HAVE_WRITEV */
  371:   {
  372:     int ret1;
  373:     
  374:     ret1 = _dbus_write (fd, buffer1, start1, len1);
  375:     if (ret1 == len1 && buffer2 != NULL)
  376:       {
  377:         ret2 = _dbus_write (fd, buffer2, start2, len2);
  378:         if (ret2 < 0)
  379:           ret2 = 0; /* we can't report an error as the first write was OK */
  380:        
  381:         return ret1 + ret2;
  382:       }
  383:     else
  384:       return ret1;
  385:   }
  386: #endif /* !HAVE_WRITEV */   
  387: }
  388: 
  389: #define _DBUS_MAX_SUN_PATH_LENGTH 99
  390: 
  391: /**
  392:  * @def _DBUS_MAX_SUN_PATH_LENGTH
  393:  *
  394:  * Maximum length of the path to a UNIX domain socket,
  395:  * sockaddr_un::sun_path member. POSIX requires that all systems
  396:  * support at least 100 bytes here, including the nul termination.
  397:  * We use 99 for the max value to allow for the nul.
  398:  *
  399:  * We could probably also do sizeof (addr.sun_path)
  400:  * but this way we are the same on all platforms
  401:  * which is probably a good idea.
  402:  */
  403: 
  404: /**
  405:  * Creates a socket and connects it to the UNIX domain socket at the
  406:  * given path.  The connection fd is returned, and is set up as
  407:  * nonblocking.
  408:  * 
  409:  * Uses abstract sockets instead of filesystem-linked sockets if
  410:  * requested (it's possible only on Linux; see "man 7 unix" on Linux).
  411:  * On non-Linux abstract socket usage always fails.
  412:  *
  413:  * @param path the path to UNIX domain socket
  414:  * @param abstract #TRUE to use abstract namespace
  415:  * @param error return location for error code
  416:  * @returns connection file descriptor or -1 on error
  417:  */
  418: int
  419: _dbus_connect_unix_socket (const char     *path,
  420:                            dbus_bool_t     abstract,
  421:                            DBusError      *error)
  422: {
  423:   int fd;
  424:   size_t path_len;
  425:   struct sockaddr_un addr;  
  426: 
  427:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  428: 
  429:   _dbus_verbose ("connecting to unix socket %s abstract=%d\n",
  430:                  path, abstract);
  431:   
  432:   
  433:   if (!_dbus_open_unix_socket (&fd, error))
  434:     {
  435:       _DBUS_ASSERT_ERROR_IS_SET(error);
  436:       return -1;
  437:     }
  438:   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
  439: 
  440:   _DBUS_ZERO (addr);
  441:   addr.sun_family = AF_UNIX;
  442:   path_len = strlen (path);
  443: 
  444:   if (abstract)
  445:     {
  446: #ifdef HAVE_ABSTRACT_SOCKETS
  447:       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
  448:       path_len++; /* Account for the extra nul byte added to the start of sun_path */
  449: 
  450:       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
  451:         {
  452:           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
  453:                       "Abstract socket name too long\n");
  454:           _dbus_close (fd, NULL);
  455:           return -1;
  456:         }
  457:         
  458:       strncpy (&addr.sun_path[1], path, path_len);
  459:       /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */
  460: #else /* HAVE_ABSTRACT_SOCKETS */
  461:       dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
  462:                       "Operating system does not support abstract socket namespace\n");
  463:       _dbus_close (fd, NULL);
  464:       return -1;
  465: #endif /* ! HAVE_ABSTRACT_SOCKETS */
  466:     }
  467:   else
  468:     {
  469:       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
  470:         {
  471:           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
  472:                       "Socket name too long\n");
  473:           _dbus_close (fd, NULL);
  474:           return -1;
  475:         }
  476: 
  477:       strncpy (addr.sun_path, path, path_len);
  478:     }
  479:   
  480:   if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0)
  481:     {      
  482:       dbus_set_error (error,
  483:                       _dbus_error_from_errno (errno),
  484:                       "Failed to connect to socket %s: %s",
  485:                       path, _dbus_strerror (errno));
  486: 
  487:       _dbus_close (fd, NULL);
  488:       fd = -1;
  489:       
  490:       return -1;
  491:     }
  492: 
  493:   if (!_dbus_set_fd_nonblocking (fd, error))
  494:     {
  495:       _DBUS_ASSERT_ERROR_IS_SET (error);
  496:       
  497:       _dbus_close (fd, NULL);
  498:       fd = -1;
  499: 
  500:       return -1;
  501:     }
  502: 
  503:   return fd;
  504: }
  505: 
  506: /**
  507:  * Enables or disables the reception of credentials on the given socket during
  508:  * the next message transmission.  This is only effective if the #LOCAL_CREDS
  509:  * system feature exists, in which case the other side of the connection does
  510:  * not have to do anything special to send the credentials.
  511:  *
  512:  * @param fd socket on which to change the #LOCAL_CREDS flag.
  513:  * @param on whether to enable or disable the #LOCAL_CREDS flag.
  514:  */
  515: static dbus_bool_t
  516: _dbus_set_local_creds (int fd, dbus_bool_t on)
  517: {
  518:   dbus_bool_t retval = TRUE;
  519: 
  520: #if defined(HAVE_CMSGCRED)
  521:   /* NOOP just to make sure only one codepath is used 
  522:    *      and to prefer CMSGCRED
  523:    */
  524: #elif defined(LOCAL_CREDS) 
  525:   int val = on ? 1 : 0;
  526:   if (setsockopt (fd, 0, LOCAL_CREDS, &val, sizeof (val)) < 0)
  527:     {
  528:       _dbus_verbose ("Unable to set LOCAL_CREDS socket option on fd %d\n", fd);
  529:       retval = FALSE;
  530:     }
  531:   else
  532:     _dbus_verbose ("LOCAL_CREDS %s for further messages on fd %d\n",
  533:                    on ? "enabled" : "disabled", fd);
  534: #endif
  535: 
  536:   return retval;
  537: }
  538: 
  539: /**
  540:  * Creates a socket and binds it to the given path,
  541:  * then listens on the socket. The socket is
  542:  * set to be nonblocking.
  543:  *
  544:  * Uses abstract sockets instead of filesystem-linked
  545:  * sockets if requested (it's possible only on Linux;
  546:  * see "man 7 unix" on Linux).
  547:  * On non-Linux abstract socket usage always fails.
  548:  *
  549:  * @param path the socket name
  550:  * @param abstract #TRUE to use abstract namespace
  551:  * @param error return location for errors
  552:  * @returns the listening file descriptor or -1 on error
  553:  */
  554: int
  555: _dbus_listen_unix_socket (const char     *path,
  556:                           dbus_bool_t     abstract,
  557:                           DBusError      *error)
  558: {
  559:   int listen_fd;
  560:   struct sockaddr_un addr;
  561:   size_t path_len;
  562: 
  563:   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
  564: 
  565:   _dbus_verbose ("listening on unix socket %s abstract=%d\n",
  566:                  path, abstract);
  567:   
  568:   if (!_dbus_open_unix_socket (&listen_fd, error))
  569:     {
  570:       _DBUS_ASSERT_ERROR_IS_SET(error);
  571:       return -1;
  572:     }
  573:   _DBUS_ASSERT_ERROR_IS_CLEAR(error);
  574: 
  575:   _DBUS_ZERO (addr);
  576:   addr.sun_family = AF_UNIX;
  577:   path_len = strlen (path);
  578:   
  579:   if (abstract)
  580:     {
  581: #ifdef HAVE_ABSTRACT_SOCKETS
  582:       /* remember that abstract names aren't nul-terminated so we rely
  583:        * on sun_path being filled in with zeroes above.
  584:        */
  585:       addr.sun_path[0] = '\0'; /* this is what says "use abstract" */
  586:       path_len++; /* Account for the extra nul byte added to the start of sun_path */
  587: 
  588:       if (path_len > _DBUS_MAX_SUN_PATH_LENGTH)
  589:         {
  590:           dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS,
  591:                       "Abs