introduce KdbusConnection and KdbusConnectionInfo classes 55/202555/6
authorAdrian Szyndela <adrian.s@samsung.com>
Fri, 29 Mar 2019 15:27:51 +0000 (16:27 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Wed, 3 Apr 2019 07:07:01 +0000 (09:07 +0200)
Change-Id: Ie9b80624f6f6d09e08338ed68e23657f5dc33480

src/kdbus.cpp
src/kdbus.h
src/libdbuspolicy1.cpp

index b76b201..5802625 100644 (file)
 #include <dlog/dlog.h>
 
 #include <linux/kdbus.h>
-#include <errno.h>
+#include <cerrno>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
-#include <stdbool.h>
 #include <cassert>
+#include <cstddef>
+#include <memory>
 
 #define CONNECTION_LABEL "libdbuspolicy1-kdbus"
 
@@ -34,8 +35,6 @@
 
 #define ALIGN8(l) (((l) + 7) & ~7)
 #define ALIGNDN8(l) ((l) & ~7)
-#define UID_INVALID ((uid_t) -1)
-#define GID_INVALID ((gid_t) -1)
 
 #define MAX_DBUS_NAME_LEN 255
 
@@ -73,12 +72,10 @@ public:
        T *get() { return reinterpret_cast<T*>(buffer); }
 };
 
-int kdbus_free_by_offset(kdbus_connection *conn, __u64 offset);
-
-static int kdbus_open_bus(kdbus_connection *conn, const char *path)
+int KdbusConnection::open_bus(const char *path)
 {
-       conn->fd = open(path, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC);
-       return conn->fd;
+       fd = open(path, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC);
+       return fd;
 }
 
 static void set_item_str(kdbus_item *item, const char *str, __u64 str_length, __u64 type)
@@ -88,10 +85,9 @@ static void set_item_str(kdbus_item *item, const char *str, __u64 str_length, __
        memcpy(item->str, str, str_length);
 }
 
-static int kdbus_hello(kdbus_connection *conn,
-                                          uint64_t hello_flags,
-                                          uint64_t attach_flags_send,
-                                          uint64_t attach_flags_recv)
+int KdbusConnection::hello(uint64_t hello_flags,
+                                                  uint64_t attach_flags_send,
+                                                  uint64_t attach_flags_recv)
 {
        kdbus_command<kdbus_cmd_hello, KDBUS_ITEM_SIZE_ALIGN(sizeof(CONNECTION_LABEL))> command(hello_flags);
        auto cmd = command.get();
@@ -102,47 +98,36 @@ static int kdbus_hello(kdbus_connection *conn,
 
        set_item_str(cmd->items, CONNECTION_LABEL, sizeof(CONNECTION_LABEL), KDBUS_ITEM_CONN_DESCRIPTION);
 
-       if (ioctl(conn->fd, KDBUS_CMD_HELLO, cmd) < 0)
+       if (ioctl(fd, KDBUS_CMD_HELLO, cmd) < 0)
                return -errno;
 
-       kdbus_free_by_offset(conn, cmd->offset);
+       free_by_offset(cmd->offset);
 
-       conn->pool = static_cast<char *>(mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, conn->fd, 0));
-       if (MAP_FAILED == conn->pool)
+       pool = static_cast<decltype(pool)>(mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0));
+       if (MAP_FAILED == pool)
                return -errno;
 
        return 0;
 }
 
