X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dbus%2Fdbus-sysdeps.c;h=030d0801f8399650585d0b709be920a45c5ddc4b;hb=1a163e765c0d6a86d2aa2ffb18a1d7e29a052e7a;hp=917a240c1446b957fb3df8a2145c0ffadc6c991a;hpb=5cd4c9ac5fb269a413f58d188b214b1ee4f6a5a6;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 917a240..030d080 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -57,7 +57,9 @@ #ifdef HAVE_BACKTRACE #include #endif - +#ifdef HAVE_GETPEERUCRED +#include +#endif #ifndef O_BINARY #define O_BINARY 0 @@ -396,6 +398,7 @@ _dbus_connect_unix_socket (const char *path, DBusError *error) { int fd; + size_t path_len; struct sockaddr_un addr; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -417,15 +420,23 @@ _dbus_connect_unix_socket (const char *path, _DBUS_ZERO (addr); addr.sun_family = AF_UNIX; + path_len = strlen (path); if (abstract) { #ifdef HAVE_ABSTRACT_SOCKETS - /* remember that abstract names aren't nul-terminated so we rely - * on sun_path being filled in with zeroes above. - */ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ - strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2); + path_len++; /* Account for the extra nul byte added to the start of sun_path */ + + if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) + { + dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, + "Abstract socket name too long\n"); + close (fd); + return -1; + } + + strncpy (&addr.sun_path[1], path, path_len); /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ #else /* HAVE_ABSTRACT_SOCKETS */ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, @@ -436,10 +447,18 @@ _dbus_connect_unix_socket (const char *path, } else { - strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1); + if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) + { + dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, + "Socket name too long\n"); + close (fd); + return -1; + } + + strncpy (addr.sun_path, path, path_len); } - if (connect (fd, (struct sockaddr*) &addr, sizeof (addr)) < 0) + if (connect (fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), @@ -487,6 +506,7 @@ _dbus_listen_unix_socket (const char *path, { int listen_fd; struct sockaddr_un addr; + size_t path_len; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -505,6 +525,7 @@ _dbus_listen_unix_socket (const char *path, _DBUS_ZERO (addr); addr.sun_family = AF_UNIX; + path_len = strlen (path); if (abstract) { @@ -513,7 +534,17 @@ _dbus_listen_unix_socket (const char *path, * on sun_path being filled in with zeroes above. */ addr.sun_path[0] = '\0'; /* this is what says "use abstract" */ - strncpy (&addr.sun_path[1], path, _DBUS_MAX_SUN_PATH_LENGTH - 2); + path_len++; /* Account for the extra nul byte added to the start of sun_path */ + + if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) + { + dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, + "Abstract socket name too long\n"); + close (listen_fd); + return -1; + } + + strncpy (&addr.sun_path[1], path, path_len); /* _dbus_verbose_bytes (addr.sun_path, sizeof (addr.sun_path)); */ #else /* HAVE_ABSTRACT_SOCKETS */ dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED, @@ -542,10 +573,18 @@ _dbus_listen_unix_socket (const char *path, unlink (path); } - strncpy (addr.sun_path, path, _DBUS_MAX_SUN_PATH_LENGTH - 1); + if (path_len > _DBUS_MAX_SUN_PATH_LENGTH) + { + dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, + "Abstract socket name too long\n"); + close (listen_fd); + return -1; + } + + strncpy (addr.sun_path, path, path_len); } - if (bind (listen_fd, (struct sockaddr*) &addr, sizeof (addr)) < 0) + if (bind (listen_fd, (struct sockaddr*) &addr, _DBUS_STRUCT_OFFSET (struct sockaddr_un, sun_path) + path_len) < 0) { dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to bind socket \"%s\": %s", @@ -742,12 +781,40 @@ write_credentials_byte (int server_fd, { int bytes_written; char buf[1] = { '\0' }; +#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS) + struct { + struct cmsghdr hdr; + struct cmsgcred cred; + } cmsg; + struct iovec iov; + struct msghdr msg; +#endif + +#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS) + iov.iov_base = buf; + iov.iov_len = 1; + + memset (&msg, 0, sizeof (msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + msg.msg_control = &cmsg; + msg.msg_controllen = sizeof (cmsg); + memset (&cmsg, 0, sizeof (cmsg)); + cmsg.hdr.cmsg_len = sizeof (cmsg); + cmsg.hdr.cmsg_level = SOL_SOCKET; + cmsg.hdr.cmsg_type = SCM_CREDS; +#endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); again: +#if defined(HAVE_CMSGCRED) && !defined(LOCAL_CREDS) + bytes_written = sendmsg (server_fd, &msg, 0); +#else bytes_written = write (server_fd, buf, 1); +#endif if (bytes_written < 0 && errno == EINTR) goto again; @@ -801,8 +868,10 @@ _dbus_read_credentials_unix_socket (int client_fd, char buf; #ifdef HAVE_CMSGCRED - char cmsgmem[CMSG_SPACE (sizeof (struct cmsgcred))]; - struct cmsghdr *cmsg = (struct cmsghdr *) cmsgmem; + struct { + struct cmsghdr hdr; + struct cmsgcred cred; + } cmsg; #endif _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -837,9 +906,9 @@ _dbus_read_credentials_unix_socket (int client_fd, msg.msg_iovlen = 1; #ifdef HAVE_CMSGCRED - memset (cmsgmem, 0, sizeof (cmsgmem)); - msg.msg_control = cmsgmem; - msg.msg_controllen = sizeof (cmsgmem); + memset (&cmsg, 0, sizeof (cmsg)); + msg.msg_control = &cmsg; + msg.msg_controllen = sizeof (cmsg); #endif again: @@ -862,7 +931,7 @@ _dbus_read_credentials_unix_socket (int client_fd, } #ifdef HAVE_CMSGCRED - if (cmsg->cmsg_len < sizeof (cmsgmem) || cmsg->cmsg_type != SCM_CREDS) + if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS) { dbus_set_error (error, DBUS_ERROR_FAILED, "Message from recvmsg() was not SCM_CREDS"); @@ -890,14 +959,36 @@ _dbus_read_credentials_unix_socket (int client_fd, cr_len, (int) sizeof (cr), _dbus_strerror (errno)); } #elif defined(HAVE_CMSGCRED) - struct cmsgcred *cred; - - cred = (struct cmsgcred *) CMSG_DATA (cmsg); - - credentials->pid = cred->cmcred_pid; - credentials->uid = cred->cmcred_euid; - credentials->gid = cred->cmcred_groups[0]; -#else /* !SO_PEERCRED && !HAVE_CMSGCRED */ + credentials->pid = cmsg.cred.cmcred_pid; + credentials->uid = cmsg.cred.cmcred_euid; + credentials->gid = cmsg.cred.cmcred_groups[0]; +#elif defined(HAVE_GETPEEREID) + uid_t euid; + gid_t egid; + if (getpeereid (client_fd, &euid, &egid) == 0) + { + credentials->uid = euid; + credentials->gid = egid; + } + else + { + _dbus_verbose ("Failed to getpeereid() credentials: %s\n", _dbus_strerror (errno)); + } +#elif defined(HAVE_GETPEERUCRED) + ucred_t * ucred = NULL; + if (getpeerucred (client_fd, &ucred) == 0) + { + credentials->pid = ucred_getpid (ucred); + credentials->uid = ucred_geteuid (ucred); + credentials->gid = ucred_getegid (ucred); + } + else + { + _dbus_verbose ("Failed to getpeerucred() credentials: %s\n", _dbus_strerror (errno)); + } + if (ucred != NULL) + ucred_free (ucred); +#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */ _dbus_verbose ("Socket credentials not supported on this OS\n"); #endif } @@ -1135,6 +1226,7 @@ _dbus_string_parse_int (const DBusString *str, * Checks to make sure the given directory is * private to the user * +* @param dir the name of the directory * @param error error return * @returns #FALSE on failure **/ @@ -1167,8 +1259,6 @@ _dbus_check_dir_is_private_to_user (DBusString *dir, DBusError *error) return TRUE; } -#ifdef DBUS_BUILD_TESTS -/* Not currently used, so only built when tests are enabled */ /** * Parses an unsigned integer contained in a DBusString. Either return * parameter may be #NULL if you aren't interested in it. The integer @@ -1207,7 +1297,6 @@ _dbus_string_parse_uint (const DBusString *str, return TRUE; } -#endif /* DBUS_BUILD_TESTS */ #ifdef DBUS_BUILD_TESTS static dbus_bool_t