1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* kdbus-common.c kdbus related utils for daemon and libdbus
4 * Copyright (C) 2013 Samsung Electronics
6 * Licensed under the Academic Free License version 2.1
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version and under the terms of the GNU
12 * Lesser General Public License as published by the
13 * Free Software Foundation; either version 2.1 of the License, or (at
14 * your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include <linux/kdbus.h>
28 #include "kdbus-common.h"
29 #include "dbus-transport-kdbus.h"
30 #include "dbus-valgrind-internal.h"
36 #include <dbus/dbus-internals.h>
37 #include <dbus/dbus-shared.h>
38 #include "dbus-signals.h"
40 #include <sys/ioctl.h>
41 #include <sys/types.h>
48 const char *path; /**< Path to kdbus file */
49 int fd; /**< File descriptor */
50 void *mmap_ptr; /**< Mapped memory where kdbus (kernel) writes
51 * messages incoming to us.
53 size_t pool_size; /**< Size of mapped memory */
54 __u64 id; /**< unique id of the connection */
55 char bus_id[sizeof (((struct kdbus_cmd_hello *)(0))->id128)]; /**< id of the bus */
56 struct kdbus_bloom_parameter bloom; /**< bloom parameters*/
59 /* ALIGN8 and KDBUS_FOREACH taken from systemd */
60 #define ALIGN8(l) (((l) + 7) & ~7)
61 #define KDBUS_FOREACH(iter, first, _size) \
62 for (iter = (first); \
63 ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
64 ((uint8_t *)(iter) >= (uint8_t *)(first)); \
65 iter = (void*)(((uint8_t *)iter) + ALIGN8((iter)->size)))
69 unsigned long request,
75 ret = ioctl (fd, request, data);
77 while (-1 == ret && EINTR == errno);
83 free_by_offset (kdbus_t *kdbus,
86 struct kdbus_cmd_free cmd;
89 * Kdbus requires to initialize ioctl params partially. Some parts
90 * are for data passed from user to kernel, and other parts
91 * for data passed from kernel to user.
93 * Valgrind detects when uninitialized data is passed to kernel
94 * and has no way to know that it is meant to be filled by kernel.
95 * Thus, we initialize params for Valgrind to stop complaining.
97 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
99 cmd.size = sizeof (cmd);
103 if (safe_ioctl (kdbus->fd, KDBUS_CMD_FREE, &cmd )!= 0)
109 static void make_item_name (const char *name, struct kdbus_item *item)
111 size_t len = strlen (name) + 1;
112 item->size = KDBUS_ITEM_HEADER_SIZE + len;
113 item->type = KDBUS_ITEM_NAME;
115 memcpy (item->str, name, len);
119 * Adds an item in the current position of items array.
121 * @param item item to fill
122 * @param item_type type of the item
123 * @param string value of the item
124 * @param string_size size of the value
125 * @returns pointer to the next item
128 _kdbus_item_add_string (struct kdbus_item *item,
130 const char *item_string,
131 __u64 item_string_size)
133 item->size = KDBUS_ITEM_HEADER_SIZE + item_string_size;
134 item->type = item_type;
135 memcpy (item->str, item_string, item_string_size);
136 return KDBUS_ITEM_NEXT (item);
140 _kdbus_item_add_payload_memfd (struct kdbus_item *item,
145 item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
146 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_memfd);
147 item->memfd.start = start;
148 item->memfd.size = size;
150 return KDBUS_ITEM_NEXT (item);
154 _kdbus_item_add_payload_vec (struct kdbus_item *item,
156 __u64 address_or_offset)
158 item->type = KDBUS_ITEM_PAYLOAD_VEC;
159 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_vec);
160 item->vec.size = size;
161 item->vec.address = address_or_offset;
162 return KDBUS_ITEM_NEXT (item);
166 _kdbus_item_add_fds (struct kdbus_item *item,
170 item->type = KDBUS_ITEM_FDS;
171 item->size = KDBUS_ITEM_HEADER_SIZE + (__u64)fds_count * sizeof (int);
172 memcpy (item->fds, fds, fds_count * sizeof (int));
173 return KDBUS_ITEM_NEXT (item);
177 _kdbus_item_add_bloom_filter (struct kdbus_item *item,
179 struct kdbus_bloom_filter **out_ptr)
181 item->type = KDBUS_ITEM_BLOOM_FILTER;
182 item->size = KDBUS_ITEM_HEADER_SIZE
183 + sizeof (struct kdbus_bloom_filter)
185 memset (item->bloom_filter.data, 0, kdbus->bloom.size);
186 item->bloom_filter.generation = 0;
187 *out_ptr = &item->bloom_filter;
188 return KDBUS_ITEM_NEXT (item);
192 _kdbus_bloom_filter_get_data (struct kdbus_bloom_filter *bloom_filter)
194 return bloom_filter->data;
198 _kdbus_item_add_name_change (struct kdbus_item *item,
204 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_notify_name_change);
205 item->type = KDBUS_ITEM_NAME_CHANGE;
206 item->name_change.old_id.id = old_id;
207 item->name_change.old_id.flags = old_id_flags;
208 item->name_change.new_id.id = new_id;
209 item->name_change.new_id.flags = new_id_flags;
210 return KDBUS_ITEM_NEXT (item);
214 _kdbus_item_add_id_add (struct kdbus_item *item,
218 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (struct kdbus_notify_id_change);
219 item->type = KDBUS_ITEM_ID_ADD;
220 item->id_change.id = id;
221 item->id_change.flags = id_flags;
222 return KDBUS_ITEM_NEXT (item);
226 _kdbus_item_add_id (struct kdbus_item *item,
229 item->size = KDBUS_ITEM_HEADER_SIZE + sizeof (id);
230 item->type = KDBUS_ITEM_ID;
232 return KDBUS_ITEM_NEXT (item);
236 _kdbus_item_add_bloom_mask (struct kdbus_item *item,
238 kdbus_bloom_data_t **bloom)
240 item->size = KDBUS_ITEM_HEADER_SIZE + kdbus->bloom.size;
241 item->type = KDBUS_ITEM_BLOOM_MASK;
242 memset (item->data64, 0, kdbus->bloom.size);
244 *bloom = item->data64;
245 return KDBUS_ITEM_NEXT (item);
249 get_from_offset (kdbus_t *kdbus,
252 return ((char *)kdbus->mmap_ptr) + offset;
256 _kdbus_new (const char *path)
258 kdbus_t *kdbus = dbus_new (kdbus_t, 1);
261 kdbus->path = _dbus_strdup(path);
262 if (NULL == kdbus->path)
272 _kdbus_free (kdbus_t *kdbus)
274 dbus_free ((char*)kdbus->path);
279 * Opens a connection to the kdbus bus
281 * @param kdbus kdbus object
282 * @returns 0 on success, -errno on failure
285 _kdbus_open (kdbus_t *kdbus)
287 int fd = open (kdbus->path, O_RDWR|O_CLOEXEC|O_NONBLOCK);
296 _kdbus_close (kdbus_t *kdbus)
304 ret = close (kdbus->fd);
305 } while (-1 == ret && EINTR == errno);
309 ret = munmap (kdbus->mmap_ptr, kdbus->pool_size);
321 _kdbus_get_path (kdbus_t *kdbus)
327 _kdbus_get_fd (kdbus_t *kdbus)
333 _kdbus_get_id (kdbus_t *kdbus)
339 _kdbus_get_bus_id (kdbus_t *kdbus)
341 return kdbus->bus_id;
345 _kdbus_get_bus_id_size (void)
347 return sizeof (((struct kdbus_t *)(0))->bus_id);
351 _kdbus_hello (kdbus_t *kdbus,
353 __u64 attach_flags_send,
354 __u64 attach_flags_recv,
356 const char *activator_name,
357 const char *connection_name)
359 struct kdbus_cmd_hello *hello;
360 struct kdbus_item *item, *items;
362 size_t activator_name_size = 0;
363 size_t connection_name_size = 0;
367 hello_size = sizeof (struct kdbus_cmd_hello);
369 if (NULL != activator_name)
371 activator_name_size = strlen (activator_name) + 1;
372 hello_size += KDBUS_ITEM_SIZE (activator_name_size);
375 if (NULL != connection_name)
377 connection_name_size = strlen (connection_name) + 1;
378 hello_size += KDBUS_ITEM_SIZE (connection_name_size);
381 hello = dbus_malloc (hello_size);
385 VALGRIND_MAKE_MEM_DEFINED (hello, hello_size);
387 hello->flags = flags;
388 hello->attach_flags_send = attach_flags_send;
389 hello->attach_flags_recv = attach_flags_recv;
390 hello->pool_size = pool_size;
393 if (connection_name_size > 0)
394 item = _kdbus_item_add_string (item,
395 KDBUS_ITEM_CONN_DESCRIPTION,
397 connection_name_size);
398 if (activator_name_size > 0)
400 _kdbus_item_add_string (item,
403 activator_name_size);
404 hello->flags |= KDBUS_HELLO_ACTIVATOR;
407 hello->size = hello_size;
409 if (safe_ioctl (kdbus->fd, KDBUS_CMD_HELLO, hello) != 0)
415 kdbus->id = hello->id;
416 memcpy (kdbus->bus_id, hello->id128, sizeof (kdbus->bus_id));
418 offset = hello->offset;
419 items_size = hello->items_size;
422 kdbus->mmap_ptr = mmap (NULL, pool_size, PROT_READ, MAP_SHARED, kdbus->fd, 0);
423 if (MAP_FAILED == kdbus->mmap_ptr)
426 kdbus->pool_size = pool_size;
428 items = get_from_offset (kdbus, offset);
429 KDBUS_FOREACH (item, items, items_size)
431 if (KDBUS_ITEM_BLOOM_PARAMETER == item->type)
432 kdbus->bloom = item->bloom_parameter;
435 free_by_offset (kdbus, offset);
441 _kdbus_send (kdbus_t *kdbus,
443 struct kdbus_msg *msg,
444 struct kdbus_msg **msg_reply)
446 struct kdbus_cmd_send cmd;
448 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
450 cmd.size = sizeof (cmd);
451 cmd.msg_address = (uintptr_t)msg;
454 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_SEND, &cmd))
457 if (flags & KDBUS_SEND_SYNC_REPLY)
459 if (NULL != msg_reply)
460 *msg_reply = get_from_offset (kdbus, cmd.reply.offset);
462 free_by_offset (kdbus, cmd.reply.offset);
469 _kdbus_recv (kdbus_t *kdbus,
472 struct kdbus_msg **msg)
474 struct kdbus_cmd_recv cmd;
476 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
478 cmd.size = sizeof (cmd);
480 cmd.priority = priority;
482 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_RECV, &cmd))
485 *msg = get_from_offset (kdbus, cmd.msg.offset);
491 * Provides list of names on the bus.
493 * @param kdbus kdbus object
494 * @param flags specification of required names. See enum kdbus_list_flags in kdbus.h.
495 * @param name_list data from kdbus response - the list
496 * @param list_size size of name_list in bytes
497 * @return 0 on success, errno on failure
499 * Note that name_list is allocated in kdbus pool and must be freed by _kdbus_free_mem.
502 _kdbus_list (kdbus_t *kdbus,
504 struct kdbus_info **name_list,
507 struct kdbus_cmd_list cmd;
509 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
511 cmd.size = sizeof (cmd);
514 if (-1 == safe_ioctl (kdbus->fd, KDBUS_CMD_LIST, &cmd))
517 *name_list = get_from_offset (kdbus, cmd.offset);
518 *list_size = cmd.list_size;
524 _kdbus_compute_match_items_size (kdbus_t *kdbus,
525 dbus_bool_t with_bloom_mask,
527 const char *sender_name)
532 size += KDBUS_ITEM_SIZE (kdbus->bloom.size);
534 if (KDBUS_MATCH_ID_ANY != sender_id) /* unique name present */
535 size += KDBUS_ITEM_SIZE (sizeof (sender_id));
536 else if (NULL != sender_name)
537 size += KDBUS_ITEM_SIZE (strlen (sender_name) + 1);
542 struct kdbus_cmd_match *
543 _kdbus_new_cmd_match (kdbus_t *kdbus,
548 struct kdbus_cmd_match *cmd;
549 __u64 cmd_size = sizeof (*cmd) + items_size;
550 cmd = dbus_malloc (cmd_size);
554 VALGRIND_MAKE_MEM_DEFINED (cmd, cmd_size);
556 cmd->size = cmd_size;
558 cmd->cookie = cookie;
564 _kdbus_free_cmd_match (struct kdbus_cmd_match *cmd)
570 _kdbus_add_match_name_acquired (kdbus_t *kdbus,
579 struct kdbus_cmd_match *cmd;
580 struct kdbus_item *item;
582 unsigned int len = 0;
585 len = strlen(name) + 1;
586 cmd = _kdbus_new_cmd_match (kdbus,
587 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
594 _kdbus_item_add_name_change (item,
595 old_id, old_id_flags,
596 new_id, new_id_flags);
599 memcpy(item->name_change.name, name, len);
601 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
603 goto err_name_acquired;
605 item->type = KDBUS_ITEM_NAME_ADD;
606 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
608 goto err_name_acquired;
613 _kdbus_free_cmd_match (cmd);
618 _kdbus_add_match_name_lost (kdbus_t *kdbus,
627 struct kdbus_cmd_match *cmd;
628 struct kdbus_item *item;
630 unsigned int len = 0;
633 len = strlen(name) + 1;
635 cmd = _kdbus_new_cmd_match (kdbus,
636 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
643 _kdbus_item_add_name_change (item,
644 old_id, old_id_flags,
645 new_id, new_id_flags);
649 memcpy(item->name_change.name, name, len);
651 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
653 goto err_name_remove;
655 item->type = KDBUS_ITEM_NAME_REMOVE;
656 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
658 goto err_name_remove;
663 _kdbus_free_cmd_match (cmd);
668 _kdbus_add_match_name_change (kdbus_t *kdbus,
677 struct kdbus_cmd_match *cmd;
678 struct kdbus_item *item;
680 unsigned int len = 0;
683 len = strlen(name) + 1;
685 /* name = NULL or Well-known Name */
686 if (name == NULL || (name[0] != ':')) {
687 cmd = _kdbus_new_cmd_match (kdbus,
688 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_name_change) + len),
695 _kdbus_item_add_name_change (item,
696 old_id, old_id_flags,
697 new_id, new_id_flags);
701 memcpy(item->name_change.name, name, len);
703 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
706 item->type = KDBUS_ITEM_NAME_ADD;
707 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
710 item->type = KDBUS_ITEM_NAME_REMOVE;
711 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
718 _kdbus_free_cmd_match (cmd);
726 _kdbus_add_match_id_change (kdbus_t *kdbus,
733 struct kdbus_cmd_match *cmd;
734 struct kdbus_item *item;
737 /* name = NULL or Unique Name */
738 if (name == NULL || name[0] == ':')
740 cmd = _kdbus_new_cmd_match (kdbus,
741 KDBUS_ITEM_SIZE (sizeof (struct kdbus_notify_id_change)),
748 _kdbus_item_add_id_add (item, id, id_flags);
751 item->id_change.id = strtoull (name + 3, NULL, 10);
753 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
756 item->type = KDBUS_ITEM_ID_REMOVE;
757 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
763 _kdbus_free_cmd_match (cmd);
769 int _kdbus_add_match (kdbus_t *kdbus,
770 struct kdbus_cmd_match *cmd)
772 int ret = safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_ADD, cmd);
780 * Allocates and initializes kdbus message structure.
781 * @param kdbus kdbus object
782 * @param size_for_items size of items that will be attached to this message
783 * @param flags flags for message
784 * @returns initialized kdbus message or NULL if malloc failed
787 _kdbus_new_msg (kdbus_t *kdbus,
788 __u64 size_for_items,
793 enum kdbus_payload_type payload_type,
795 __u64 timeout_ns_or_cookie_reply)
797 struct kdbus_msg *msg;
798 __u64 msg_size = sizeof (struct kdbus_msg) + size_for_items;
800 msg = dbus_malloc (msg_size);
804 msg->size = msg_size;
806 msg->priority = priority;
807 msg->dst_id = dst_id;
808 msg->src_id = src_id;
809 msg->payload_type = payload_type;
810 msg->cookie = cookie;
811 msg->timeout_ns = timeout_ns_or_cookie_reply;
817 _kdbus_free_msg (struct kdbus_msg *msg)
823 _kdbus_free_mem (kdbus_t *kdbus, void *mem)
825 char *base_ptr = kdbus->mmap_ptr;
826 char *mem_ptr = (char *)mem;
828 return free_by_offset (kdbus, mem_ptr - base_ptr);
832 * Computes size of items that will be attached to a message.
834 * @param kdbus kdbus object
835 * @param destination Well-known name or NULL. If NULL, dst_id must be supplied.
836 * @param dst_id Numeric id of recipient. Ignored if name is not NULL.
837 * @param body_size Size of message body (may be 0).
838 * @param use_memfd Flag to build memfd message.
839 * @param fds_count Number of file descriptors sent in the message.
840 * @returns size in bytes needed for the message object
843 _kdbus_compute_msg_items_size (kdbus_t *kdbus,
844 const char *destination,
847 dbus_bool_t use_memfd,
850 __u64 items_size = 0;
853 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
858 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_memfd));
861 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
865 __u64 vectors = (body_size + KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE - 1)
866 / KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
867 /* subsequent vectors -> parts of body */
868 items_size += vectors * KDBUS_ITEM_SIZE (sizeof (struct kdbus_vec));
872 items_size += KDBUS_ITEM_SIZE (sizeof (int) * fds_count);
875 items_size += KDBUS_ITEM_SIZE (strlen (destination) + 1);
876 else if (KDBUS_DST_ID_BROADCAST == dst_id)
877 items_size += KDBUS_ITEM_SIZE (sizeof (struct kdbus_bloom_filter))
884 * Asks the bus to assign the given name to the connection.
886 * Use same flags as original dbus version with one exception below.
887 * Result flag #DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER is currently
888 * never returned by kdbus, instead DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
889 * is returned by kdbus.
891 * @param transport transport of the connection
892 * @param name the name to request
894 * @returns a DBus result code on success, -errno on error
897 _kdbus_request_name (kdbus_t *kdbus,
901 struct kdbus_cmd *cmd_name;
902 size_t len = strlen (name) + 1;
903 __u64 size = sizeof (*cmd_name) + KDBUS_ITEM_SIZE (len);
904 __u64 flags_kdbus = 0;
906 cmd_name = alloca (size);
907 cmd_name->size = size;
909 if (flags & DBUS_NAME_FLAG_ALLOW_REPLACEMENT)
910 flags_kdbus |= KDBUS_NAME_ALLOW_REPLACEMENT;
911 if (!(flags & DBUS_NAME_FLAG_DO_NOT_QUEUE))
912 flags_kdbus |= KDBUS_NAME_QUEUE;
913 if (flags & DBUS_NAME_FLAG_REPLACE_EXISTING)
914 flags_kdbus |= KDBUS_NAME_REPLACE_EXISTING;
916 cmd_name->flags = flags_kdbus;
917 make_item_name (name, &(cmd_name->items[0]));
919 _dbus_verbose ("Request name - flags sent: 0x%llx !!!!!!!!!\n", cmd_name->flags);
921 if (ioctl (kdbus->fd, KDBUS_CMD_NAME_ACQUIRE, cmd_name) < 0)
923 _dbus_verbose ("error acquiring name '%s': %m, %d\n", name, errno);
925 return DBUS_REQUEST_NAME_REPLY_EXISTS;
926 if (errno == EALREADY)
927 return DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
930 else if ((cmd_name->return_flags & KDBUS_NAME_PRIMARY)
931 && !(cmd_name->return_flags & KDBUS_NAME_ACQUIRED))
932 return DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER;
934 _dbus_verbose ("Request name - received flag: 0x%llx !!!!!!!!!\n", cmd_name->flags);
936 if (cmd_name->return_flags & KDBUS_NAME_IN_QUEUE)
937 return DBUS_REQUEST_NAME_REPLY_IN_QUEUE;
939 return DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
944 * Releases well-known name - the connections resign from the name
945 * which can be then assigned to another connection or the connection
946 * is being removed from the queue for that name
948 * @param name the name to request
949 * @param id unique id of the connection for which the name is being released
950 * @returns a DBus result code on success, -errno on error
953 _kdbus_release_name (kdbus_t *kdbus,
956 struct kdbus_cmd *cmd_name;
957 size_t len = strlen (name)+1;
958 __u64 size = sizeof (*cmd_name) + KDBUS_ITEM_SIZE (len);
960 cmd_name = alloca (size);
961 cmd_name->size = size;
963 make_item_name (name, &(cmd_name->items[0]));
965 if (ioctl (kdbus->fd, KDBUS_CMD_NAME_RELEASE, cmd_name))
967 if ((errno == ESRCH))
968 return DBUS_RELEASE_NAME_REPLY_NON_EXISTENT;
969 else if (errno == EADDRINUSE)
970 return DBUS_RELEASE_NAME_REPLY_NOT_OWNER;
971 _dbus_verbose ("error releasing name '%s'. Error: %m, %d\n", name, errno);
975 _dbus_verbose ("Name '%s' released\n", name);
977 return DBUS_RELEASE_NAME_REPLY_RELEASED;
981 decode_connection_info (struct kdbus_info *connection_info,
982 struct nameInfo *pInfo,
983 dbus_bool_t get_sec_label)
985 struct kdbus_item *item;
987 memset (pInfo, 0, sizeof (*pInfo));
989 pInfo->uniqueId = connection_info->id;
990 pInfo->flags = connection_info->flags;
992 item = connection_info->items;
994 while ((uint8_t *)item < ((uint8_t *)connection_info) + connection_info->size)
998 case KDBUS_ITEM_PIDS:
999 pInfo->processId = item->pids.pid;
1001 case KDBUS_ITEM_CREDS:
1002 pInfo->userId = item->creds.uid;
1004 case KDBUS_ITEM_SECLABEL:
1007 pInfo->sec_label_len = item->size - KDBUS_ITEM_HEADER_SIZE;
1008 if (0 != pInfo->sec_label_len)
1010 pInfo->sec_label = dbus_malloc (pInfo->sec_label_len);
1011 if (NULL == pInfo->sec_label)
1014 memcpy (pInfo->sec_label, item->data, pInfo->sec_label_len);
1020 item = KDBUS_ITEM_NEXT (item);
1026 process_connection_info_cmd (kdbus_t *kdbus,
1027 struct kdbus_cmd_info *cmd,
1028 struct nameInfo *pInfo,
1029 dbus_bool_t get_sec_label)
1032 struct kdbus_info *kdbus_info;
1037 ret = safe_ioctl (kdbus->fd, KDBUS_CMD_CONN_INFO, cmd);
1041 pInfo->uniqueId = 0;
1046 kdbus_info = get_from_offset (kdbus, cmd->offset);
1047 ret = decode_connection_info (kdbus_info,
1055 ret = free_by_offset (kdbus, cmd->offset);
1058 _dbus_verbose ("kdbus error freeing pool: %d (%m)\n", errno);
1061 free (pInfo->sec_label);
1062 pInfo->sec_label = NULL;
1072 * In this function either id is equal to 0 AND name is not NULL,
1073 * or id is greater than 0 AND name is NULL.
1074 * Thus, condition NULL != name is equivalent to 0 == id.
1076 static struct kdbus_cmd_info *
1077 prepare_connection_info_cmd (__u64 id,
1079 dbus_bool_t get_sec_label)
1081 struct kdbus_cmd_info *cmd;
1082 __u64 size = sizeof (*cmd);
1085 size += KDBUS_ITEM_SIZE (strlen (name) + 1);
1087 cmd = dbus_malloc (size);
1094 make_item_name (name, &(cmd->items[0]));
1096 cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_PIDS;
1098 cmd->attach_flags |= KDBUS_ATTACH_SECLABEL;
1106 * Gets connection info for the given unique id.
1108 * @param kdbus kdbus object
1109 * @param id unique id to query for
1110 * @param get_sec_label #TRUE if sec_label field in pInfo should be filled
1111 * @param pInfo nameInfo structure address to store info about the name
1112 * @return 0 on success, errno if failed
1114 * @note If you specify #TRUE in get_sec_label param, you must free
1115 * pInfo.sec_label with dbus_free() after use.
1118 _kdbus_connection_info_by_id (kdbus_t *kdbus,
1120 dbus_bool_t get_sec_label,
1121 struct nameInfo *pInfo)
1123 struct kdbus_cmd_info *cmd = prepare_connection_info_cmd (id, NULL, get_sec_label);
1125 return process_connection_info_cmd (kdbus, cmd, pInfo, get_sec_label);
1129 * Gets connection info for the given name
1131 * @param kdbus kdbus object
1132 * @param name name to query for
1133 * @param get_sec_label #TRUE if sec_label field in pInfo should be filled
1134 * @param pInfo nameInfo structure address to store info about the name
1135 * @return 0 on success, errno if failed
1137 * @note If you specify #TRUE in get_sec_label param, you must free
1138 * pInfo.sec_label with dbus_free() after use.
1141 _kdbus_connection_info_by_name (kdbus_t *kdbus,
1143 dbus_bool_t get_sec_label,
1144 struct nameInfo *pInfo)
1146 struct kdbus_cmd_info *cmd;
1148 /* if name starts with ":1." it is a unique name and should be send as number */
1149 if ((name[0] == ':') && (name[1] == '1') && (name[2] == '.'))
1151 return _kdbus_connection_info_by_id (kdbus,
1152 strtoull (&name[3], NULL, 10),
1157 cmd = prepare_connection_info_cmd (0, name, get_sec_label);
1159 return process_connection_info_cmd (kdbus, cmd, pInfo, get_sec_label);
1163 * Removes match rule in kdbus on behalf of sender of the message
1164 * @param kdbus kdbus object
1165 * @param cookie cookie of the rules to be removed
1168 _kdbus_remove_match (kdbus_t *kdbus,
1171 struct kdbus_cmd_match cmd;
1173 VALGRIND_MAKE_MEM_DEFINED (&cmd, sizeof (cmd));
1175 cmd.cookie = cookie;
1176 cmd.size = sizeof (struct kdbus_cmd_match);
1179 if (safe_ioctl (kdbus->fd, KDBUS_CMD_MATCH_REMOVE, &cmd) != 0)
1185 /************************* BLOOM FILTERS ***********************/
1188 * Macros for SipHash algorithm
1190 #define ROTL(x,b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )
1192 #define U32TO8_LE(p, v) \
1193 (p)[0] = (unsigned char)((v) ); (p)[1] = (unsigned char)((v) >> 8); \
1194 (p)[2] = (unsigned char)((v) >> 16); (p)[3] = (unsigned char)((v) >> 24);
1196 #define U64TO8_LE(p, v) \
1197 U32TO8_LE((p), (uint32_t)((v) )); \
1198 U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
1200 #define U8TO64_LE(p) \
1201 (((uint64_t)((p)[0]) ) | \
1202 ((uint64_t)((p)[1]) << 8) | \
1203 ((uint64_t)((p)[2]) << 16) | \
1204 ((uint64_t)((p)[3]) << 24) | \
1205 ((uint64_t)((p)[4]) << 32) | \
1206 ((uint64_t)((p)[5]) << 40) | \
1207 ((uint64_t)((p)[6]) << 48) | \
1208 ((uint64_t)((p)[7]) << 56))
1212 v0 += v1; v1=ROTL(v1,13); v1 ^= v0; v0=ROTL(v0,32); \
1213 v2 += v3; v3=ROTL(v3,16); v3 ^= v2; \
1214 v0 += v3; v3=ROTL(v3,21); v3 ^= v0; \
1215 v2 += v1; v1=ROTL(v1,17); v1 ^= v2; v2=ROTL(v2,32); \
1220 * Hash keys for bloom filters
1222 static const unsigned char hash_keys[8][16] =
1224 {0xb9,0x66,0x0b,0xf0,0x46,0x70,0x47,0xc1,0x88,0x75,0xc4,0x9c,0x54,0xb9,0xbd,0x15},
1225 {0xaa,0xa1,0x54,0xa2,0xe0,0x71,0x4b,0x39,0xbf,0xe1,0xdd,0x2e,0x9f,0xc5,0x4a,0x3b},
1226 {0x63,0xfd,0xae,0xbe,0xcd,0x82,0x48,0x12,0xa1,0x6e,0x41,0x26,0xcb,0xfa,0xa0,0xc8},
1227 {0x23,0xbe,0x45,0x29,0x32,0xd2,0x46,0x2d,0x82,0x03,0x52,0x28,0xfe,0x37,0x17,0xf5},
1228 {0x56,0x3b,0xbf,0xee,0x5a,0x4f,0x43,0x39,0xaf,0xaa,0x94,0x08,0xdf,0xf0,0xfc,0x10},
1229 {0x31,0x80,0xc8,0x73,0xc7,0xea,0x46,0xd3,0xaa,0x25,0x75,0x0f,0x9e,0x4c,0x09,0x29},
1230 {0x7d,0xf7,0x18,0x4b,0x7b,0xa4,0x44,0xd5,0x85,0x3c,0x06,0xe0,0x65,0x53,0x96,0x6d},
1231 {0xf2,0x77,0xe9,0x6f,0x93,0xb5,0x4e,0x71,0x9a,0x0c,0x34,0x88,0x39,0x25,0xbf,0x35}
1238 _g_siphash24 (unsigned char out[8],
1241 const unsigned char k[16])
1243 uint64_t v0 = 0x736f6d6570736575ULL;
1244 uint64_t v1 = 0x646f72616e646f6dULL;
1245 uint64_t v2 = 0x6c7967656e657261ULL;
1246 uint64_t v3 = 0x7465646279746573ULL;
1248 uint64_t k0 = U8TO64_LE (k);
1249 uint64_t k1 = U8TO64_LE (k + 8);
1251 const unsigned char *in = _in;
1252 const unsigned char *end = in + inlen - (inlen % sizeof (uint64_t));
1253 const int left = inlen & 7;
1254 b = ((uint64_t) inlen) << 56;
1260 for (; in != end; in += 8)
1271 case 7: b |= ((uint64_t) in[6]) << 48;
1272 case 6: b |= ((uint64_t) in[5]) << 40;
1273 case 5: b |= ((uint64_t) in[4]) << 32;
1274 case 4: b |= ((uint64_t) in[3]) << 24;
1275 case 3: b |= ((uint64_t) in[2]) << 16;
1276 case 2: b |= ((uint64_t) in[1]) << 8;
1277 case 1: b |= ((uint64_t) in[0]); break;
1291 b = v0 ^ v1 ^ v2 ^ v3;
1296 _kdbus_bloom_add_data (kdbus_t *kdbus,
1297 kdbus_bloom_data_t *bloom_data,
1301 unsigned char hash[8];
1303 unsigned int bytes_num = 0;
1304 unsigned int cnt_1, cnt_2;
1305 unsigned int hash_index = 0;
1310 bit_num = kdbus->bloom.size * 8;
1313 bytes_num = ((__builtin_clzll (bit_num) ^ 63U) + 7) / 8;
1315 for (cnt_1 = 0; cnt_1 < kdbus->bloom.n_hash; cnt_1++)
1317 for (cnt_2 = 0, hash_index = 0; cnt_2 < bytes_num; cnt_2++)
1321 _g_siphash24 (hash, data, data_size, hash_keys[hash_index++]);
1325 p = (p << 8ULL) | (uint64_t) hash[8 - c];
1330 bloom_data[p >> 6] |= 1ULL << (p & 63);