refactoring: don't copy string_refs for matching 97/202897/3
authorAdrian Szyndela <adrian.s@samsung.com>
Thu, 4 Apr 2019 09:42:37 +0000 (11:42 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Thu, 11 Apr 2019 15:13:09 +0000 (17:13 +0200)
This modifies MatchItemSR to use externally built array of names instead of
copying input arrays. The external array was built anyway in case
names were taken from KDBUS_CMD_CONN_INFO ioctl.

The other case, where the array is built from space separated string is
changed in a way that the building process is performed outside of
MatchItemSR. This allows further simplifications.

Change-Id: I13cfba0940f3347be91c9281614a3c66b8cb11b6

16 files changed:
src/internal/array_with_size.hpp [new file with mode: 0644]
src/internal/bus_names_array.hpp [new file with mode: 0644]
src/internal/internal.cpp
src/internal/internal.h
src/internal/policy.cpp
src/internal/policy.hpp
src/kdbus.cpp
src/kdbus.h
src/libdbuspolicy1.cpp
src/stest_performance.cpp
src/test-libdbuspolicy1-method-gdi.cpp
src/test-libdbuspolicy1-method.cpp
src/test-libdbuspolicy1-send_destination_prefix-deny-gdi.cpp
src/test-libdbuspolicy1-send_destination_prefix-deny.cpp
src/test-libdbuspolicy1-signal-gdi.cpp
src/test-libdbuspolicy1-signal.cpp

diff --git a/src/internal/array_with_size.hpp b/src/internal/array_with_size.hpp
new file mode 100644 (file)
index 0000000..e8f7220
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+#pragma once
+
+#include <array>
+
+template <typename T, size_t MAX_SIZE>
+class ArrayWithSize : public std::array<T, MAX_SIZE> {
+       size_t num{0};
+
+public:
+       size_t size() const { return num; }
+       bool empty() const { return size() == 0; }
+
+       void push_back(const T &elem) {
+               if (num < MAX_SIZE)
+                       (*this)[num++] = elem;
+       }
+       void clear() { num = 0; }
+       const T *begin() const { return &(*this)[0]; }
+       const T *end() const { return &(*this)[num]; }
+};
diff --git a/src/internal/bus_names_array.hpp b/src/internal/bus_names_array.hpp
new file mode 100644 (file)
index 0000000..fee3064
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+#pragma once
+
+#include "array_with_size.hpp"
+#include "tslog.hpp"
+
+#include <boost/utility/string_ref.hpp>
+#include <cstdlib>
+
+/* kdbus driver hard limit for names per connection - as in kernel's kdbus/limits.h. */
+#define KDBUS_CONN_MAX_NAMES 256
+
+class KdbusBusNames : public ArrayWithSize<boost::string_ref, KDBUS_CONN_MAX_NAMES>
+{
+public:
+       KdbusBusNames &addSpaceSeparatedNames(const char *names) noexcept {
+               if (names) {
+                       boost::string_ref current(names);
+                       while (!current.empty()) {
+
+                               if (!(isalnum(current[0]) || current[0] == ' '))
+                                       tslog::log_verbose("Wrong name(", current, "): ", names, "\n");
+
+                               auto space = current.find_first_of(" ");
+                               push_back(current.substr(0, space));
+
+                               if (space != current.npos)      // skip the space
+                                       current = current.substr(space+1);
+                               else
+                                       current.clear();
+                       }
+               }
+               return *this;
+       }
+};
index 1a96cf7..9800e86 100644 (file)
@@ -100,25 +100,13 @@ int __internal_can_send(BusType bus_type,
                                                const uid_t user,
                                                const gid_t group,
                                                const char* const label,
-                                               const char* const destination,
-                                               const char** const destination_names,
-                                               uint16_t destination_names_size,
+                                               const KdbusBusNames &destination_names,
                                                const char* const path,
                                                const char* const interface,
                                                const char* const member,
                                                int type)
 {
-       MatchItemSend matcher(interface, member, path, static_cast<MessageType>(type));
-       if (destination_names_size == 0) {
-               if (!matcher.addNames(destination)) {
-                       tslog::log_verbose("Destination too long: ", destination, "\n");
-                       return false;
-               }
-       } else {
-               assert(destination_names);
-               for (size_t i = 0; i < destination_names_size; i++)
-                       matcher.addName(destination_names[i]);
-       }
+       MatchItemSend matcher(interface, member, path, static_cast<MessageType>(type), destination_names);
        return static_cast<int>(policy_checker(bus_type).check(user, group, label, matcher));
 }
 
@@ -126,25 +114,13 @@ int __internal_can_recv(BusType bus_type,
                                                const uid_t user,
                                                const gid_t group,
                                                const char* const label,
-                                               const char* const sender,
-                                               const char** const sender_names,
-                                               uint16_t sender_names_size,
+                                               const KdbusBusNames &sender_names,
                                                const char* const path,
                                                const char* const interface,
                                                const char* const member,
                                                int type)
 {
-       MatchItemReceive matcher(interface, member, path, static_cast<MessageType>(type));
-       if (0 == sender_names_size) {
-               if (!matcher.addNames(sender)) {
-                       tslog::log_verbose("Sender too long: ", sender, "\n");
-                       return false;
-               }
-       } else {
-               assert(sender_names);
-               for (size_t i = 0; i < sender_names_size; i++)
-                       matcher.addName(sender_names[i]);
-       }
+       MatchItemReceive matcher(interface, member, path, static_cast<MessageType>(type), sender_names);
        return static_cast<int>(policy_checker(bus_type).check(user, group, label, matcher));
 }
 
index 6c898d5..75246c6 100644 (file)
@@ -26,6 +26,7 @@
 #ifndef _LIBDBUSPOLICY1_INTERNAL_H_
 #define _LIBDBUSPOLICY1_INTERNAL_H_
 
+#include "bus_names_array.hpp"
 #include <pthread.h>
 #include <stdbool.h>
 #include <stdint.h>
@@ -105,9 +106,7 @@ int __internal_can_send(BusType bus_type,
                                                const uid_t  user,
                                                const gid_t  group,
                                                const char* const label,
-                                               const char* const destination,
-                                               const char** const destination_names,
-                                               uint16_t destination_names_size,
+                                               const KdbusBusNames &destination_names,
                                                const char* const path,
                                                const char* const interface,
                                                const char* const member,
@@ -131,9 +130,7 @@ int __internal_can_recv(BusType bus_type,
                                                uid_t user,
                                                gid_t group,
                                                const char* const label,
-                                               const char* const sender,
-                                               const char** const sender_names,
-                                               uint16_t sender_names_size,
+                                               const KdbusBusNames &sender_names,
                                                const char* const path,
                                                const char* const interface,
                                                const char* const member,
index f0128aa..56b0ddd 100644 (file)
@@ -101,38 +101,19 @@ const DecisionItem& ItemOwn::getDecision() const {
        return __decision;
 }
 
-MatchItemSR::MatchItemSR(const char* i, const char* me, const char* p, MessageType t)
-       : type(t) {
+MatchItemSR::MatchItemSR(const char* i,
+                                                const char* me,
+                                                const char* p,
+                                                MessageType t,
+                                                const KdbusBusNames &n_array)
+       : names{n_array}
+       , type{t}
+{
        if (i) interface = i;
        if (me) member = me;
        if (p) path = p;
 }
 
-void MatchItemSR::addName(const char* name) {
-       names.push_back(name);
-}
-
-bool MatchItemSR::addNames(const char* name) noexcept {
-
-       if (name) {
-               boost::string_ref current(name);
-               while (!current.empty()) {
-
-                       if (!(isalnum(current[0]) || current[0] == ' '))
-                               tslog::log_verbose("Wrong name(", current, "): ", name, "\n");
-
-                       auto space = current.find_first_of(" ");
-                       names.push_back(current.substr(0, space));
-
-                       if (space != current.npos)      // skip the space
-                               current = current.substr(space+1);
-                       else
-                               current.clear();
-           }
-       }
-       return true;
-}
-
 bool MatchItemSR::match(MessageType _type,
                                                const boost::string_ref &_interface,
                                                const boost::string_ref &_path,
index d12ac7f..f7593b2 100644 (file)
 #define _POLICY_H
 
 #include "type_list.h"
+#include "bus_names_array.hpp"
+#include "internal.h"
 
 #include <boost/utility/string_ref.hpp>
-#include <internal/internal.h>
 #include <string>
 #include <vector>
-#include <typeinfo>
-
-/** Maximum tree node children. It is connected with proper characters which can be used in name.*/
-#define MAX_CHILDREN 65
 
 namespace ldp_xml {
        class StorageBackendXML;
@@ -153,15 +150,16 @@ namespace ldp_xml_parser
        };
 
        /** Struct which allows to contain multiple connection names then compared in s/r policy checker */
-       struct MatchItemSR {
-               std::vector<boost::string_ref> names;
+       class MatchItemSR {
+               const KdbusBusNames &names;
                boost::string_ref interface;
                boost::string_ref member;
                boost::string_ref path;
                MessageType type;
-               MatchItemSR(const char* i, const char* me, const char* p, MessageType t);
-               void addName(const char* name);
-               bool addNames(const char* name) noexcept;
+
+               friend std::ostream &operator<<(std::ostream& stream, const ldp_xml_parser::MatchItemSR &item);
+       public:
+               MatchItemSR(const char* i, const char* me, const char* p, MessageType t, const KdbusBusNames &n_array);
 
                bool match(MessageType _type,
                                   const boost::string_ref &_interface,
index 3432a07..a045fd5 100644 (file)
@@ -15,6 +15,8 @@
 */
 
 #include "kdbus.h"
+#include "internal/tslog.hpp"
+#include <boost/utility/string_ref.hpp>
 #include <cassert>
 #include <cerrno>
 #include <cstddef>
@@ -23,6 +25,8 @@
 #include <fcntl.h>
 #include <linux/kdbus.h>
 #include <memory>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -166,6 +170,7 @@ int KdbusConnection::get_conn_info(const char *bus_name,
                set_item_str(cmd->items, bus_name, l+1, KDBUS_ITEM_NAME);
        }
        if (ioctl(fd, KDBUS_CMD_CONN_INFO, cmd) < 0) {
+               LOGE("Failed KDBUS_CMD_CONN_INFO: %m\n");
                if (errno == ENXIO || errno == ESRCH)
                        return DBUSPOLICY_RESULT_DEST_NOT_AVAILABLE;
 
@@ -225,7 +230,7 @@ void KdbusConnectionInfo::setNewData(uint64_t offset)
        free_offset = offset;
        set = true;
 
-       names_num = 0;
+       k_names.clear();
        _label = nullptr;
        uid_n = UID_INVALID;
        gid_n = GID_INVALID;
index 7183937..bf17d5f 100644 (file)
 
 #pragma once
 
-#include <linux/kdbus.h>
-#include <stdint.h>
 #include <pwd.h>
 #include <grp.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-
-#define KDBUS_CONN_MAX_NAMES 256
+#include <array>
+#include "internal/bus_names_array.hpp"
+#include <boost/utility/string_ref.hpp>
 
 class KdbusConnectionInfo;
 
@@ -58,11 +52,11 @@ class KdbusConnectionInfo {
        static const gid_t GID_INVALID = -1;
 
        char const *_label{nullptr};
-       const char *k_names[KDBUS_CONN_MAX_NAMES]{};
+
+       KdbusBusNames k_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;
@@ -74,7 +68,7 @@ public:
        void release_info();
        void setNewData(uint64_t offset);
 
-       void addName(const char *name) { k_names[names_num++] = name; }
+       void addName(const char *name) { k_names.push_back(name); }
 
        void setCreds(uid_t uid, gid_t gid) { uid_n = uid; gid_n = gid; }
 
@@ -83,8 +77,8 @@ public:
        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; }
+       const KdbusBusNames &names() const { return k_names; }
+       KdbusBusNames &names() { return k_names; }
        uid_t uid() const { return uid_n; }
        gid_t gid() const { return gid_n; }
        const char *label() const { return _label; }
index 4f377ec..46d1648 100644 (file)
@@ -265,6 +265,19 @@ DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration)
        delete KCONN(configuration);
 }
 
+static int getNames(const char *name, KdbusConnectionInfo &info,
+               KdbusConnection::conn_info_type info_type) {
+       if (name && *name) {
+               int r = info.get(name, info_type);
+               if (r < 0)
+                       return r;
+
+               if (info.names().empty())
+                       info.names().addSpaceSeparatedNames(name);
+       }
+       return 0;
+}
+
 DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
                                                                                         const char *destination,
                                                                                         const char *sender,
@@ -289,16 +302,13 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
        int r;
        /* check can send */
        /* if broadcasting, then pass - null destination */
-       if (destination && *destination) {
-               r = destinationInfo.get(destination, KdbusConnection::POLICY_CONN_INFO_ALL);
-               if (r < 0)
-                       return r;
-       }
+       r = getNames(destination, destinationInfo, KdbusConnection::POLICY_CONN_INFO_ALL);
+       if (r < 0)
+               return r;
 
        r = __internal_can_send(kconn->bus_type,
                        g_udesc.uid, g_udesc.gid, g_udesc.label,
-                       destination, destinationInfo.names(), destinationInfo.numberOfNames(),
-                       path, interface, member, message_type);
+                       destinationInfo.names(), path, interface, member, message_type);
 
        if (r <= 0)
                return r;
@@ -306,16 +316,13 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_out(void* configuration,
        KdbusConnectionInfo senderInfo(kconn->conn);
        /* check can recv */
        /* get sender information from kdbus */
-       r = senderInfo.get(sender, KdbusConnection::POLICY_CONN_INFO_NAME);
-       if (r < 0) {
-               fprintf(stderr, "failed to kdbus conn info:%d\n", r);
+       r = getNames(sender, senderInfo, KdbusConnection::POLICY_CONN_INFO_NAME);
+       if (r < 0)
                return r;
-       }
 
        return __internal_can_recv(kconn->bus_type,
                        destinationInfo.uid(), destinationInfo.gid(), destinationInfo.label(),
-                       sender, senderInfo.names(), senderInfo.numberOfNames(),
-                       path, interface, member, message_type);
+                       senderInfo.names(), path, interface, member, message_type);
 }
 
 DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
@@ -338,16 +345,13 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
        auto kconn = KCONN(configuration);
        KdbusConnectionInfo info(kconn->conn);
        int r;
-       if (destination && *destination) {
-               r = info.get(destination, KdbusConnection::POLICY_CONN_INFO_NAME);
-               if (r < 0)
-                       return r;
-       }
+       r = getNames(destination, info, KdbusConnection::POLICY_CONN_INFO_NAME);
+       if (r < 0)
+               return r;
 
        r = __internal_can_send(kconn->bus_type,
                        sender_uid, sender_gid, sender_label,
-                       destination, info.names(), info.numberOfNames(),
-                       path, interface, member, message_type);
+                       info.names(), path, interface, member, message_type);
 
        if (r <= 0)
                return r;
@@ -356,9 +360,10 @@ DBUSPOLICY1_EXPORT int dbuspolicy1_check_in(void* configuration,
                sender = ":";
 
        /* libdbus, gdbus pass multiple sender as parameter : eg. "name_A name_B name_C". */
+       KdbusBusNames names;
        r = __internal_can_recv(kconn->bus_type,
                        g_udesc.uid, g_udesc.gid, g_udesc.label,
-                       sender, nullptr, 0,
+                       names.addSpaceSeparatedNames(sender),
                        path, interface, member, message_type);
 
        if (r <= 0)
index 4aa8aba..4c3265e 100644 (file)
@@ -155,8 +155,9 @@ template <typename DB>
 void send_prefix_test(const DB &db)
 {
        for (const auto &test : tests) {
-               MatchItemSend m_item(test.interface, test.member, test.path, test.type);
-               m_item.addNames(test.destination);
+               KdbusBusNames names;
+               MatchItemSend m_item(test.interface, test.member, test.path, test.type,
+                               names.addSpaceSeparatedNames(test.destination));
 
                auto ret = db.getDecisionItemContextMandatory(m_item);
 
index c4d4585..05747a6 100644 (file)
@@ -77,8 +77,9 @@ template <typename DB, typename T>
 Decision get_decision(DB &db, const MethodTest &test) {
        DecisionItem ret;
 
-       T m_item = T(test.interface, test.member, test.path, test.type);
-       m_item.addNames(test.name);
+       KdbusBusNames names;
+       T m_item = T(test.interface, test.member, test.path, test.type,
+                       names.addSpaceSeparatedNames(test.name));
 
        ret = db.getDecisionItemContextMandatory(m_item);
        if (ret.getDecision() == Decision::ANY) {
index 85ce088..edd579d 100644 (file)
@@ -66,17 +66,19 @@ bool method_test() {
        bool ret = true;
        __internal_init(SYSTEM_BUS, "tests/default_allow/system.conf");
        for (i = 0; i < sizeof(method_tests)/sizeof(struct MethodTest); i++) {
+               KdbusBusNames bus_names;
+               bus_names.addSpaceSeparatedNames(method_tests[i].name);
                if (method_tests[i].recv_send == MessageDirection::SEND)
                {
                        ret = __internal_can_send(SYSTEM_BUS,
                                        method_tests[i].user, method_tests[i].group, method_tests[i].label,
-                                       method_tests[i].name, nullptr, 0,
+                                       bus_names,
                                        method_tests[i].path, method_tests[i].interface, method_tests[i].member,
                                        static_cast<int>(method_tests[i].type));
                } else if (method_tests[i].recv_send == MessageDirection::RECEIVE) {
                        ret = __internal_can_recv(SYSTEM_BUS,
                                        method_tests[i].user, method_tests[i].group, method_tests[i].label,
-                                       method_tests[i].name, nullptr, 0,
+                                       bus_names,
                                        method_tests[i].path, method_tests[i].interface, method_tests[i].member,
                                        static_cast<int>(method_tests[i].type));
                }
index 1e72d33..760ae6f 100644 (file)
@@ -155,8 +155,9 @@ bool send_prefix_test(const DB &db)
        bool flag = true;
 
        for (const auto &test : tests) {
-               MatchItemSend m_item(test.interface, test.member, test.path, test.type);
-               m_item.addNames(test.destination);
+               KdbusBusNames names;
+               MatchItemSend m_item(test.interface, test.member, test.path, test.type,
+                               names.addSpaceSeparatedNames(test.destination));
 
                auto ret = db.getDecisionItemContextMandatory(m_item);
 
index fc64d3f..61d5a1b 100644 (file)
@@ -140,8 +140,10 @@ bool test()
        __internal_init(SYSTEM_BUS, "tests/default_deny/system.conf");
 
        for (i = 0; i < sizeof(tests)/sizeof(struct Test); i++) {
+               KdbusBusNames names;
                ret = __internal_can_send(SYSTEM_BUS, tests[i].user,
-                               tests[i].group, tests[i].label, tests[i].destination, nullptr, 0,
+                               tests[i].group, tests[i].label,
+                               names.addSpaceSeparatedNames(tests[i].destination),
                                tests[i].path, tests[i].interface, tests[i].member,
                                (int)tests[i].type);
 
index b08d51e..95f158d 100644 (file)
@@ -49,8 +49,9 @@ bool signal_test(const DB &db) {
        unsigned  i = 0;
        bool flag = true;
        for (const auto &test : signal_tests) {
-               MatchItemSend m_item(test.interface, NULL, NULL, ldp_xml_parser::MessageType::SIGNAL);
-               m_item.addNames(test.dest);
+               KdbusBusNames names;
+               MatchItemSend m_item(test.interface, NULL, NULL, ldp_xml_parser::MessageType::SIGNAL,
+                               names.addSpaceSeparatedNames(test.dest));
 
                auto ret = db.getDecisionItemContextMandatory(m_item);
 
index c4b622f..f9c57b2 100644 (file)
@@ -32,9 +32,10 @@ bool signal_test() {
        bool ret = true;
        __internal_init(SYSTEM_BUS, "tests/default_allow/system.conf");
        for (i = 0; i < sizeof(signal_tests)/sizeof(struct SignalTest); i++) {
+               KdbusBusNames names;
                ret = __internal_can_send(SYSTEM_BUS,
                                signal_tests[i].user, signal_tests[i].group, signal_tests[i].label,
-                               signal_tests[i].dest, nullptr, 0,
+                               names.addSpaceSeparatedNames(signal_tests[i].dest),
                                NULL, signal_tests[i].interface, NULL, DBUSPOLICY_MESSAGE_TYPE_SIGNAL);
                if ( (int)((signal_tests[i].expected_result)) != ret) {
                        printf("[ERROR][%d] signal test failed: %d %d ", i, (int)((signal_tests[i].expected_result)), ret);