int size = ALIGN8(sizeof(struct kdbus_cmd_hello)) + ALIGN8(offsetof(struct kdbus_item, data) + sizeof(CONNECTION_LABEL));
cmd = calloc(1, size);
+ if (!cmd)
+ goto err;
cmd->size = size;
cmd->flags = hello_flags;
cmd->attach_flags_send = attach_flags_send;
g_udesc.uid = uid;
g_udesc.gid = gid;
if (label)
- strcpy (g_udesc.label, label);
+ strncpy (g_udesc.label, label, strlen(label) + 1);
}
#endif
static bool configuration_bus_type(struct kconn const *configuration) { return configuration != g_conn; }
+union kdbus_cmd_union {
+ struct kdbus_cmd_info cmd_info;
+ struct kdbus_cmd_free cmd_free;
+ uint8_t _buffer_[sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(MAX_DBUS_NAME_LEN+1)];
+};
+
+struct kdbus_cmd_param {
+ char const *label;
+ const char* k_names[KDBUS_CONN_MAX_NAMES+1];
+ uid_t uid_n;
+ gid_t gid_n;
+ bool free_offset;
+ bool empty_names;
+ union kdbus_cmd_union cmd;
+};
+
+int kdbus_get_conn_info(bool bus_type, const char *destination, int message_type, struct kdbus_cmd_param *info)
+{
+ char const *label = NULL;
+ const char** k_names = info->k_names;
+ int k_i = 0;
+ int r;
+ uid_t uid_n = UID_INVALID;
+ gid_t gid_n = GID_INVALID;
+ bool free_offset = false;
+ bool empty_names = true;
+ union kdbus_cmd_union *cmd = &info->cmd;
+
+ struct kdbus_info *conn_info;
+ struct kdbus_item *item;
+ uintptr_t items_end;
+
+ cmd->cmd_info.flags = 0;
+ cmd->cmd_info.attach_flags = (__u64)(KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type ? KDBUS_ATTACH_SECLABEL : 0));
+
+ if (kdbus_is_unique_id(destination)) {
+ cmd->cmd_info.size = sizeof(cmd->cmd_info);
+ cmd->cmd_info.id = kdbus_unique_id(destination);
+ } else {
+ unsigned int l = strlen(destination);
+ cmd->cmd_info.size = sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(l+1);
+ cmd->cmd_info.id = 0;
+ cmd->cmd_info.items->size = (__u64)offsetof(struct kdbus_item, data) + (__u64)l + (__u64)1;
+ cmd->cmd_info.items->type = KDBUS_ITEM_NAME;
+ *(uint64_t*)ALIGNDN8((uintptr_t)cmd->cmd_info.items->str + l) = 0; /* trailing zero + padding */
+ memcpy(cmd->cmd_info.items->str, destination, l);
+ }
+ r = ioctl(g_conn[bus_type].fd, KDBUS_CMD_CONN_INFO, &cmd->cmd_info);
+ if (r < 0) {
+ if (errno == ENXIO || errno == ESRCH)
+ r = DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE;
+ else
+ r = DBUSPOLICY_RESULT_KDBUS_ERROR;
+ goto end;
+ }
+
+ cmd->cmd_free.size = sizeof(cmd->cmd_free);
+ /* flags already 0 */
+ _Static_assert(sizeof(cmd->cmd_info.flags) == sizeof(cmd->cmd_free.flags), "cmd_info/cmd_free: flag sizeof differs");
+ _Static_assert(offsetof(typeof(cmd->cmd_info), flags) == offsetof(typeof(cmd->cmd_free), flags), "cmd_info/cmd_free: flag offsetof differs");
+ cmd->cmd_free.offset = cmd->cmd_info.offset;
+
+ free_offset = true;
+
+ conn_info = (struct kdbus_info *) ((uint8_t *) g_conn[bus_type].pool + cmd->cmd_info.offset);
+ items_end = (uintptr_t)conn_info + (unsigned)conn_info->size;
+
+ _Static_assert((unsigned)KDBUS_ITEM_CREDS == KDBUS_ITEM_CREDS, "KDBUS_ITEM_CREDS not preserved when cast to unsigned");
+ _Static_assert((unsigned)KDBUS_ITEM_SECLABEL == KDBUS_ITEM_SECLABEL, "KDBUS_ITEM_SECLABEL not preserved when cast to unsigned");
+ _Static_assert((unsigned)KDBUS_ITEM_OWNED_NAME == KDBUS_ITEM_OWNED_NAME, "KDBUS_ITEM_OWNED_NAME not preserved when cast to unsigned");
+
+ for (item = conn_info->items; (uintptr_t)item < items_end; item = (typeof(item))ALIGN8((uintptr_t)item + (unsigned)item->size))
+ switch ((unsigned)item->type)
+ {
+ case KDBUS_ITEM_CREDS:
+ uid_n = item->creds.euid;
+ gid_n = item->creds.egid;
+ break;
+ case KDBUS_ITEM_SECLABEL:
+ label = item->str;
+ break;
+ case KDBUS_ITEM_OWNED_NAME:
+ empty_names = false;
+ k_names[k_i++] = item->name.name;
+ break;
+ }
+ if (!empty_names)
+ k_names[k_i++] = NULL;
+
+end:
+ info->label = label;
+ info->uid_n = uid_n;
+ info->gid_n = gid_n;
+ info->free_offset = free_offset;
+ info->empty_names = empty_names;
+
+ return r;
+}
+
DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
const char *destination,
const char *sender,
(void)reply_serial;
(void)requested_reply;
- char const *label = NULL;
- const char* k_names[KDBUS_CONN_MAX_NAMES+1];
- int k_i = 0;
int r;
- uid_t uid_n = UID_INVALID;
- gid_t gid_n = GID_INVALID;
- bool free_offset = false;
- bool empty_names = true;
bool bus_type = configuration_bus_type(configuration);
- union {
- struct kdbus_cmd_info cmd_info;
- struct kdbus_cmd_free cmd_free;
- uint8_t _buffer_[sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(MAX_DBUS_NAME_LEN+1)];
- } cmd;
+ struct kdbus_cmd_param info = {
+ .free_offset = false,
+ .empty_names = true
+ };
+ union kdbus_cmd_union *cmd = &info.cmd;
+ char *dest_label = NULL;
+
+ /* Broadcast signal has NULL destination */
+ /* Due to this sender can not check rule correctly */
+ if (message_type == DBUSPOLICY_MESSAGE_TYPE_SIGNAL && !destination)
+ return 1;
__internal_enter();
- if (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type || (destination && *destination)) {
- struct kdbus_info *conn_info;
- struct kdbus_item *item;
- uintptr_t items_end;
-
- cmd.cmd_info.flags = 0;
- cmd.cmd_info.attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type ? KDBUS_ATTACH_SECLABEL : 0);
-
- if (kdbus_is_unique_id(destination)) {
- cmd.cmd_info.size = sizeof(cmd.cmd_info);
- cmd.cmd_info.id = kdbus_unique_id(destination);
- } else {
- int l = strlen(destination);
- cmd.cmd_info.size = sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(l+1);
- cmd.cmd_info.id = 0;
- cmd.cmd_info.items->size = offsetof(struct kdbus_item, data) + l+1;
- cmd.cmd_info.items->type = KDBUS_ITEM_NAME;
- *(uint64_t*)ALIGNDN8((uintptr_t)cmd.cmd_info.items->str + l) = 0; /* trailing zero + padding */
- memcpy(cmd.cmd_info.items->str, destination, l);
- }
- r = ioctl(g_conn[bus_type].fd, KDBUS_CMD_CONN_INFO, &cmd.cmd_info);
- if (r < 0) {
- if (errno == ENXIO || errno == ESRCH)
- r = DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE;
- else
- r = DBUSPOLICY_RESULT_KDBUS_ERROR;
+ /* check can send */
+ /* if broadcasting, then pass - null destination */
+ if (destination && *destination) {
+ r = kdbus_get_conn_info(bus_type, destination, message_type, &info);
+ if (r < 0)
goto end;
- }
-
- cmd.cmd_free.size = sizeof(cmd.cmd_free);
- /* flags already 0 */
- _Static_assert(sizeof(cmd.cmd_info.flags) == sizeof(cmd.cmd_free.flags), "cmd_info/cmd_free: flag sizeof differs");
- _Static_assert(offsetof(typeof(cmd.cmd_info), flags) == offsetof(typeof(cmd.cmd_free), flags), "cmd_info/cmd_free: flag offsetof differs");
- cmd.cmd_free.offset = cmd.cmd_info.offset;
-
- free_offset = true;
-
- conn_info = (struct kdbus_info *) ((uint8_t *) g_conn[bus_type].pool + cmd.cmd_info.offset);
- items_end = (uintptr_t)conn_info + (unsigned)conn_info->size;
-
- _Static_assert((unsigned)KDBUS_ITEM_CREDS == KDBUS_ITEM_CREDS, "KDBUS_ITEM_CREDS not preserved when cast to unsigned");
- _Static_assert((unsigned)KDBUS_ITEM_SECLABEL == KDBUS_ITEM_SECLABEL, "KDBUS_ITEM_SECLABEL not preserved when cast to unsigned");
- _Static_assert((unsigned)KDBUS_ITEM_OWNED_NAME == KDBUS_ITEM_OWNED_NAME, "KDBUS_ITEM_OWNED_NAME not preserved when cast to unsigned");
-
- for (item = conn_info->items; (uintptr_t)item < items_end; item = (typeof(item))ALIGN8((uintptr_t)item + (unsigned)item->size))
- switch ((unsigned)item->type)
- {
- case KDBUS_ITEM_CREDS:
- uid_n = item->creds.euid;
- gid_n = item->creds.egid;
- break;
- case KDBUS_ITEM_SECLABEL:
- label = item->str;
- break;
- case KDBUS_ITEM_OWNED_NAME:
- empty_names = false;
- k_names[k_i++] = item->name.name;
- break;
- }
}
- if (empty_names)
+ if (info.empty_names)
r = __internal_can_send(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, destination, path, interface, member, message_type);
- else {
- k_names[k_i++] = NULL;
- r = __internal_can_send_multi_dest(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, k_names, path, interface, member, message_type);
- }
+ else
+ r = __internal_can_send_multi_dest(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, info.k_names, path, interface, member, message_type);
+
if (r <= 0)
goto end;
- if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
- sender = NULL;
- r = __internal_can_recv(bus_type, uid_n, gid_n, label, sender, path, interface, member, message_type);
+ uid_t dest_uid_n = 0;
+ gid_t dest_gid_n = 0;
+
+ /* copy & free */
+ if (destination && *destination) {
+ dest_uid_n = info.uid_n;
+ dest_gid_n = info.gid_n;
+
+ if (info.label) {
+ dest_label = (char*)malloc(sizeof(char) * strlen(info.label) + 1);
+ strncpy(dest_label, info.label, strlen(info.label) + 1);
+ }
+ if (info.free_offset)
+ ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd->cmd_free);
+
+ info.free_offset = false;
+ info.empty_names = true;
+ }
+
+ /* check can recv */
+ /* get sender information from kdbus */
+ r = kdbus_get_conn_info(bus_type, sender, message_type, &info);
+ if (r < 0) {
+ fprintf(stderr, "failed to kdbus conn info:%d\n", r);
+ goto end;
}
+ if (info.empty_names)
+ r = __internal_can_recv(bus_type, dest_uid_n, dest_gid_n, dest_label, sender, path, interface, member, message_type);
+ else
+ r = __internal_can_recv_multi(bus_type, dest_uid_n, dest_gid_n, dest_label, info.k_names, path, interface, member, message_type);
+
end:
- if (free_offset)
- ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd.cmd_free);
+ if (info.free_offset)
+ ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd->cmd_free);
+ if (dest_label)
+ free(dest_label);
__internal_exit();
+
return r;
}
int r;
bool bus_type = configuration_bus_type(configuration);
+ struct kdbus_cmd_param info = {
+ .free_offset = false,
+ .empty_names = true
+ };
__internal_enter();
- r = __internal_can_send(bus_type, sender_uid, sender_gid, sender_label, destination, path, interface, member, message_type);
+ if (destination && *destination) {
+ r = kdbus_get_conn_info(bus_type, destination, message_type, &info);
+ if (r < 0)
+ goto end;
+ }
+
+ if (info.empty_names)
+ r = __internal_can_send(bus_type, sender_uid, sender_gid, sender_label, destination, path, interface, member, message_type);
+ else
+ r = __internal_can_send_multi_dest(bus_type, sender_uid, sender_gid, sender_label, info.k_names, path, interface, member, message_type);
+
if (r <= 0)
goto end;
- if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
- r = __internal_can_recv(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, sender, path, interface, member, message_type);
- if (r <= 0)
- goto end;
- }
+ /* libdbus, gdbus pass multiple sender as parameter : eg. "name_A name_B name_C". */
+ /* Because of '__internal_can_recv' can check rule against multiple names, */
+ /* it is not needed to use __internal_can_recv_multi here. */
+ r = __internal_can_recv(bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, sender, path, interface, member, message_type);
+ if (r <= 0)
+ goto end;
end:
+ if (info.free_offset)
+ ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &info.cmd.cmd_free);
+
__internal_exit();
return r;
}