-void kdbus_shared_init_fd(kdbus_connection *conn, int fd)
-{
-       conn->fd = fd;
-}
-
-void kdbus_shared_init_pool(kdbus_connection *conn, void *pool)
-{
-       conn->pool = static_cast<char*>(pool);
-}
-
-int kdbus_connect(kdbus_connection *conn,
-                                 const char *path,
-                                 uint64_t hello_flags,
-                                 uint64_t attach_flags_send,
-                                 uint64_t attach_flags_recv)
+int KdbusConnection::connect(const char *path,
+                                                        uint64_t hello_flags,
+                                                        uint64_t attach_flags_send,
+                                                        uint64_t attach_flags_recv)
 {
-       if ((conn->fd = kdbus_open_bus(conn, path)) < 0) {
+       if (open_bus(path) < 0) {
                LOGE("Error opening bus: %s", path);
                return -1;
        }
-       if (kdbus_hello(conn, hello_flags, attach_flags_send, attach_flags_recv) < 0) {
+       if (hello(hello_flags, attach_flags_send, attach_flags_recv) < 0) {
                LOGE("Error: bus hello failed");
-               close(conn->fd);
+               close(fd);
                return -1;
        }
        return 0;
 }
 
-static bool kdbus_is_unique_id(const char* name)
+constexpr bool kdbus_is_unique_id(const char* name)
 {
        return ':' == name[0];
 }
@@ -161,79 +146,89 @@ static uint64_t kdbus_unique_id(char const *name)
        return res;
 }
 
-int kdbus_get_conn_info(kdbus_connection *conn,
-                                               const char *destination,
-                                               kdbus_cmd_param *info,
-                                               conn_info_type conn_info_type)
+int KdbusConnection::get_conn_info(const char *bus_name,
+                                                                  conn_info_type conn_info_type,
+                                                                  KdbusConnectionInfo *info)
 {
        kdbus_command<kdbus_cmd_info, KDBUS_ITEM_SIZE_ALIGN(ALIGN8(MAX_DBUS_NAME_LEN+1))> command(0, 0);
        auto cmd = command.get();
 
-       char const *label = NULL;
-       uid_t uid_n = UID_INVALID;
-       gid_t gid_n = GID_INVALID;
-
-       cmd->flags = 0;
        if (conn_info_type == POLICY_CONN_INFO_ALL)
                cmd->attach_flags = (KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | KDBUS_ATTACH_SECLABEL);
        else
                cmd->attach_flags = KDBUS_ATTACH_NAMES;
 
-       if (kdbus_is_unique_id(destination)) {
-               cmd->id = kdbus_unique_id(destination);
+       if (kdbus_is_unique_id(bus_name)) {
+               cmd->id = kdbus_unique_id(bus_name);
        } else {
-               auto l = strlen(destination);
-               cmd->size += KDBUS_ITEM_SIZE_ALIGN(ALIGN8(l+1));
+               auto l = strlen(bus_name);
+               cmd->size += KDBUS_ITEM_SIZE_ALIGN(l+1);
                cmd->id = 0;
-               set_item_str(cmd->items, destination, l+1, KDBUS_ITEM_NAME);
+
+               set_item_str(cmd->items, bus_name, l+1, KDBUS_ITEM_NAME);
        }
-       if (ioctl(conn->fd, KDBUS_CMD_CONN_INFO, cmd) < 0) {
+       if (ioctl(fd, KDBUS_CMD_CONN_INFO, cmd) < 0) {
                if (errno == ENXIO || errno == ESRCH)
                        return DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE;
 
                return DBUSPOLICY_RESULT_KDBUS_ERROR;
        }
 
-       info->free_offset = cmd->offset;
+       info->setNewData(cmd->offset);
 
-       auto conn_info = reinterpret_cast<kdbus_info *>((uint8_t *) conn->pool + cmd->offset);
+       auto conn_info = reinterpret_cast<kdbus_info *>(pool + cmd->offset);
        uintptr_t items_end = (uintptr_t)conn_info + (size_t)conn_info->size;
 
-       info->names_num = 0;
        for (auto item = conn_info->items;
                        (uintptr_t)item < items_end;
                        item = reinterpret_cast<decltype(item)>(ALIGN8((uintptr_t)item + (size_t)item->size))) {
                switch (item->type) {
                case KDBUS_ITEM_CREDS:
-                       uid_n = item->creds.euid;
-                       gid_n = item->creds.egid;
+                       info->setCreds(item->creds.euid, item->creds.egid);
                        break;
                case KDBUS_ITEM_SECLABEL:
-                       label = item->str;
+                       info->setLabel(item->str);
                        break;
                case KDBUS_ITEM_OWNED_NAME:
-                       info->k_names[info->names_num++] = item->name.name;
+                       info->addName(item->name.name);
                        break;
                }
        }
 
-       info->label = label;
-       info->uid_n = uid_n;
-       info->gid_n = gid_n;
-
        return 0;
 }
 
-int kdbus_free_by_offset(kdbus_connection *conn, __u64 offset)
+int KdbusConnection::free_by_offset(uint64_t offset)
 {
        kdbus_command<kdbus_cmd_free> command;
        auto cmd = command.get();
        cmd->offset = offset;
 
-       if (ioctl(conn->fd, KDBUS_CMD_FREE, cmd) != 0) {
+       if (ioctl(fd, KDBUS_CMD_FREE, cmd) != 0) {
                LOGE("failed KDBUS_CMD_FREE");
                return errno;
        }
 
        return 0;
 }
+
+void KdbusConnectionInfo::release_info()
+{
+       if (set) {
+               my_connection.free_by_offset(free_offset);
+               set = false;
+       }
+}
+
+void KdbusConnectionInfo::setNewData(uint64_t offset)
+{
+       release_info();
+
+       free_offset = offset;
+       set = true;
+
+       names_num = 0;
+       _label = nullptr;
+       uid_n = UID_INVALID;
+       gid_n = GID_INVALID;
+}
index 55fe607..7183937 100644 (file)
 
 #define KDBUS_CONN_MAX_NAMES 256
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+class KdbusConnectionInfo;
 
-struct kdbus_connection {
+class KdbusConnection {
        int fd;
-       char *pool;
-};
+       uint8_t *pool;
 
-typedef struct kdbus_connection kdbus_connection;
+       int open_bus(const char *path);
+       int hello(uint64_t hello_flags,
+                         uint64_t attach_flags_send,
+                         uint64_t attach_flags_recv);
+public:
+       typedef enum { POLICY_CONN_INFO_ALL, POLICY_CONN_INFO_NAME } conn_info_type;
 
-struct kdbus_cmd_param {
-       char const *label;
-       const char* k_names[KDBUS_CONN_MAX_NAMES];
-       __u64 free_offset;
-       uid_t uid_n;
-       gid_t gid_n;
-       uint16_t names_num;
+       void shared_init_fd(int fd_to_set) { fd = fd_to_set; }
+       void shared_init_pool(void *pool_to_set) { pool = static_cast<decltype(pool)>(pool_to_set); }
+       int connect(const char *path,
+                               uint64_t hello_flags,
+                               uint64_t attach_flags_send,
+                               uint64_t attach_flags_recv);
+       int get_conn_info(const char *bus_name,
+                                         conn_info_type conn_info_type,
+                                         KdbusConnectionInfo *info);
+       int free_by_offset(uint64_t offset);
 };
 
-void kdbus_shared_init_fd(kdbus_connection *conn, int fd);
-void kdbus_shared_init_pool(kdbus_connection *conn, void *pool);
+class KdbusConnectionInfo {
+       static const uid_t UID_INVALID = -1;
+       static const gid_t GID_INVALID = -1;
+
+       char const *_label{nullptr};
+       const char *k_names[KDBUS_CONN_MAX_NAMES]{};
+       uint64_t free_offset{0};
+       uid_t uid_n{UID_INVALID};
+       gid_t gid_n{GID_INVALID};
+       uint16_t names_num{0};
+       bool set{false};
+
+       KdbusConnection &my_connection;
 
-int kdbus_connect(kdbus_connection *conn,
-                                 const char *path,
-                                 uint64_t hello_flags,
-                                 uint64_t attach_flags_send,
-                                 uint64_t attach_flags_recv);
+public:
+       KdbusConnectionInfo(KdbusConnection &c) : my_connection{c} {}
+       ~KdbusConnectionInfo() { release_info(); }
 
-typedef enum { POLICY_CONN_INFO_ALL, POLICY_CONN_INFO_NAME } conn_info_type;
+       void release_info();
+       void setNewData(uint64_t offset);
 
-int kdbus_get_conn_info(kdbus_connection *conn,
-                                               const char *destination,
-                                               struct kdbus_cmd_param *info,
-                                               conn_info_type conn_info_type);
+       void addName(const char *name) { k_names[names_num++] = name; }
 
-int kdbus_free_by_offset(kdbus_connection *conn, __u64 offset);
+       void setCreds(uid_t uid, gid_t gid) { uid_n = uid; gid_n = gid; }
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
+       void setLabel(const char *label) { _label = label; }
+
+       int get(const char *destination, KdbusConnection::conn_info_type conn_info_type) {
+               return my_connection.get_conn_info(destination, conn_info_type, this);
+       }
+       const char **names() { return k_names; }
+       uint16_t numberOfNames() const { return names_num; }
+       uid_t uid() const { return uid_n; }
+       gid_t gid() const { return gid_n; }
+       const char *label() const { return _label; }
+};
index 5b8b6bb..6f9b673 100644 (file)
@@ -40,7 +40,7 @@
 #define KDBUS_SYSTEM_BUS_PATH KDBUS_PATH_PREFIX"0-system/bus"
 
 struct kconn {
-       kdbus_connection conn;
+       KdbusConnection conn;
        BusType bus_type;
 } g_conn[2];
 
@@ -183,7 +183,7 @@ static void init_global_conn_locked(BusType bus_type, std::shared_ptr<const char
        struct kconn *kconn = &g_conn[bus_type];
        kconn->bus_type = bus_type;
 
-       if (kdbus_connect(&kconn->conn, resolved_path.get(), 0, _KDBUS_ATTACH_ALL, 0) < 0) {
+       if (kconn->conn.connect(resolved_path.get(), 0, _KDBUS_ATTACH_ALL, 0) < 0) {
                assert(false && "failed kdbus_connect");
        }
 }
@@ -197,12 +197,12 @@ static struct kconn *get_global_conn(BusType bus_type, std::shared_ptr<const cha
 
 static kconn *init_shared_fd(BusType bus_type, int fd)
 {
-       kconn *result = static_cast<kconn*>(malloc(sizeof(*result)));
-       if (NULL == result) {
+       kconn *result = new kconn;
+       if (nullptr == result) {
                LOGE("Error: failed to allocate memory for policy configuration");
-               return NULL;
+               return nullptr;
        }
-       kdbus_shared_init_fd(&result->conn, fd);
+       result->conn.shared_init_fd(fd);
        result->bus_type = bus_type;
        return result;
 }
@@ -229,7 +229,7 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd)
                return nullptr;
        }
 
-       struct kconn *result = NULL;
+       struct kconn *result = nullptr;
        if (can_open(bus_type, bus_owner)) {
                if (-1 == fd) {
                        result = get_global_conn(bus_type, resolved_path);
@@ -248,9 +248,12 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path)
        return dbuspolicy1_init_shared(bus_path, -1);
 }
 
+inline kconn *KCONN(void *config) { return static_cast<kconn *>(config); }
+inline KdbusConnection &KDBUS_CONN(void *config) { return KCONN(config)->conn; }
+
 DBUSPOLICY1_EXPORT void dbuspolicy1_init_set_pool(void *configuration, void *pool)
 {
-       kdbus_shared_init_pool(static_cast<kdbus_connection *>(configuration), pool);
+       KDBUS_CONN(configuration).shared_init_pool(pool);
 }
 
 DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration)
@@ -259,7 +262,7 @@ DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration)
                if (configuration == &g_conn[i])
                        return;
 
-       free(configuration);
+       delete KCONN(configuration);
 }
 
 DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
@@ -269,21 +272,10 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
                                                                                         const char *interface,
                                                                                         const char *member,
                                                                                         int         message_type,
-                                                                                        const char *error_name,
-                                                                                        int         reply_serial,
-                                                                                        int         requested_reply)
+                                                                                        const char * /*error_name*/,
+                                                                                        int         /*reply_serial*/,
+                                                                                        int         /*requested_reply*/)
 {
-       (void)error_name;
-       (void)reply_serial;
-       (void)requested_reply;
-
-       struct kconn *kconn = static_cast<struct kconn*>(configuration);
-
-       int r;
-       struct kdbus_cmd_param info = {};
-       std::string dest_label;
-       bool free_conn_info = false;
-
        /* Broadcast signal has NULL destination */
        /* Due to this sender can not check rule correctly */
        if (message_type == DBUSPOLICY_MESSAGE_TYPE_SIGNAL && !destination)
@@ -292,59 +284,38 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
        __internal_enter();
        auto internal_enter_guard = transaction_guard::makeGuard([] () { __internal_exit(); });
 
-       uid_t dest_uid_n = 0;
-       gid_t dest_gid_n = 0;
-
+       auto kconn = KCONN(configuration);
+       KdbusConnectionInfo destinationInfo(kconn->conn);
+       int r;
        /* check can send */
        /* if broadcasting, then pass - null destination */
        if (destination && *destination) {
-               r = kdbus_get_conn_info(&kconn->conn, destination, &info, POLICY_CONN_INFO_ALL);
+               r = destinationInfo.get(destination, KdbusConnection::POLICY_CONN_INFO_ALL);
                if (r < 0)
                        return r;
-               free_conn_info = true;
        }
 
        r = __internal_can_send(kconn->bus_type,
                        g_udesc.uid, g_udesc.gid, g_udesc.label,
-                       destination, info.k_names, info.names_num,
+                       destination, destinationInfo.names(), destinationInfo.numberOfNames(),
                        path, interface, member, message_type);
 
        if (r <= 0)
-               goto end;
-
-       /* copy & free */
-       if (destination && *destination) {
-               dest_uid_n = info.uid_n;
-               dest_gid_n = info.gid_n;
-
-               if (info.label)
-                       dest_label = info.label;
-
-               if (free_conn_info) {
-                       kdbus_free_by_offset(&kconn->conn, info.free_offset);
-                       free_conn_info = false;
-               }
-       }
+               return r;
 
+       KdbusConnectionInfo senderInfo(kconn->conn);
        /* check can recv */
        /* get sender information from kdbus */
-       r = kdbus_get_conn_info(&kconn->conn, sender, &info, POLICY_CONN_INFO_NAME);
+       r = senderInfo.get(sender, KdbusConnection::POLICY_CONN_INFO_NAME);
        if (r < 0) {
                fprintf(stderr, "failed to kdbus conn info:%d\n", r);
-               goto end;
+               return r;
        }
-       free_conn_info = true;
 
-       r = __internal_can_recv(kconn->bus_type,
-                       dest_uid_n, dest_gid_n, dest_label.c_str(),
-                       sender, info.k_names, info.names_num,
+       return __internal_can_recv(kconn->bus_type,
+                       destinationInfo.uid(), destinationInfo.gid(), destinationInfo.label(),
+                       sender, senderInfo.names(), senderInfo.numberOfNames(),
                        path, interface, member, message_type);
-
-end:
-       if (free_conn_info)
-               kdbus_free_by_offset(&kconn->conn, info.free_offset);
-
-       return r;
 }
 
 DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
@@ -357,61 +328,51 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
                                                                                        const char *interface,
                                                                                        const char *member,
                                                                                        int         message_type,
-                                                                                       const char *error_name,
-                                                                                       int         reply_serial,
-                                                                                       int         requested_reply)
+                                                                                       const char * /*error_name*/,
+                                                                                       int         /*reply_serial*/,
+                                                                                       int         /*requested_reply*/)
 {
-       (void)error_name;
-       (void)reply_serial;
-       (void)requested_reply;
-
-       struct kconn *kconn = static_cast<struct kconn *>(configuration);
-
-       int r;
-       struct kdbus_cmd_param info;
-
        __internal_enter();
+       auto internal_enter_guard = transaction_guard::makeGuard([] () { __internal_exit(); });
 
+       auto kconn = KCONN(configuration);
+       KdbusConnectionInfo info(kconn->conn);
+       int r;
        if (destination && *destination) {
-               r = kdbus_get_conn_info(&kconn->conn, destination, &info, POLICY_CONN_INFO_NAME);
+               r = info.get(destination, KdbusConnection::POLICY_CONN_INFO_NAME);
                if (r < 0)
-                       goto end;
+                       return r;
        }
 
        r = __internal_can_send(kconn->bus_type,
                        sender_uid, sender_gid, sender_label,
-                       destination, info.k_names, info.names_num,
+                       destination, info.names(), info.numberOfNames(),
                        path, interface, member, message_type);
 
        if (r <= 0)
-               goto end;
+               return r;
 
-       /* 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. */
        if (!sender)
                sender = ":";
+
+       /* libdbus, gdbus pass multiple sender as parameter : eg. "name_A name_B name_C". */
        r = __internal_can_recv(kconn->bus_type,
                        g_udesc.uid, g_udesc.gid, g_udesc.label,
                        sender, nullptr, 0,
                        path, interface, member, message_type);
 
        if (r <= 0)
-               goto end;
-end:
-       if (info.free_offset)
-               kdbus_free_by_offset(&kconn->conn, info.free_offset);
+               return r;
 
-       __internal_exit();
        return r;
 }
 
 DBUSPOLICY1_EXPORT int dbuspolicy1_can_own(void* configuration, const char* const service)
 {
-       int r;
-       struct kconn *kconn = static_cast<struct kconn *>(configuration);
+       auto kconn = KCONN(configuration);
+
        __internal_enter();
-       r = __internal_can_own(kconn->bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, service);
-       __internal_exit();
-       return r;
+       auto internal_enter_guard = transaction_guard::makeGuard([] () { __internal_exit(); });
+
+       return __internal_can_own(kconn->bus_type, g_udesc.uid, g_udesc.gid, g_udesc.label, service);
 }