From 1bbaec20965aa5b168f7c9ec72baa384c8456883 Mon Sep 17 00:00:00 2001 From: Baumann Date: Tue, 11 Jun 2019 16:18:14 +0200 Subject: [PATCH 01/16] dbuspolicy-finder documentation Change-Id: Ia6617d124a4e4da8a1377eefba2b70b971b65c23 --- src/documentation.txt | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/documentation.txt diff --git a/src/documentation.txt b/src/documentation.txt new file mode 100644 index 0000000..89ee5b3 --- /dev/null +++ b/src/documentation.txt @@ -0,0 +1,115 @@ +DESCRIPTION: +dbuspolicy-finder is the libdbuspolicy filtering tool. See http://www.freedesktop.org/software/dbus/ for more information about the big picture. +A message bus daemon has a configuration file that specializes it for a particular application. +For example, one configuration file might set up the message bus to be a systemwide message bus, while another might set it up to be a per-user-login-session bus. +There are two standard configuration files: 'system.conf' and 'session.conf', but users can choose their own configuration file. + +The element has one of three attributes: +- context="(default|mandatory)" +- user="username or userid" +- group="group name or gid" + +This program prints matching rules from all the contexts: 'default', 'user', 'group' and 'mandatory' in the order of evaluation. + +There are two modes: +- where specific filter options are provided (printing matching rules); +- only group, user or even no options are provided (printing all the rules from the context). + +OPTIONS: +User must provide both: policy type (send | receive | own | access) and the configuration file. Otherwise, program will ask for it and show help. +Additionaly, user can choose from the following arguments: + +Options for 'send': + + -t, --type=TYPE The default type is ANY; type="method_call" | "method_return" | "signal" | "error" + + -g, --group=GROUP It is possible to limit found records to the only one group. You can use both: names or digits; group="groupname" + + -u, --user=USER It is possible to limit found records to the only one user. You can use both: names or digits; user="username" + + -n, --name It is the destination, where message should be send; it matches to send_destination attribute; name="service_name" + + -i, --interface It is an interface; it matches to send_interface attribute; interface="interface_name" + + -p, --path It is a path to the dbus object; it matches to send_path attribute; path="/path/name" + + -m, --member It is a member; it matches to send_member attribute; it matches to member="method_or_signal_name" + + +Options for 'receive': + + -t, --type=TYPE The default type is ANY; type="method_call" | "method_return" | "signal" | "error" + + -g, --group=GROUP It is possible to limit found records to the only one group. You can use both: names or digits; group="groupname" + + -u, --user=USER It is possible to limit found records to the only one user. You can use both: names or digits; user="username" + + -n, --name It is the sender, from which message came; it matches to receive_sender attribute; name="sender_name" + + -i, --interface It is an interface; it matches to receive_interface attribute; interface="interface_name" + + -p, --path It is a path to the dbus object; it matches to receive_path attribute; path="/path/name" + + -m, --member It is a member; it matches to receive_member attribute; member="method_or_signal_name" + + +Options for 'access': + + -g, --group=GROUP It is possible to limit found records to the only one group. You can use both: names or digits; group="groupname" + + -u, --user=USER It is possible to limit found records to the only one user. You can use both: names or digits; user="username" + + +Options for 'own': + + -g, --group=GROUP It is possible to limit found records to the only one group. You can use both: names or digits; group="groupname" + + -u, --user=USER It is possible to limit found records to the only one user. You can use both: names or digits; user="username" + + -n, --name It is a well-known bus name; name="service_name" + + +EXAMPLES: +$ dbuspolicy-finder send -c configuration_file.conf --group 7 --interface org.bluez +//you can provide your configuration file + + +$ dbuspolicy-finder receive --session --group lp + + Context Default: +ItemReceive: name(), inter(), member(), path(), type(METHOD_CALL), decision(ALLOW) +ItemReceive: name(), inter(), member(), path(), type(METHOD_RETURN), decision(ALLOW) +ItemReceive: name(), inter(), member(), path(), type(SIGNAL), decision(ALLOW) +ItemReceive: name(), inter(), member(), path(), type(ERROR), decision(ALLOW) +ItemReceive: name(), inter(org.tizen.data_control_service), member(), path(), type(SIGNAL), decision(CHECK:http://tizen.org/privilege/datasharing) +No rules for group in policy! + + +$ dbuspolicy-finder send --session --user root --interface org.bluez + + Context Default: +ItemSend: name(), inter(), member(), path(), type(ANY), decision(ALLOW) +ItemSend: name(), inter(), member(), path(/org/tizen/messageport), type(ANY), decision(ALLOW) +No rules for user in policy! + + +$ echo "Rejected send message, 2 matched rules; type=\"method_call\", sender=\":1.26\" (uid=551 pid=2808 comm=\"\") interface=\"net.weconn.Manager\" member=\"GetState\" error name=\"(unset)\" requested_reply=\"0\" destination=\"net.weconn\" privilege=\"(n/a)\" (uid=551 pid=2786 comm=\"\")"| dbuspolicy-finder send --session --error + + Context Default: +ItemSend: name(), inter(), member(), path(), type(ANY), decision(ALLOW) +ItemSend: name(), inter(), member(), path(/org/tizen/messageport), type(ANY), decision(ALLOW) + + +$ dbuspolicy-finder send --system -t method_call -n org.tizen.system.vibrator + + Context Default: +ItemSend: name(org.tizen.system.vibrator), inter(), member(), path(), type(ANY), decision(DENY) +ItemSend: name(org.tizen.system.vibrator), inter(), member(), path(/Org/Tizen/System/Vibrator/Haptic), type(ANY), decision(CHECK:http://tizen.org/privilege/haptic) + User: 0 +ItemSend: name(org.tizen.system.vibrator), inter(), member(), path(), type(ANY), decision(ALLOW) + + +$ dbuspolicy-finder access --system + + Context Default +ItemAccess: type(ALL_USERS), uid(0), gid(0), decision(ALLOW) -- 2.7.4 From a0b841f97347af01266b888b1bc7f9a51132e286 Mon Sep 17 00:00:00 2001 From: Baumann Date: Tue, 18 Jun 2019 12:39:13 +0200 Subject: [PATCH 02/16] new printing pattern Change-Id: Ifb3f31c44ba845a35490f26d63e74f05cb8c6658 --- src/dbuspolicy_finder.cpp | 96 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/src/dbuspolicy_finder.cpp b/src/dbuspolicy_finder.cpp index c25f030..1bb2997 100644 --- a/src/dbuspolicy_finder.cpp +++ b/src/dbuspolicy_finder.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include using namespace ldp_xml_parser; @@ -55,6 +56,13 @@ static const std::map types { { "error", MessageType::ERROR } }; +static const std::map buses { + { "user", BusAccessType::USER }, + { "group", BusAccessType::GROUP }, + { "all_users", BusAccessType::ALL_USERS }, + {"all_groups", BusAccessType::ALL_GROUPS} +}; + MessageType stringToMessageType(std::string tmp) { std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c) { return std::tolower(c); } ); @@ -69,6 +77,82 @@ MessageType stringToMessageType(std::string tmp) { } } +std::pair getItemStrings (const ItemSend &) { + return std::make_pair ("send", "send_destination"); +} +std::pair getItemStrings (const ItemReceive &) { + return std::make_pair ("receive", "receive_sender"); +} + +template void printDecision(const T & item) { + bool everything_is_null = true; + const auto strings = getItemStrings(item); + + if (!item.getInterface().empty()) { + everything_is_null = false; + std::cout << " " << strings.first << "=\"" << item.getInterface() << "\""; + } + if (!item.getMember().empty()) { + everything_is_null = false; + std::cout << " " << strings.first << "=\"" << item.getMember() << "\""; + } + if (!item.getPath().empty()) { + everything_is_null = false; + std::cout << " " << strings.first << "=\"" << item.getPath() << "\""; + } + if (!item.getName().empty()) { + everything_is_null = false; + std::cout << " " << strings.first << "=\"" << item.getName() << "\""; + } + if (!item.getName().empty() && item.isNamePrefix()) { + everything_is_null = false; + std::cout << " " << strings.second << "=\"" << item.getName() << "\""; + } + const auto type_it = std::find_if(types.begin(), types.end(), [&item] (const decltype(types)::value_type & type) { return type.second == item.getType(); } ); + + if (type_it != types.end()) { + everything_is_null = false; + std::cout << " type=\"" << type_it->first << "\""; + } + if (everything_is_null) + std::cout << '*'; + + std::cout << std::endl; +} + +void printDecision(const ItemAccess & item) { + bool everything_is_null = true; + std::cout << " access" << + " uid=\"" << item.getUid() << "\"" << + " gid=\"" << item.getGid() << "\""; + + const auto bus_it = std::find_if(buses.begin(), buses.end(), [&item] (const decltype(buses)::value_type & bus) { return bus.second == item.getType(); } ); + + if (bus_it != buses.end()) { + everything_is_null = false; + std::cout << " type=\"" << bus_it->first << "\""; + } + if (everything_is_null) + std::cout << '*'; + + std::cout << std::endl; +} + +template void printDecisionMain(const typename T::item_type & item) { + const auto tmp = item.getDecision().getDecision(); + + if (tmp == Decision::ALLOW) + std::cout << "allow"; + + else if (tmp == Decision::DENY) + std::cout << "deny"; + + else if (tmp == Decision::CHECK) + std::cout << "check"; + + printDecision(item); +} + void printDecision(const Decision & di, const std::string & token, const std::string & extraText, Print_once & printer) { if (di == Decision::ANY) return; @@ -118,7 +202,7 @@ template void matchPolicy(const T & policy, const typename T::item_ for (const auto & iter : policy.getItems()) { if (noFilter || mi.match(iter.getType(), iter.getInterface(), iter.getPath(), iter.getMember(), iter.getName(), iter.isNamePrefix(), Decision::ANY)) { printer.print(); - std::cout << iter << std::endl; + printDecisionMain(iter); } } } @@ -138,7 +222,7 @@ template <> void matchPolicy(const PolicyAccess & policy, const Ma for (const auto & iter : policy.getItems()) { if (noFilter || mi.match(iter.getType(), iter.getUid(), iter.getGid())) { printer.print(); - std::cout << iter << std::endl; + printDecisionMain(iter); } } } @@ -151,10 +235,10 @@ template void pickPolicy(const StorageBackendXML & storage, const t if (numberGroup == ((gid_t) -1) && numberUser == ((uid_t) -1)) { for (const auto & gid : groups) { - matchPolicy(gid.second, mi, noFilter, std::string("Group:") + std::to_string(gid.first)); + matchPolicy(gid.second, mi, noFilter, std::string("Group: ") + std::to_string(gid.first)); } for (const auto & uid : users) { - matchPolicy(uid.second, mi, noFilter, std::string("User:") + std::to_string(uid.first)); + matchPolicy(uid.second, mi, noFilter, std::string("User: ") + std::to_string(uid.first)); } } else { if (numberGroup != (gid_t) -1) { @@ -162,14 +246,14 @@ template void pickPolicy(const StorageBackendXML & storage, const t if (it == groups.end()) std::cout << "No rules for group in policy!" << std::endl; else - matchPolicy(it->second, mi, noFilter, std::string("Group:") + std::to_string(numberGroup)); + matchPolicy(it->second, mi, noFilter, std::string("Group: ") + std::to_string(numberGroup)); } if (numberUser != (uid_t) -1) { const auto it = users.find(numberUser); if (it == users.end()) std::cout << "No rules for user in policy!" << std::endl; else - matchPolicy(it->second, mi, noFilter, std::string("User:") + std::to_string(numberUser)); + matchPolicy(it->second, mi, noFilter, std::string("User: ") + std::to_string(numberUser)); } } matchPolicy(storage.getPolicyContextMandatory(), mi, noFilter, "Context Mandatory:"); -- 2.7.4 From 16fb9f79117b4455459fc6311efcab14f42117bc Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Tue, 25 Jun 2019 13:39:29 +0200 Subject: [PATCH 03/16] refactoring: remove unnecessary includes Change-Id: I07f76694014d24d89964b95d834d10b4b3f8b38b --- src/dbuspolicy_serializer.cpp | 1 - src/internal/policy.cpp | 1 - src/internal/serializer.cpp | 1 - 3 files changed, 3 deletions(-) diff --git a/src/dbuspolicy_serializer.cpp b/src/dbuspolicy_serializer.cpp index cd172d2..0b9d788 100644 --- a/src/dbuspolicy_serializer.cpp +++ b/src/dbuspolicy_serializer.cpp @@ -7,7 +7,6 @@ #include #include #include "internal/serializer.hpp" -#include "internal/naive_policy_checker.hpp" #include "dbuspolicy1/libdbuspolicy1.h" #include "libdbuspolicy1-private.h" diff --git a/src/internal/policy.cpp b/src/internal/policy.cpp index ef6f129..7815a47 100644 --- a/src/internal/policy.cpp +++ b/src/internal/policy.cpp @@ -17,7 +17,6 @@ * \file * \ingroup Implementation */ -#include "naive_policy_checker.hpp" #include "policy.hpp" #include "storage_backend_xml.hpp" #include "tslog.hpp" diff --git a/src/internal/serializer.cpp b/src/internal/serializer.cpp index 726f0d4..eb185e8 100644 --- a/src/internal/serializer.cpp +++ b/src/internal/serializer.cpp @@ -15,7 +15,6 @@ */ #include "include/fb_generated.h" #include "include/flatbuffers/flatbuffers.h" -#include "naive_policy_checker.hpp" #include "serializer.hpp" #include "tslog.hpp" #include -- 2.7.4 From cc0aeb97972ed2c8d5810845416eb697493726c6 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Wed, 29 May 2019 16:17:49 +0200 Subject: [PATCH 04/16] internal: add send index This adds indexes: - main index for send rules; - additional index for send prefix rules; - indexes for send rules for each user; - additional indexes for send prefix rules for each user. Change-Id: I45a4b3625fe67a9fff7525d04ae6ebf8879e14f1 --- src/internal/policy.hpp | 2 + src/internal/storage_backend_serialized.cpp | 158 ++++++++++++++++++++++++---- 2 files changed, 142 insertions(+), 18 deletions(-) diff --git a/src/internal/policy.hpp b/src/internal/policy.hpp index 9f1575e..71fd8ae 100644 --- a/src/internal/policy.hpp +++ b/src/internal/policy.hpp @@ -167,6 +167,8 @@ namespace ldp_xml_parser const boost::string_ref &_name, bool _is_name_prefix, Decision decision) const; + + const KdbusBusNames &getNames() const { return names; } }; class MatchItemSend : public MatchItemSR { diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp index d9439ce..ef0855b 100644 --- a/src/internal/storage_backend_serialized.cpp +++ b/src/internal/storage_backend_serialized.cpp @@ -23,12 +23,14 @@ #include #include #include +#include #include #include #include #include using namespace FB; +using ldp_xml_parser::MatchItemSend; namespace ldp_serialized { @@ -36,6 +38,8 @@ namespace ldp_serialized { // 1MB. Adjustable #define MAX_SFILE_SIZE (1024 * 1024) +typedef boost::tokenizer> tokenizer; + template struct type_helper; @@ -50,18 +54,136 @@ class StorageBackendSerialized::StorageBackendSerializedImpl { void releaseMMap(); void releaseFD(); + typedef std::pair ItemWithScore; // a pair: Item, index of Item + typedef std::vector ItemsWithScore; // items + typedef std::pair HighestScoreWithItems; // value for index map: highest index for items, items + typedef std::map MapIndex; + typedef std::vector SendPrefixIndex; + + MapIndex sendIndex; // context default + SendPrefixIndex sendPrefixIndex; // context default prefix rules + std::map userSendIndex; + std::map userSendPrefixIndex; + public: bool init(const char *filename, bool verify); bool init(const FB::File *f); bool initFromXML(const char *config_name); void release(); + void createSendIndex(); + ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item, const MapIndex &index, const SendPrefixIndex &prefixIndex); + ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item); + ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item, uid_t uid); + void printContent() const; template ::policy_set_type> const M *getPolicySet(); }; +inline boost::string_ref s(const flatbuffers::String *str) { + return boost::string_ref(str->c_str(), str->size()); +} + +template +bool match(const T &match, const I *i) { + return match.match(makeMessageType(i->type()), + s(i->interface()), + s(i->path()), + s(i->member()), + s(i->name()), + i->is_name_prefix(), + makeDecision(i->decision()->decision())); +} + +ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item, + const MapIndex &index, const SendPrefixIndex &prefixIndex) { + ldp_xml_parser::DecisionItem decision(ldp_xml_parser::Decision::ANY); + + ItemWithScore currentBest(nullptr, 0); + + auto updateCurrentBest = [¤tBest, &item, &index](boost::string_ref name) { + // check if there are any rules for the name + auto fit = index.find(name); + if (fit == index.end()) + return; + + // check if there's any chance to get better score + // fit->second.first is the highest score from vector fit->second.second + if (fit->second.first <= currentBest.second) + return; + + // look for better score + for (const auto &it: fit->second.second) { + if (it.second > currentBest.second && match(item, it.first)) + currentBest = it; + } + }; + + // iterate over names + for (const auto &name: item.getNames()) { + // find and check the no-prefix rules + updateCurrentBest(name); + + // check the prefix rules + for (const auto &prefixItem: prefixIndex) { + if (prefixItem.second > currentBest.second && match(item, prefixItem.first)) + currentBest = prefixItem; + } + } + + // check no-name rules + updateCurrentBest(""); + + if (currentBest.first) + decision = makeDecisionItem(currentBest.first->decision()); + + return decision; +} + +ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item) { + return getDecisionFromSendIndex(item, sendIndex, sendPrefixIndex); +} + +ldp_xml_parser::DecisionItem StorageBackendSerialized::StorageBackendSerializedImpl::getDecisionFromSendIndex(const MatchItemSend &item, uid_t uid) { + return getDecisionFromSendIndex(item, userSendIndex[uid], userSendPrefixIndex[uid]); +} + +void StorageBackendSerialized::StorageBackendSerializedImpl::createSendIndex() { + // helper for adding items to indexes + auto add = [](MapIndex &index, SendPrefixIndex &prefixIndex, boost::string_ref key, ItemWithScore value) { + if (value.first->is_name_prefix()) { + prefixIndex.push_back(value); + } else { + index[key].second.push_back(value); + // we insert items in increasing score order, so we just update the highest score on each add + index[key].first = value.second; + } + }; + + // context default index + const auto *policy = file->m_send_set()->context_default(); + unsigned cnt = 1; + + const auto *v = policy->items(); + for (auto it = v->begin(); it != v->end(); ++it) + add(sendIndex, sendPrefixIndex, + boost::string_ref(it->name()->c_str(), it->name()->size()), + ItemWithScore(*it, cnt++)); + + // users index + for (const auto &uidPolicy: *file->m_send_set()->user()) { + cnt = 1; + for (const auto it: *uidPolicy->policy()->items()) { + add(userSendIndex[uidPolicy->id()], + userSendPrefixIndex[uidPolicy->id()], + boost::string_ref(it->name()->c_str(), it->name()->size()), + ItemWithScore(it, cnt++)); + } + } +} + void StorageBackendSerialized::StorageBackendSerializedImpl::releaseMMap() { assert(MAP_FAILED != mem); assert(0 != length); @@ -138,13 +260,17 @@ bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const char *fi mmapGuard.dismiss(); file = GetFile(mem); - return file != nullptr; + bool res = file != nullptr; + if (res) + createSendIndex(); + return res; } bool StorageBackendSerialized::StorageBackendSerializedImpl::init(const FB::File *f) { assert(nullptr == file); file = f; + createSendIndex(); return true; } @@ -206,21 +332,6 @@ void StorageBackendSerialized::printContent() const { pimpl->printContent(); } -inline boost::string_ref s(const flatbuffers::String *str) { - return boost::string_ref(str->c_str(), str->size()); -} - -template -bool match(const T &match, const I *i) { - return match.match(makeMessageType(i->type()), - s(i->interface()), - s(i->path()), - s(i->member()), - s(i->name()), - i->is_name_prefix(), - makeDecision(i->decision()->decision())); -} - template <> bool match(const ldp_xml_parser::MatchItemAccess &match, const FB::ItemAccess *item) { return match.match(makeBusAccessType(item->type()), item->uid(), item->gid()); } @@ -235,8 +346,6 @@ ldp_xml_parser::DecisionItem getDecisionItem(const T &item, const P *policy) { return ldp_xml_parser::Decision::ANY; } -typedef boost::tokenizer> tokenizer; - const DecisionItem *getDecisionItemFromTree(const FB::PolicyOwnNode *node, tokenizer &tokens, tokenizer::iterator &iterator) { @@ -288,6 +397,19 @@ ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextMan return getDecisionItem(item, pimpl->getPolicySet()->context_mandatory()); } +template <> +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const MatchItemSend &item) const { + return pimpl->getDecisionFromSendIndex(item); +} + +template <> +ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemUser(uid_t uid, const MatchItemSend &item) const { + auto *policyPair = pimpl->getPolicySet()->user()->LookupByKey(uid); + if (nullptr == policyPair) + return ldp_xml_parser::Decision::ANY; + return pimpl->getDecisionFromSendIndex(item, uid); +} + template ldp_xml_parser::DecisionItem StorageBackendSerialized::getDecisionItemContextDefault(const T &item) const { return getDecisionItem(item, pimpl->getPolicySet()->context_default()); -- 2.7.4 From e11eec3c4969998248ba906dc7981f6364f55bc5 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Mon, 8 Jul 2019 15:48:31 +0200 Subject: [PATCH 05/16] Add a missing whitespace "allowown" -> "allow own" Change-Id: Ied47493a5a678a13b34be421a573a7bed52b62bb Signed-off-by: Michal Bloch --- src/dbuspolicy_finder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dbuspolicy_finder.cpp b/src/dbuspolicy_finder.cpp index 1bb2997..674b534 100644 --- a/src/dbuspolicy_finder.cpp +++ b/src/dbuspolicy_finder.cpp @@ -164,7 +164,7 @@ void printDecision(const Decision & di, const std::string & token, const std::st std::cout << "deny"; else if (di == Decision::CHECK) std::cout << "check"; - std::cout << extraText << "=\"" << token << "\"" << std::endl; + std::cout << ' ' << extraText << "=\"" << token << "\"" << std::endl; } void checkIfMatches(const std::shared_ptr & iter, const MatchItemOwn & mio, const std::string & currentToken, bool noFilter, Print_once & printer) { -- 2.7.4 From 63bad060def92de04a795533fce8f7c481f9cc6e Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Tue, 9 Jul 2019 14:53:34 +0200 Subject: [PATCH 06/16] Fix a dangling pointer / needless copy Change-Id: I388462ea3d8949f7512228e1b65e4c9ccbc25bdb Signed-off-by: Michal Bloch --- src/test-serializer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test-serializer.cpp b/src/test-serializer.cpp index 2aaf1fd..3461301 100644 --- a/src/test-serializer.cpp +++ b/src/test-serializer.cpp @@ -54,7 +54,7 @@ struct TestsHelper { return value; } - static const char *to_str(const std::string value) { + static const char *to_str(const std::string & value) { return value.c_str(); } -- 2.7.4 From eb752b450f3c1efbb21a7502efc67936e55e6de6 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Wed, 17 Jul 2019 09:19:21 +0900 Subject: [PATCH 07/16] change 'constructor with 1 argument' to explicit constructor * implicit conversion The compiler is allowed to make one implicit conversion to resolve the parameters to a function. What this means is that the compiler can use constructors callable with a single parameter to convert from one type to another in order to get the right type for a parameter. Change-Id: I79da863d9d86d3ea19e43089f2c836d2f52ef6d8 Signed-off-by: sanghyeok.oh --- src/internal/transaction_guard.hpp | 2 +- src/internal/tslog.hpp | 4 ++-- src/kdbus.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/internal/transaction_guard.hpp b/src/internal/transaction_guard.hpp index 8357459..dec307f 100644 --- a/src/internal/transaction_guard.hpp +++ b/src/internal/transaction_guard.hpp @@ -27,7 +27,7 @@ class Guard { FunRelease fun; bool active; public: - Guard(FunRelease f) : fun(f), active(true) {} + explicit Guard(FunRelease f) : fun(f), active(true) {} Guard() = delete; Guard(const Guard &) = delete; Guard &operator=(const Guard &) = delete; diff --git a/src/internal/tslog.hpp b/src/internal/tslog.hpp index e5ad89f..f028601 100644 --- a/src/internal/tslog.hpp +++ b/src/internal/tslog.hpp @@ -74,7 +74,7 @@ namespace tslog struct print_errno { int err; - print_errno(int e) : err(e) {} + explicit print_errno(int e) : err(e) {} }; std::ostream &operator<<(std::ostream &stream, const print_errno &p); @@ -85,7 +85,7 @@ namespace tslog class LogLock { bool locked; public: - LogLock(ldp_log_level level = ldp_log_level::ERROR); + explicit LogLock(ldp_log_level level = ldp_log_level::ERROR); ~LogLock(); }; } diff --git a/src/kdbus.h b/src/kdbus.h index bf17d5f..22b7ec5 100644 --- a/src/kdbus.h +++ b/src/kdbus.h @@ -62,7 +62,7 @@ class KdbusConnectionInfo { KdbusConnection &my_connection; public: - KdbusConnectionInfo(KdbusConnection &c) : my_connection{c} {} + explicit KdbusConnectionInfo(KdbusConnection &c) : my_connection{c} {} ~KdbusConnectionInfo() { release_info(); } void release_info(); -- 2.7.4 From 475677ae26cba2718ab61143396c430301f91f0f Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 18 Jul 2019 14:43:33 +0200 Subject: [PATCH 08/16] Migrate to openssl 1.1 Change-Id: I07c62e6cf0e0fd9173a5d92b40b4b34756f05861 --- packaging/libdbuspolicy.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libdbuspolicy.spec b/packaging/libdbuspolicy.spec index 43d32b5..caa52b3 100644 --- a/packaging/libdbuspolicy.spec +++ b/packaging/libdbuspolicy.spec @@ -19,7 +19,7 @@ Summary: Helper library for fine-grained userspace policy handling-develo %package serializer Summary: Tool to serialize dbus policy -BuildRequires: libopenssl-devel libopenssl +BuildRequires: pkgconfig(openssl1.1) %package assert-data-valid Requires: %{name}-serializer -- 2.7.4 From 2063fc8903e57d36d68c2bc823acb845f58d7da8 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Tue, 30 Jul 2019 17:06:38 +0900 Subject: [PATCH 09/16] dbuspolicy-printer: fix segfault due to invalid input -i opt expecting serialized file. Change-Id: I31bde3750deaa43c8148f2469e74a52e7ef4ba15 Signed-off-by: sanghyeok.oh --- src/dbuspolicy_printer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbuspolicy_printer.cpp b/src/dbuspolicy_printer.cpp index 25a45fa..691ea20 100644 --- a/src/dbuspolicy_printer.cpp +++ b/src/dbuspolicy_printer.cpp @@ -14,7 +14,7 @@ static const struct option options[] = { static void print_help(const char *name) { cout << endl; - cout << "usage: " << name << " [-i input_filename] [-v]" << endl; + cout << "usage: " << name << " [-i serialized filename] [-v]" << endl; cout << " " << name << " {--system|--session} [-v]" << endl; cout << " -v - just verify, don't print anything" << endl; cout << endl; @@ -69,7 +69,7 @@ int main(int argc, char *argv[]) { ldp_serialized::StorageBackendSerialized storage; - if (!storage.init(input_filename.c_str(), just_verify)) { + if (!storage.init(input_filename.c_str(), true)) { if (just_verify) cout << input_filename << ": FAILED" << endl; return EXIT_FAILURE; -- 2.7.4 From e1a0d279edf125a15d2410f964edcbfe667eaeb4 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Tue, 30 Jul 2019 22:01:33 +0900 Subject: [PATCH 10/16] dbuspolicy-printer: add xml format Change-Id: I67cc1f29fb8e4f2fded530dea7719c46f74c0568 Signed-off-by: sanghyeok.oh --- src/dbuspolicy_printer.cpp | 9 +++- src/internal/print_content.cpp | 73 +++++++++++++++++++++++++---- src/internal/print_content.hpp | 4 ++ src/internal/storage_backend_serialized.cpp | 9 ++-- src/internal/storage_backend_serialized.hpp | 2 +- 5 files changed, 82 insertions(+), 15 deletions(-) diff --git a/src/dbuspolicy_printer.cpp b/src/dbuspolicy_printer.cpp index 691ea20..778ff69 100644 --- a/src/dbuspolicy_printer.cpp +++ b/src/dbuspolicy_printer.cpp @@ -17,6 +17,7 @@ static void print_help(const char *name) { cout << "usage: " << name << " [-i serialized filename] [-v]" << endl; cout << " " << name << " {--system|--session} [-v]" << endl; cout << " -v - just verify, don't print anything" << endl; + cout << " -x - print rule as xml format" << endl; cout << endl; } @@ -24,6 +25,7 @@ int main(int argc, char *argv[]) { std::string input_filename; int c; bool just_verify = false; + bool xml_format = false; if (argc < 2) { print_help(argv[0]); @@ -32,7 +34,7 @@ int main(int argc, char *argv[]) { while (1) { int option_index; - c = getopt_long(argc, argv, "i:v", options, &option_index); + c = getopt_long(argc, argv, "i:v:x", options, &option_index); if (c == -1) break; @@ -50,6 +52,9 @@ int main(int argc, char *argv[]) { case 'v': just_verify = true; break; + case 'x': + xml_format = true; + break; case '?': print_help(argv[0]); return EXIT_FAILURE; @@ -80,7 +85,7 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - storage.printContent(); + storage.printContent(xml_format); return EXIT_SUCCESS; } diff --git a/src/internal/print_content.cpp b/src/internal/print_content.cpp index 5c67497..d65a433 100644 --- a/src/internal/print_content.cpp +++ b/src/internal/print_content.cpp @@ -31,6 +31,13 @@ inline const char* __access_type_to_str(ldp_xml_parser::BusAccessType type) { } } +namespace print_content { +static bool xml_format = false; +void use_xml_format(const bool xml) { + xml_format = xml; +} +} + template std::ostream &print_val(std::ostream &stream, const boost::string_ref &name, const T &val) { return stream << name << "(" << val << ")"; @@ -68,10 +75,14 @@ std::ostream &print_content_item_sr(std::ostream &stream, const boost::string_ref &member, const boost::string_ref &path, ldp_xml_parser::MessageType type, - const ldp_xml_parser::DecisionItem &decisionItem) + const ldp_xml_parser::DecisionItem &decisionItem, + const bool is_prefix) { stream << item_type << ": "; - print_val(stream, "name", name); + if (is_prefix) + print_val(stream, "name_prefix", name); + else + print_val(stream, "name", name); print_next_val(stream, "inter", interface); print_next_val(stream, "member", member); print_next_val(stream, "path", path); @@ -79,6 +90,49 @@ std::ostream &print_content_item_sr(std::ostream &stream, return print_next_val(stream, "decision", decisionItem); } +std::ostream &print_content_item_sr_xml(std::ostream &stream, + const boost::string_ref &item_type, + const boost::string_ref &name, + const boost::string_ref &interface, + const boost::string_ref &member, + const boost::string_ref &path, + ldp_xml_parser::MessageType type, + const ldp_xml_parser::DecisionItem &decisionItem, + const bool is_prefix) +{ + const char *strDecision[] = {"any", "allow", "deny", "check"}; + const char *sr; + std::string type_str; + + if (item_type == "ItemSend") + sr = "send"; + else + sr = "receive"; + + stream << "<" << strDecision[static_cast(decisionItem.getDecision())] << " "; + if (is_prefix) + stream << sr << "_destination_prefix=\"" << name << "\" "; + else if (!name.empty()) + stream << sr << "_" << (item_type == "ItemSend" ? "destination" : "sender") << "=\"" << name << "\" "; + + if (!path.empty()) + stream << sr << "_" << "path=\"" << path << "\" "; + if (!interface.empty()) + stream << sr << "_" << "interface=\"" << interface << "\" "; + if (!member.empty()) + stream << sr << "_" << "member=\"" << member << "\" "; + if (!decisionItem.getPrivilege().empty()) + stream << sr << "_" << "privilege=\"" << decisionItem.getPrivilege() << "\" "; + + type_str = __message_type_to_str(type); + std::transform(type_str.begin(), type_str.end(), type_str.begin(), [](unsigned char c){ return std::tolower(c); }); + + if (type_str != "any") + stream << sr << "_" << "type=\"" << type_str << "\" "; + + return stream << "/>"; +} + namespace { static const char* message_decision[] = {"NO_DECISION", "ALLOW", "DENY", "CHECK"}; static inline const char* __decision_to_str(ldp_xml_parser::Decision dec) { @@ -105,9 +159,10 @@ template <> void printContentItem(std::ostream &stream, const FB::ItemAccess *it template void printContentItemSR(std::ostream &stream, const boost::string_ref &item_type, const T *item) { - print_content_item_sr(stream, item_type, item->name()->c_str(), item->interface()->c_str(), + auto print_func = (print_content::xml_format ? print_content_item_sr_xml : print_content_item_sr); + print_func(stream, item_type, item->name()->c_str(), item->interface()->c_str(), item->member()->c_str(), item->path()->c_str(), makeMessageType(item->type()), - makeDecisionItem(item->decision())); + makeDecisionItem(item->decision()), item->is_name_prefix()); } template <> void printContentItem(std::ostream &stream, const FB::ItemSend *item) { @@ -189,13 +244,15 @@ std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemOwn &it } std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemSend &item) { - return print_content_item_sr(stream, "ItemSend", item.getName(), item.getInterface(), item.getMember(), - item.getPath(), item.getType(), item.getDecision()); + auto print_func = (print_content::xml_format ? print_content_item_sr_xml : print_content_item_sr); + return print_func(stream, "ItemSend", item.getName(), item.getInterface(), item.getMember(), + item.getPath(), item.getType(), item.getDecision(), item.isNamePrefix()); } std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemReceive &item) { - return print_content_item_sr(stream, "ItemReceive", item.getName(), item.getInterface(), item.getMember(), - item.getPath(), item.getType(), item.getDecision()); + auto print_func = (print_content::xml_format ? print_content_item_sr_xml : print_content_item_sr); + return print_func(stream, "ItemReceive", item.getName(), item.getInterface(), item.getMember(), + item.getPath(), item.getType(), item.getDecision(), item.isNamePrefix()); } std::ostream &operator<<(std::ostream &stream, const ldp_xml_parser::ItemAccess &item) { diff --git a/src/internal/print_content.hpp b/src/internal/print_content.hpp index c0ffc8f..78f6381 100644 --- a/src/internal/print_content.hpp +++ b/src/internal/print_content.hpp @@ -20,6 +20,10 @@ #include +namespace print_content { +void use_xml_format(const bool xml); +} + namespace FB { std::ostream &operator<<(std::ostream &stream, const FB::File &file); } diff --git a/src/internal/storage_backend_serialized.cpp b/src/internal/storage_backend_serialized.cpp index ef0855b..4859951 100644 --- a/src/internal/storage_backend_serialized.cpp +++ b/src/internal/storage_backend_serialized.cpp @@ -76,7 +76,7 @@ public: ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item); ldp_xml_parser::DecisionItem getDecisionFromSendIndex(const MatchItemSend &item, uid_t uid); - void printContent() const; + void printContent(const bool xml_format = false) const; template ::policy_set_type> const M *getPolicySet(); @@ -288,7 +288,8 @@ bool StorageBackendSerialized::StorageBackendSerializedImpl::initFromXML(const c return init(FB::GetFile(data)); } -void StorageBackendSerialized::StorageBackendSerializedImpl::printContent() const { +void StorageBackendSerialized::StorageBackendSerializedImpl::printContent(const bool xml_format) const { + print_content::use_xml_format(xml_format); std::cerr << *file; } @@ -328,8 +329,8 @@ void StorageBackendSerialized::release() { pimpl->release(); } -void StorageBackendSerialized::printContent() const { - pimpl->printContent(); +void StorageBackendSerialized::printContent(const bool xml_format) const { + pimpl->printContent(xml_format); } template <> bool match(const ldp_xml_parser::MatchItemAccess &match, const FB::ItemAccess *item) { diff --git a/src/internal/storage_backend_serialized.hpp b/src/internal/storage_backend_serialized.hpp index 658e197..ef40013 100644 --- a/src/internal/storage_backend_serialized.hpp +++ b/src/internal/storage_backend_serialized.hpp @@ -34,7 +34,7 @@ public: bool initFromXML(const char *config_name); void release(); - void printContent() const; + void printContent(const bool xml_format = false) const; // Supported template parameters are: // MatchPolicyOwn, MatchPolicySend, MatchPolicyReceive -- 2.7.4 From 189b9045c7f6802f9a9558c497e4eae120e25b3e Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Mon, 26 Aug 2019 20:53:10 +0900 Subject: [PATCH 11/16] coverity fix Change-Id: I124109dfd923f30471c2a0799fa5774f29ee091c Signed-off-by: sanghyeok.oh --- src/internal/serializer.hpp | 113 ++++++++++++++++++++++---------------------- src/kdbus.h | 1 + src/test-serializer.cpp | 3 +- 3 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/internal/serializer.hpp b/src/internal/serializer.hpp index b5a7f68..f7f5bfd 100644 --- a/src/internal/serializer.hpp +++ b/src/internal/serializer.hpp @@ -28,64 +28,65 @@ namespace ldp_xml_parser { - enum class SetType : uint8_t { - OWN, - SEND, - RECEIVE, - ACCESS - }; - - template - using FbOff = flatbuffers::Offset; - - class Serializer { - private: - template - struct type_helper; - - const ldp_xml::StorageBackendXML *m_db; - flatbuffers::FlatBufferBuilder m_builder; - - template - auto get_create_set() -> decltype(type_helper::create_set); - template - auto get_create_policy() -> decltype(type_helper::create_policy); - template - auto get_create_policy_pair() -> decltype(type_helper::create_policy_pair); - template - auto get_create_item() -> decltype(type_helper::create_item); - - FbOff serialize_tree(const OwnershipTree &tree); - FbOff serialize_tree(const std::shared_ptr &node); - FbOff serialize_decision(const DecisionItem &item); - - template - auto serialize_item(const P &item) -> FbOff::item>; - - template - auto serialize_policy(const T &policy) -> FbOff::policy>; + enum class SetType : uint8_t { + OWN, + SEND, + RECEIVE, + ACCESS + }; template - auto serialize_policy(const std::vector::item>> items) - -> FbOff::policy>; - - template - auto serialize_pair(const long int id, const P policy) - -> FbOff::pair>; - - template - auto serialize_set() -> FbOff::set>; - - template - auto serialize_set(FbOff context_default, - FbOff context_mandatory) - -> FbOff::set>; - public: - uint8_t *serialize(const ldp_xml::StorageBackendXML &db, size_t &size); - uint8_t *serialize(const std::string config_path, size_t &size); - uint8_t *serialize(const std::string config_path, std::ostream &output); - friend class SerializerTests; - }; + using FbOff = flatbuffers::Offset; + + class Serializer { + private: + template + struct type_helper; + + const ldp_xml::StorageBackendXML *m_db; + flatbuffers::FlatBufferBuilder m_builder; + + template + auto get_create_set() -> decltype(type_helper::create_set); + template + auto get_create_policy() -> decltype(type_helper::create_policy); + template + auto get_create_policy_pair() -> decltype(type_helper::create_policy_pair); + template + auto get_create_item() -> decltype(type_helper::create_item); + + FbOff serialize_tree(const OwnershipTree &tree); + FbOff serialize_tree(const std::shared_ptr &node); + FbOff serialize_decision(const DecisionItem &item); + + template + auto serialize_item(const P &item) -> FbOff::item>; + + template + auto serialize_policy(const T &policy) -> FbOff::policy>; + + template + auto serialize_policy(const std::vector::item>> items) + -> FbOff::policy>; + + template + auto serialize_pair(const long int id, const P policy) + -> FbOff::pair>; + + template + auto serialize_set() -> FbOff::set>; + + template + auto serialize_set(FbOff context_default, + FbOff context_mandatory) + -> FbOff::set>; + public: + Serializer() : m_db(nullptr) {} + uint8_t *serialize(const ldp_xml::StorageBackendXML &db, size_t &size); + uint8_t *serialize(const std::string config_path, size_t &size); + uint8_t *serialize(const std::string config_path, std::ostream &output); + friend class SerializerTests; + }; } diff --git a/src/kdbus.h b/src/kdbus.h index 22b7ec5..567b4e8 100644 --- a/src/kdbus.h +++ b/src/kdbus.h @@ -33,6 +33,7 @@ class KdbusConnection { uint64_t attach_flags_send, uint64_t attach_flags_recv); public: + KdbusConnection() : fd(0), pool(nullptr) {} typedef enum { POLICY_CONN_INFO_ALL, POLICY_CONN_INFO_NAME } conn_info_type; void shared_init_fd(int fd_to_set) { fd = fd_to_set; } diff --git a/src/test-serializer.cpp b/src/test-serializer.cpp index 3461301..9f8c89e 100644 --- a/src/test-serializer.cpp +++ b/src/test-serializer.cpp @@ -405,7 +405,8 @@ class SerializerTests { checkPolicy(file->m_access_set()->context_mandatory(), item_access_context_mandatory_test); } - public: +public: + SerializerTests() : file(nullptr) {} bool run_all_tests(const std::string &config) { serialize_xml(config); -- 2.7.4 From 58142065510eed6dbcfd5a1804c53b2d8b3e3f81 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Tue, 3 Sep 2019 10:11:22 +0200 Subject: [PATCH 12/16] printer: fix 'v' argument ':' in getopt list means that the option requires an argument. 'v' option does not require argument. Change-Id: I63052b80e8ed9cc6df93524b7052f8f1c77a8773 --- src/dbuspolicy_printer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dbuspolicy_printer.cpp b/src/dbuspolicy_printer.cpp index 778ff69..44018b4 100644 --- a/src/dbuspolicy_printer.cpp +++ b/src/dbuspolicy_printer.cpp @@ -34,7 +34,7 @@ int main(int argc, char *argv[]) { while (1) { int option_index; - c = getopt_long(argc, argv, "i:v:x", options, &option_index); + c = getopt_long(argc, argv, "i:vx", options, &option_index); if (c == -1) break; -- 2.7.4 From 1fe6f615ce186f1802c919916ae75c490eb376e6 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Fri, 6 Sep 2019 13:06:31 +0200 Subject: [PATCH 13/16] src: fix non-linking with some compilers/linkers We got a report that the library does not link within some environments, giving messages like: undefined reference to `BusPathResolver::KDBUS_SYSTEM_BUS_PATH' This is due to missing definition of static constexpr fields. It is not necessary to give such definition when a field is initialized inline since C++17, but this is compiled with C++11. This commit adds definition of static constexpr fields. Change-Id: Ia354f0e1aa5f1051571bf328fc654627f69c5dbd --- src/libdbuspolicy1.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libdbuspolicy1.cpp b/src/libdbuspolicy1.cpp index 74c8ed2..404dad7 100644 --- a/src/libdbuspolicy1.cpp +++ b/src/libdbuspolicy1.cpp @@ -273,6 +273,9 @@ public: uid_t bus_owner() { return owner; } }; +constexpr boost::string_ref BusPathResolver::KDBUS_PATH_PREFIX; +constexpr boost::string_ref BusPathResolver::KDBUS_SYSTEM_BUS_PATH; + DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd) { assert(bus_path); -- 2.7.4 From 6b7a89694e4c95c171362d659dbcb12b4234a4b6 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Tue, 17 Sep 2019 14:44:06 +0900 Subject: [PATCH 14/16] svace fix Change-Id: Ie5f39ba6e883d259b6da10c4052000cae5e4c738 Signed-off-by: sanghyeok.oh --- src/dbuspolicy_finder.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbuspolicy_finder.cpp b/src/dbuspolicy_finder.cpp index 674b534..b4914c6 100644 --- a/src/dbuspolicy_finder.cpp +++ b/src/dbuspolicy_finder.cpp @@ -227,7 +227,7 @@ template <> void matchPolicy(const PolicyAccess & policy, const Ma } } -template void pickPolicy(const StorageBackendXML & storage, const typename T::item_type::match_type & mi, uid_t numberUser, gid_t numberGroup, bool noFilter) { +template void pickPolicy(const StorageBackendXML & storage, const typename T::item_type::match_type & mi, uid_t numberUser, gid_t numberGroup, bool noFilter) noexcept { matchPolicy(storage.getPolicyContextDefault(), mi, noFilter, "Context Default:"); const auto & groups = storage.getPoliciesGroup(); @@ -312,7 +312,7 @@ int bailOut(const std::string & error) { } void getToken(const std::string & long_name, std::string & interface, std::string & member, MessageType & type, std::string & serviceName, - gid_t & numberGroup, uid_t & numberUser, std::string & path) + gid_t & numberGroup, uid_t & numberUser, std::string & path) noexcept { std::string short_name = long_name; -- 2.7.4 From 9a4f9bd5959b6082645c8bf966a68d667da7baa2 Mon Sep 17 00:00:00 2001 From: "sanghyeok.oh" Date: Tue, 17 Sep 2019 15:40:43 +0900 Subject: [PATCH 15/16] svace fix:add catch - std::out_of_range Change-Id: I2bf65edb452d6d4baeeabc34682825e56ef69199 Signed-off-by: sanghyeok.oh --- src/dbuspolicy_finder.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/dbuspolicy_finder.cpp b/src/dbuspolicy_finder.cpp index b4914c6..f22e4cd 100644 --- a/src/dbuspolicy_finder.cpp +++ b/src/dbuspolicy_finder.cpp @@ -312,7 +312,7 @@ int bailOut(const std::string & error) { } void getToken(const std::string & long_name, std::string & interface, std::string & member, MessageType & type, std::string & serviceName, - gid_t & numberGroup, uid_t & numberUser, std::string & path) noexcept + gid_t & numberGroup, uid_t & numberUser, std::string & path) { std::string short_name = long_name; @@ -445,6 +445,8 @@ int main(int argc, char *argv[]) { getToken(str, interface, member, type, serviceName, numberGroup, numberUser, path); } catch (std::invalid_argument & e) { return bailOut(e.what()); + } catch (std::out_of_range & e) { + return bailOut(e.what()); } break; } -- 2.7.4 From 14744f64568d1875f1680b720f3c62d2488ec242 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Mon, 7 Oct 2019 11:08:32 +0200 Subject: [PATCH 16/16] doc: overview, purpose, design, implementation The description of the libdbuspolicy project. It includes the overview, the purpose, the description of the design and the implementation, and additionally notes for improvements made or considered. Change-Id: I6b0bc9028ed86cb688d0dac9e910c10d3c4d8bc5 (cherry picked from commit 92c61f4ae8c64d2be5adf809c1ba10a1cdb5e905) --- doc/documentation.rst | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 doc/documentation.rst diff --git a/doc/documentation.rst b/doc/documentation.rst new file mode 100644 index 0000000..00b4ade --- /dev/null +++ b/doc/documentation.rst @@ -0,0 +1,114 @@ +Libdbuspolicy documentation +--------------------------- + +This document describes purpose, assumptions, and implementation of libdbuspolicy. + +Doxygen docs +------------ + +API and many internal functions and methods are described in doxygen markups through the code. +This document does not describe API or any particular function or method. + +Purpose +------- + +Tizen on some platforms supports kdbus, an in-kernel D-Bus implementation. Kdbus systems +work without central D-Bus daemon (dbus-daemon) running. Messages are passed between +processes by the kernel driver. The driver supports some kind of access control, +but it is not sufficient for Tizen. For example, it does not support Cynara privileges. + +That's why this library has been created. It controls accesses and sits between +D-Bus libraries and the kdbus driver. D-Bus libraries, which support libdbuspolicy +are libdbus and glib. systemd's sd-bus does not support libdbuspolicy. Libdbuspolicy +uses standard XML policy files as defined for dbus-daemon. + +Security considerations +----------------------- + +If a rogue program is executed, it can bypass libdbus, glib and libdbuspolicy +and connect directly to kdbus to send or receive messages. Only file access rules apply. +However, if other clients use standard libdbus or glib libraries, the messages +will be checked against both sending and receiving policy. The only real +downside is owning policy. A rogue program can own any name, and even hijack names +from other owners. + +Implementation (a bit of history) +------------------------------------- + +Implementation of libdbuspolicy went through several phases. In the first phase +a database of rules was created. The database was in fact two databases: system and session +database. Each of them was divided into default, mandatory, user and group sub-databases. + +This basic structure was maintained at least until 2019. + +In 2018 it appeared that memory consumption of the database was too big. Heavy kilobytes +multiplied by over a hundred of processes were taking up heavy megabytes. Additionally, +initialization of the database slowed down each program which was using D-Bus. This led +to code refactoring and introducing serialization. + +Google's FlatBuffers (https://google.github.io/flatbuffers/) were selected to implement +serialization. In order to do that, the code was heavily refactored. + +Layers +------ + +There are the following layers in libdbuspolicy: + +#. API and programs: library code for connecting database searches with acquiring data from kdbus, + and program code for the utilities, i.e. printer, serializer, finder; +#. checking: library code for handling access check requests, with full information; it performs + several database queries per one check; +#. database: data keeping, searching and converting; +#. FlatBuffers: serialization and deserialization. + +There is also some helping code for printing diagnostics, etc. + +Design +------ + +The almost current overview of the design of the checking, database, and FlatBuffers layers: + +.. image:: dia/Classes-use-only-serialized.png + +Diagram description: + +#. MatchItem, MatchItemWithUserAndGroup - queries constructed by PolicyChecker; +#. PolicyChecker - entry point for checking policy; creates MatchItems to pass them + to StorageBackendSerialized; +#. StorageBackend - interface class; defines query interface for PolicyChecker, + and provides entry point for printing content; +#. StorageBackendXML - storage specific for XML-based data; supports adding items and + provides accessory functions for serialization; serves as an intermediate stage + for StorageBackendSerialized; +#. XmlParser - parser for XML data; creates items and adds them to StorageBackendXML; +#. StorageBackendSerialized - storage specific for serialized data; +#. Serializer - a translator between XML-based data and serialized data; used as an + entry point for serializator tool; used for creating serialized data from + StorageBackendXML; +#. Printer - an entry point for printer tool; +#. FlatBuffers - a library used for management of serialized data. + +The implementation differs from the design mostly in these ways: + +#. StorageBackendXML no longer is able to get decisions (getDecisionItem*), it is used + only for conversion to serialized form (StorageBackendSerialized) +#. Additional use case, Finder, was added; it's a bit like 'grep' for policies: prints + matching rules for a given query + +Improvements +------------ + +Instead of a direct linear search a simple mapping index for send rules was introduced +in StorageBackendSerialized. Basically, it creates a map for send_destination names. +Send_destination is a parameter by which the rules differ the most. Thus, "splitting" +linear search over just matching send_destination names gives significant performance +boost. As of Oct 2019 it has been implemented without the serialization. It needs +about 15KB per process. Therefore, there is a plan to add the serialization to the index. + +Additionally, there is a concept of creating a direct acycling graph containing the rules. +It would contains "levels", for keeping track of various parts of the query/key +(name, interface, method, object, message type, etc.). Each level is dedicated for +one part. A node in a level in which key is a text can be e.g. a trie. A query would +traverse the dag through levels, until reaching a leaf with ALLOW, DENY or CHECK value. +Creating and serializing such graph would make the querying process very fast and low-memory +consuming. -- 2.7.4