Fixed kdbus pool memory managment.
Refactored tslog (getenv called only once).
Removed duplicated credential information.
Dropped unused timeouts.
Added lockless calls when logs are disabled.
Removed udesc allocation.
Decreased KDBUS_POOL_SIZE from 16M to 1M.
Minor fixes.
Change-Id: I1e5fda8df4dbd1dd6dfecae60aff6d7d67705a3b
#define SYSTEM_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/system-local.conf"
#define SESSION_BUS_CONF_FILE_SECONDARY "/etc/dbus-1/session-local.conf"
-#define SYSTEM_BUS 1
-#define SESSION_BUS 2
-
/** used when check policy for message prepared to send */
#define DBUSPOLICY_DIRECTION_SENDING 0
extern "C" {
#endif
-static const char* get_bus(int bus_type) {
- return (bus_type == SYSTEM_BUS) ? "SYSTEM" : "SESSION";
-}
-
static const char* get_str(const char* const szstr) {
return (szstr != NULL) ? szstr : "";
}
+static std::string get_strv(const char *s) {
+ unsigned i = 0;
+ if (s) {
+ i = -1;
+ char c;
+ while ((c = s[++i]) && ' ' != c);
+ }
+ return std::string{s, i};
+}
+
static const char* get_message_type(int type) {
const char* sztype;
switch(type) {
return sztype;
}
-int __internal_init(unsigned int bus_type, const char* const config_name)
+int __internal_init(bool bus_type, const char* const config_name)
{
- _ldp_xml_parser::XmlAsyncParser p;
- auto err = p.parse_policy(get_bus(bus_type), get_str(config_name));
+ _ldp_xml_parser::XmlParser p;
+ auto err = p.parse_policy(bus_type, get_str(config_name));
return err.get();
}
-int __internal_can_send(unsigned int bus_type,
+pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void __internal_init_once()
+{
+ tslog::init();
+}
+
+void __internal_init_flush_logs()
+{
+ if (tslog::enabled()) {
+ pthread_mutex_lock(&g_mutex);
+ std::cout << std::flush;
+ pthread_mutex_unlock(&g_mutex);
+ }
+}
+
+void __internal_enter()
+{
+ if (tslog::enabled())
+ pthread_mutex_lock(&g_mutex);
+}
+void __internal_exit()
+{
+ if (tslog::enabled())
+ pthread_mutex_unlock(&g_mutex);
+}
+
+int __internal_can_send(bool bus_type,
const char* const user,
const char* const group,
const char* const label,
const char* const member,
int type)
{
- _ldp_xml_parser::XmlAsyncParser p;
- auto err = p.can_send(get_bus(bus_type), get_str(user), get_str(group), get_str(label), get_str(destination), get_str(path), get_str(interface), get_str(member), get_message_type(type));
+ _ldp_xml_parser::XmlParser p;
+ auto err = p.can_send(bus_type, get_str(user), get_str(group), get_str(label), get_strv(destination), get_str(path), get_str(interface), get_str(member), get_message_type(type));
return err.get();
}
-int __internal_can_recv(unsigned int bus_type,
+int __internal_can_recv(bool bus_type,
const char* const user,
const char* const group,
const char* const label,
const char* const member,
int type)
{
- _ldp_xml_parser::XmlAsyncParser p;
- auto err = p.can_recv(get_bus(bus_type), get_str(user), get_str(group), get_str(label), get_str(sender), get_str(path), get_str(interface), get_str(member), get_message_type(type));
+ _ldp_xml_parser::XmlParser p;
+ auto err = p.can_recv(bus_type, get_str(user), get_str(group), get_str(label), get_strv(sender), get_str(path), get_str(interface), get_str(member), get_message_type(type));
return err.get();
}
-int __internal_can_own(unsigned int bus_type,
+int __internal_can_own(bool bus_type,
const char* const user,
const char* const group,
const char* const service)
{
- _ldp_xml_parser::XmlAsyncParser p;
- auto err = p.can_own(get_bus(bus_type), get_str(user), get_str(group), get_str(service));
+ _ldp_xml_parser::XmlParser p;
+ auto err = p.can_own(bus_type, get_str(user), get_str(group), get_str(service));
return err.get();
}
#endif
int __internal_init(unsigned int bus_type, const char* const config_name);
+void __internal_init_once(void);
+extern pthread_mutex_t g_mutex;
+void __internal_init_flush_logs(void);
+void __internal_enter(void);
+void __internal_exit(void);
-int __internal_can_send(unsigned int bus_type,
+int __internal_can_send(bool bus_type,
const char* const user,
const char* const group,
const char* const label,
const char* const member,
int type);
-int __internal_can_recv(unsigned int bus_type,
+int __internal_can_recv(bool bus_type,
const char* const user,
const char* const group,
const char* const label,
const char* const member,
int type);
-int __internal_can_own(unsigned int bus_type,
+int __internal_can_own(bool bus_type,
const char* const user,
const char* const group,
const char* const service);
#include <string>
+namespace arraySizeDetail {
+ template <class T, size_t S> constexpr size_t size(T const (&)[S]) { return S; }
+ template <class T> constexpr size_t size(std::initializer_list<T> const &l) { return l.size(); }
+}
+#define TABSIZE(...) (::arraySizeDetail::size(__VA_ARGS__))
+
namespace {
class ErrCode {
int m_err;
ErrCode(int e, const std::string& s) : m_err(e), m_err_str(s) {}
public:
ErrCode() : m_err(0), m_err_str("") {}
- virtual ~ErrCode() {}
static ErrCode ok() {
return ErrCode(0, "OK");
return ErrCode(-1, what);
}
- static ErrCode timeout(const std::string& what) {
- return ErrCode(-99, std::string("Timeout: ") + what);
- }
-
int get() const {
return m_err;
}
+++ /dev/null
-/*
- * Copyright (c) 2015 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.
-*/
-
-#ifndef _TIMER_HPP
-#define _TIMER_HPP
-#include <chrono>
-
-namespace _ldp_timer
-{
- template<typename BaseTimeUnit = std::chrono::nanoseconds>
- class Duration : public BaseTimeUnit {
- public:
- void setNanoTime(std::chrono::nanoseconds nano) {
- BaseTimeUnit d = std::chrono::duration_cast<BaseTimeUnit>(nano);
- BaseTimeUnit::operator =(d);
- }
-
- double getSeconds() {
- typename BaseTimeUnit::period p;
- return 1.0 * BaseTimeUnit::count() * p.num/p.den;
- }
-
- uint64_t getNativeTime() {
- return BaseTimeUnit::count();
- }
-
- friend std::ostream& operator<< (std::ostream& os,
- const Duration<BaseTimeUnit>& d) {
- typename BaseTimeUnit::period p;
- std::string unit;
- switch(p.den/p.num) {
- case 1000000000: unit = "ns"; break;
- case 1000000: unit = "us"; break;
- case 1000: unit = "ms"; break;
- case 1: unit = "s"; break;
- }
-
- os << d.count() << " " << unit;
- return os;
- }
- };
-
- typedef Duration<std::chrono::nanoseconds> nanosec;
- typedef Duration<std::chrono::microseconds> microsec;
- typedef Duration<std::chrono::milliseconds> millisec;
- typedef Duration<std::chrono::seconds> sec;
-
- template<typename _T = nanosec>
- class Timer {
- typedef std::chrono::steady_clock CLK;
- CLK::time_point tbegin;
- _T* const pOT;
- public:
- Timer(_T* const pTP)
- : tbegin(CLK::now()), pOT(pTP) {}
-
- virtual ~Timer() {
- if(pOT)
- pOT->setNanoTime(CLK::now() - tbegin);
- }
- };
-}
-
-#endif // _TIMER_HPP
#include <iostream>
#include <thread>
-#include <mutex>
+#include <pthread.h>
#include <stdlib.h>
-namespace _ldp_tslog
-{
- typedef std::ostream& (*t_ManFun)(std::ostream&);
-
- namespace {
- static constexpr bool LOG_DEFAULT_ENABLE = false;
- static constexpr bool LOG_DEFAULT_VERBOSE = false;
- static const std::string LDP_ENV_VERBOSE_NAME = "LDP_VERBOSE";
- static const std::string LDP_ENV_LOG_NAME = "LDP_LOG";
-
- const bool get_log_env(const std::string& name) {
- bool bret;
- char* ldp_log_mode = getenv(name.c_str());
- if(ldp_log_mode) {
- const std::string slog(ldp_log_mode);
- bret = (slog == "0") ? false : true;
- } else {
- bret = (name == LDP_ENV_LOG_NAME) ? LOG_DEFAULT_ENABLE : LOG_DEFAULT_VERBOSE;
- }
- return bret;
- }
- }
-
- const bool get_verbose() {
- return get_log_env(LDP_ENV_VERBOSE_NAME);
- }
-
- const bool get_enable() {
- return get_log_env(LDP_ENV_LOG_NAME);
- }
-
- class TsLog
- {
- private:
- static bool m_verbose;
- static std::mutex m_mtx;
- std::ostream& m_os;
- bool m_enable;
+typedef std::ostream& (*t_ManFun)(std::ostream&);
- template<typename T>
- TsLog& lckLog(const T& t) {
- if(m_enable) {
- std::unique_lock<std::mutex> lck(m_mtx);
- m_os << t;
- }
- return *this;
- }
-
- public:
- TsLog() = delete;
-
- explicit TsLog(std::ostream& os, bool enable = true)
- : m_os(os), m_enable(enable) {}
-
- virtual ~TsLog() {}
+namespace tslog
+{
+ int8_t g_verbosity; // <0 disable 0 brief >0 verbose
- template<typename T>
- TsLog& operator<< (const T& t) {
- return lckLog<T>(t);
- }
+ bool get_log_env(char const *name) {
+ char const *ldp_log_mode = getenv(name);
+ return ldp_log_mode && '0' != *ldp_log_mode;
+ }
- TsLog& operator<< (t_ManFun f) {
- return lckLog<t_ManFun>(f);
- }
+ void init() {
+ g_verbosity = get_log_env("LDP_LOG") ? get_log_env("LDP_VERBOSE") : -1;
+ }
- };
- std::mutex TsLog::m_mtx;
+ bool enabled() { return g_verbosity >= 0; }
+ bool verbose() { return g_verbosity > 0; }
}
-namespace {
- //Thread-safe loggers
- _ldp_tslog::TsLog tout(std::cout, _ldp_tslog::get_enable());
- _ldp_tslog::TsLog terr(std::cerr, _ldp_tslog::get_enable());
-
- namespace verbose {
- _ldp_tslog::TsLog tout(std::cout, _ldp_tslog::get_enable() && _ldp_tslog::get_verbose());
- _ldp_tslog::TsLog terr(std::cerr, _ldp_tslog::get_enable() && _ldp_tslog::get_verbose());
- }
-} //namespace
-
#endif
#ifndef _XML_PARSER_HPP
#define _XML_PARSER_HPP
-#include <map>
-#include <thread>
-#include <future>
+#include <set>
#include <boost/noncopyable.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
-#include <boost/functional/hash.hpp>
#include <dirent.h>
#include <libgen.h>
-#include "timer.hpp"
#include "xml_policy.hpp"
namespace _ldp_xml_parser
{
- class XmlAsyncParser : boost::noncopyable
+ class XmlParser : boost::noncopyable
{
public:
- XmlAsyncParser() {
- }
-
- virtual ~XmlAsyncParser() {
- }
-
- ErrCode parse_policy(const std::string bus,
- const std::string fname,
- const std::chrono::milliseconds timeout = std::chrono::milliseconds(std::numeric_limits<int32_t>::max())) {
- set_policy_bus_filename(bus, fname);
- m_xml_policy.init();
- ErrCode err = parse(timeout);
+ ErrCode parse_policy(bool bus,
+ std::string const &fname) {
+ ErrCode err = parse(bus, fname);
return err;
}
- ErrCode can_send(const std::string bus,
+ ErrCode can_send(bool bus,
const std::string user,
const std::string group,
const std::string label,
return m_xml_policy.can_send_to(bus, idx_v, label);
}
- ErrCode can_recv(const std::string bus,
+ ErrCode can_recv(bool bus,
const std::string user,
const std::string group,
const std::string label,
return m_xml_policy.can_recv_from(bus, idx_v, label);
}
- ErrCode can_own(const std::string bus,
+ ErrCode can_own(bool bus,
const std::string user,
const std::string group,
const std::string service) {
private:
//IO operation
- std::string m_bus;
- std::string m_filename;
- static std::map<std::string, std::size_t> m_hashes;
- static std::mutex m_io_xml_mtx;
+ static std::set<std::string> m_parsed;
//Data obtained from XML
static XmlPolicy m_xml_policy;
- //Called by calling user thread
- void set_policy_bus_filename(const std::string& bus, const std::string& fname) {
- m_filename = fname;
- m_bus = bus;
- }
-
- const std::string& get_policy_bus() const {
- return m_bus;
- }
-
- const std::string& get_policy_filename() const {
- return m_filename;
- }
-
- ErrCode parse(const std::chrono::milliseconds timeout) {
+ ErrCode parse(bool bus, std::string const &filename) {
ErrCode err;
std::vector<std::string> incl_files;
- err = parse(get_policy_filename(), incl_files, timeout);
- if(err.is_ok()) {
+ err = parse(bus, true, filename, incl_files);
+ if (err.is_ok())
for(const auto& x : incl_files) {
- err = parse(x, incl_files, timeout);
- if(err.is_error()) { break; }
+ err = parse(bus, false, x, incl_files);
+ if (err.is_error()) break;
}
- }
- if(err.is_ok()) {
- m_xml_policy.print_decision_trees();
- }
+ if(err.is_ok())
+ m_xml_policy.print_decision_trees(bus);
return err;
}
- ErrCode parse(const std::string& filename, std::vector<std::string>& included_files, const std::chrono::milliseconds timeout) {
+ ErrCode parse(bool bus, bool first, const std::string& filename, std::vector<std::string>& included_files) {
std::pair<ErrCode, std::string> errparam;
- verbose::tout << "=== XML PARSING BEGIN === : " << filename << std::endl;
+ if (tslog::verbose())
+ std::cout << "=== XML PARSING BEGIN === : " << filename << '\n';
- auto fut = std::async(std::launch::async, &XmlAsyncParser::async_xml_parse, this, filename);
-
- auto r = fut.wait_for(timeout);
- if(r == std::future_status::ready) {
- errparam = fut.get();
- if(errparam.first.get() >= 0) {
- get_included_files(filename, errparam.second, included_files);
- }
- } else if(r == std::future_status::timeout) {
- errparam.first = ErrCode::timeout("XML parsing timeout");
- }
+ errparam = xml_parse(bus, filename);
+ if (first && errparam.first.get() >= 0 && errparam.second != "")
+ get_included_files(filename, errparam.second, included_files);
- verbose::tout << "=== XML PARSING END ===" << std::endl << std::endl;
- tout << "Processing of " << filename << " -> [" << errparam.first.get() << ", " << errparam.first.get_str() << "]" << std::endl;
+ if (tslog::enabled()) {
+ if (tslog::verbose())
+ std::cout << "=== XML PARSING END ===\n\n";
+ std::cout << "Processing of " << filename << " -> [" << errparam.first.get() << ", " << errparam.first.get_str() << "]\n";
+ }
return errparam.first;
}
//Get all the .conf files within included subdirectory, POSIX style as boost::filesystem is not header-only
void get_included_files(const std::string& filename, const std::string& incldir, std::vector<std::string>& files) {
- if(get_policy_filename() == filename && incldir != "") {
- DIR *dir;
- struct dirent *ent;
- std::string fname;
- std::copy(filename.begin(), filename.end(), fname.begin());
- std::string dname = dirname(const_cast<char*>(fname.c_str()));
- dname += (std::string("/") + incldir);
- files.clear();
- if((dir = opendir(dname.c_str())) != NULL) {
- while((ent = readdir(dir)) != NULL) {
- std::string s(ent->d_name);
- if(s.find(".conf") != std::string::npos) {
- files.push_back(dname + std::string("/") + s);
- }
- }
- closedir(dir);
-
- tout << std::endl << "includedir for " << filename << " is " << incldir << ", " << files.size() << " included files found:" << std::endl;
- if(_ldp_tslog::get_enable()) { std::copy(files.begin(), files.end(), std::ostream_iterator<std::string>(std::cout, "\n")); }
- tout << std::endl;
- } else {
- terr << "could not open directory " << dname << std::endl;
- }
- }
- }
-
- //All 'async_*' methods are executed in library's internal worker threads
- std::pair<ErrCode, std::string> async_xml_parse(const std::string& filename) {
+ DIR *dir;
+ struct dirent *ent;
+ std::string fname;
+ std::copy(filename.begin(), filename.end(), fname.begin());
+ std::string dname = dirname(const_cast<char*>(fname.c_str()));
+ dname += (std::string("/") + incldir);
+ files.clear();
+ if((dir = opendir(dname.c_str())) != NULL) {
+ while((ent = readdir(dir)) != NULL) {
+ std::string s(ent->d_name);
+ if(s.find(".conf") != std::string::npos) {
+ files.push_back(dname + std::string("/") + s);
+ }
+ }
+ closedir(dir);
+
+ if (tslog::enabled()) {
+ std::cout << "\nincludedir for " << filename << " is " << incldir << ", " << files.size() << " included files found:\n";
+ std::copy(files.begin(), files.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
+ std::cout << '\n';
+ }
+ } else if (tslog::enabled())
+ std::cout << "could not open directory " << dname << '\n';
+ }
+
+ std::pair<ErrCode, std::string> xml_parse(bool bus, const std::string& filename) {
std::pair<ErrCode, std::string> ret;
- _ldp_timer::microsec latency;
- try {
- boost::property_tree::ptree pt;
+ if (m_parsed.insert(filename).second)
+ try {
+ boost::property_tree::ptree pt;
+ read_xml(filename, pt);
+ if (!pt.empty()) {
+ m_xml_policy.update(bus, pt);
+ ret.second = pt.get("busconfig.includedir", "");
+ }
+ } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) {
+ ret.first = ErrCode::error(ex.what());
+ } catch(const boost::property_tree::ptree_error& ex) {
+ ret.first = ErrCode::error(ex.what());
+ } catch(...) {
+ ret.first = ErrCode::error(filename + std::string(": unknown error while parsing XML"));
+ }
- //XML file IO critical section
- {
- std::unique_lock<std::mutex> lck(m_io_xml_mtx);
- _ldp_timer::Timer<_ldp_timer::microsec> t(&latency);
-
- std::size_t hash;
- if(async_xml_parsing_needed(filename, hash)) {
- read_xml(filename, pt);
- async_xml_hash_update(filename, hash);
- }
- }
-
- m_xml_policy.update(get_policy_bus(), pt);
-
- ret.second = pt.get("busconfig.includedir", "");
-
- ret.first = ErrCode::ok();
- } catch(const boost::property_tree::xml_parser::xml_parser_error& ex) {
- ret.first = ErrCode::error(ex.what());
- } catch(const boost::property_tree::ptree_error& ex) {
- ret.first = ErrCode::error(ex.what());
- } catch(...) {
- ret.first = ErrCode::error(filename + std::string(": unknown error while parsing XML"));
- }
-
- tout << "XML processing latency: " << latency << std::endl;
- return ret;
- }
-
- std::size_t async_xml_hash(const std::string& filename) {
- std::size_t seed = 0;
- std::ifstream ifs(filename);
- for(std::string line; getline(ifs, line); ) {
- boost::hash_combine(seed, line);
- }
- ifs.close();
-
- return seed;
- }
-
- void async_xml_hash_update(const std::string& filename, const std::size_t hash) {
- auto r = m_hashes.insert(std::pair<std::string, std::size_t>(filename, hash));
- if(r.second == false) {
- auto it = r.first;
- it->second = hash;
- }
- }
-
- bool async_xml_parsing_needed(const std::string& filename, std::size_t& hash) {
- bool ret = false;
- hash = async_xml_hash(filename);
- auto it = m_hashes.find(filename);
- if(it != m_hashes.end()) {
- if(hash == it->second) {
- ret = false;
- } else {
- ret = true;
- }
- } else {
- ret = true;
- }
return ret;
}
-
};
- std::map<std::string, std::size_t> XmlAsyncParser::m_hashes;
- std::mutex XmlAsyncParser::m_io_xml_mtx;
- XmlPolicy XmlAsyncParser::m_xml_policy;
} //namespace
#endif
#include <boost/noncopyable.hpp>
#include <boost/tokenizer.hpp>
#include <boost/property_tree/ptree.hpp>
+#include <map>
#include "libdbuspolicy1-private.hpp"
-#include "timer.hpp"
#include "tslog.hpp"
#include "cynara.hpp"
+enum class TreeType : uint8_t {
+ SEND,
+ RECV,
+ OWN
+};
+
namespace _ldp_xml_parser
{
namespace {
static const size_t IDX_OWN_LENGTH = IDX_SERVICE + 1;
static const size_t IDX_DEFAULT = IDX_GROUP + 1;
- std::string m_bus;
std::vector<std::string> m_path_content;
std::string m_privilege;
bool m_bsend;
bool m_ballow;
static size_t m_weight;
- Key(const std::string& bus)
- : m_bus(bus),
- m_path_content(std::vector<std::string>(IDX_TOTAL_LENGTH, ANY)),
+ Key(bool bus)
+ : m_path_content(std::vector<std::string>(IDX_TOTAL_LENGTH, ANY)),
m_bsend(false),
m_brecv(false),
m_bown(false),
const std::string get_path() const {
std::string path = "R";
auto it_cend = m_bown ? m_path_content.cbegin() + IDX_OWN_LENGTH : m_path_content.cend();
- for(auto it = m_path_content.cbegin(); it != it_cend; ++it) {
- path += (std::string(1, Key::DELIM) + *it);
- }
+ for(auto it = m_path_content.cbegin(); it != it_cend; ++it)
+ (path += Key::DELIM) += *it;
return path;
}
};
}
friend std::ostream& operator<<(std::ostream& os, const Leaf& lf) {
- if(lf.m_check) {
+ if(lf.m_check)
os << "check," << lf.m_privilege << "," << lf.m_weight;
- } else {
+ else
os << (lf.m_decision ? "true" : "false") << "," << lf.m_weight;
- }
return os;
}
for(auto it = tokens.begin(); it != tokens.end(); ++it) {
const auto it_last = std::next(tokens.begin(), size - 1);
if(it == tokens.begin()) {
- if(size > 2) {
+ if(size > 2)
lf.m_check = (*it == "check") ? true : false;
- } else {
+ else
lf.m_decision = (*it == "true") ? true : false;
- }
- } else if(it == it_last) {
+ } else if(it == it_last)
lf.m_weight = std::stoul(*it);
- } else {
- if(size > 2) {
- lf.m_privilege = *it;
- }
- }
+ else if(size > 2)
+ lf.m_privilege = *it;
}
return is;
}
};
- static const std::string get_context_str(const CtxType& ctx_type) {
+ static char const *get_context_str(const CtxType& ctx_type) {
switch(ctx_type) {
case CtxType::DEFAULT: return "(default)"; break;
case CtxType::SPECIFIC: return "(specific)"; break;
}
static const std::string get_field_str(const std::string& field) {
- return (field == "") ? Key::ANY : field;
+ return field == "" ? Key::ANY : field;
}
//Data obtained from XML parsing - decision trees
- typedef std::map<std::string, boost::property_tree::ptree> Trees_t;
- std::map<std::string, Trees_t> m_dec_trees;
- std::mutex m_xml_policy_mtx;
-
- boost::property_tree::ptree* get_decision_tree(const std::string& bus, const std::string& tree_type) {
- boost::property_tree::ptree* p_tree = NULL;
-
- auto it1 = m_dec_trees.find(bus);
- if(it1 != m_dec_trees.end()) {
- auto it2 = it1->second.find(tree_type);
- if(it2 != it1->second.end()) {
- p_tree = &it2->second;
- }
- }
- return p_tree;
+ boost::property_tree::ptree m_dec_trees[2][3];
+
+ boost::property_tree::ptree &get_decision_tree(bool bus, TreeType tree_type) {
+ return m_dec_trees[bus][static_cast<unsigned>(tree_type)];
}
- boost::property_tree::ptree* get_decision_tree(const Key& key) {
- std::string tree_type;
- if(key.m_bsend) { tree_type = "SEND"; }
- else if(key.m_brecv) { tree_type = "RECV"; }
- else if(key.m_bown) { tree_type = "OWN"; }
+ boost::property_tree::ptree* get_decision_tree(bool bus, const Key& key) {
+ TreeType tree_type;
+ if(key.m_bsend) tree_type = TreeType::SEND;
+ else if(key.m_brecv) tree_type = TreeType::RECV;
+ else if(key.m_bown) tree_type = TreeType::OWN;
+ else return NULL;
- return get_decision_tree(key.m_bus, tree_type);
+ return &get_decision_tree(bus, tree_type);
}
void print_decision_tree(const boost::property_tree::ptree& pt, int level = 0) {
}
}
- void print_decision_key(const Key& key) {
- if(_ldp_tslog::get_verbose()) {
- std::string s = key.m_bus + " ";
- if(key.m_bsend && !key.m_brecv) { s += "--> #"; }
- if(!key.m_bsend && key.m_brecv) { s += "<-- #"; }
- if(!key.m_bsend && !key.m_brecv && key.m_bown) { s += "OWN #"; }
+ void print_decision_key(bool bus, const Key& key) {
+ if (tslog::verbose()) {
+ std::string s = bus + " ";
+ if(key.m_bsend && !key.m_brecv) s += "--> #";
+ if(!key.m_bsend && key.m_brecv) s += "<-- #";
+ if(!key.m_bsend && !key.m_brecv && key.m_bown) s += "OWN #";
std::string prv = key.m_bcheck ? key.m_privilege : "";
- verbose::tout << s
+ std::cout << s
<< (key.m_bcheck ? "check " : std::to_string(key.m_ballow))
<< prv
<< " : "
<< key.get_path()
<< " (weight: "
<< key.m_weight
- << ")"
- << std::endl;
+ << ")\n";
}
}
- void update_decision_tree(const Key& key) {
+ void update_decision_tree(bool bus, const Key& key) {
if(!key.get_path().empty()) {
- print_decision_key(key);
+ print_decision_key(bus, key);
//update
- boost::property_tree::ptree* const p_tree = get_decision_tree(key);
+ boost::property_tree::ptree* const p_tree = get_decision_tree(bus, key);
if(p_tree) {
boost::property_tree::ptree::path_type tpath(key.get_path(), Key::DELIM);
p_tree->put(tpath, Leaf(key.m_ballow, key.m_bcheck, key.m_privilege, key.m_weight));
++key.m_weight;
} else {
if(attr) {
- std::string data_str = (v.second.data() == "*") ? Key::ANY : v.second.data();
+ std::string data_str = v.second.data() == "*" ? Key::ANY : v.second.data();
if(v.first == "context") {
if(data_str == "mandatory") {
key.m_path_content[Key::IDX_USER] = Key::MRY;
current_ctx = CtxType::DEFAULT;
}
} else if(v.first == "user") {
- if(current_ctx == CtxType::SPECIFIC) {
+ if(current_ctx == CtxType::SPECIFIC)
key.m_path_content[Key::IDX_USER] = data_str;
- }
} else if(v.first == "group") {
- if(current_ctx == CtxType::SPECIFIC) {
+ if(current_ctx == CtxType::SPECIFIC)
key.m_path_content[Key::IDX_GROUP] = data_str;
- }
} else {
- if(field_has(v, "send_")) {
+ if(field_has(v, "send_"))
key.m_bsend = true;
- }
- if(field_has(v, "receive_")) {
+ if(field_has(v, "receive_"))
key.m_brecv = true;
- }
if(v.first == "own") {
key.m_bown = true;
key.m_path_content[Key::IDX_SERVICE] = data_str;
key.m_bown = true;
key.m_path_content[Key::IDX_SERVICE] = data_str + "*";
}
- if(field_has(v, "_destination")) {
+ if(field_has(v, "_destination"))
key.m_path_content[Key::IDX_DEST] = data_str;
- }
- if(field_has(v, "_sender")) {
+ if(field_has(v, "_sender"))
key.m_path_content[Key::IDX_SENDER] = data_str;
- }
- if(field_has(v, "_path")) {
+ if(field_has(v, "_path"))
key.m_path_content[Key::IDX_PATH] = data_str;
- }
- if(field_has(v, "_interface")) {
+ if(field_has(v, "_interface"))
key.m_path_content[Key::IDX_IFACE] = data_str;
- }
- if(field_has(v, "_member")) {
+ if(field_has(v, "_member"))
key.m_path_content[Key::IDX_MEMBER] = data_str;
- }
- if(field_has(v, "_type")) {
+ if(field_has(v, "_type"))
key.m_path_content[Key::IDX_TYPE] = data_str;
- }
- if(v.first == "privilege") {
+ if(v.first == "privilege")
key.m_privilege = data_str;
- }
key.m_bcheck = bcheck;
key.m_ballow = allden;
}
void print_field(const boost::property_tree::ptree::value_type& v, int level) {
- verbose::tout << ((level > 0) ? std::string((level - 1) * 8, ' ') + std::string(8, '.') : "")
- << v.first
- << " : "
- << v.second.data()
- << std::endl;
+ std::cout << ((level > 0) ? std::string((level - 1) * 8, ' ') + std::string(8, '.') : "")
+ << v.first
+ << " : "
+ << v.second.data()
+ << '\n';
}
- void xml_traversal(const boost::property_tree::ptree& pt,
+ void xml_traversal(bool bus,
+ const boost::property_tree::ptree& pt,
Key& key,
CtxType& current_ctx,
bool allden = false,
if(v.first == "<xmlcomment>") { continue; }
update_decision_path(v, key, current_ctx, allden, bcheck, attr);
- //print_field(v, level);
- xml_traversal(v.second, key, current_ctx, allden, bcheck, attr, level + 1);
+ //if (tslog::verbose()) print_field(v, level);
+ xml_traversal(bus, v.second, key, current_ctx, allden, bcheck, attr, level + 1);
}
- if(!pt.empty() && attr && level > 1) {
- update_decision_tree(key);
- }
- } else {
- terr << "XML traversal max level reached: " << level << std::endl;
- }
+ if(!pt.empty() && attr && level > 1)
+ update_decision_tree(bus, key);
+ } else if (tslog::enabled())
+ std::cout << "XML traversal max level reached: " << level << '\n';
}
void print_indexing_path(size_t idx, const std::string& path, const Leaf& leaf = Leaf(), bool empty = true) {
- if(_ldp_tslog::get_verbose()) {
+ if (tslog::verbose()) {
std::string s;
if(!empty) {
s = " : <";
s += std::string(">");
}
- verbose::tout << "path #"
- << idx
- << " : "
- << path
- << s
- << std::endl;
+ std::cout << "path #"
+ << idx
+ << " : "
+ << path
+ << s
+ << '\n';
}
}
void prepare_indexing_path(const std::vector<std::string>& idx_v,
- const size_t pattern,
+ size_t pattern,
const size_t usrgrp_obfuscate_order,
const bool obfuscate_params,
const CtxType& ctx_type,
std::string& path) {
- const size_t offset = Key::IDX_DEFAULT;
+ constexpr size_t offset = Key::IDX_DEFAULT;
path = "R";
if(ctx_type == CtxType::SPECIFIC) {
- switch(usrgrp_obfuscate_order) {
- case 0:
- path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_USER]));
- path += (std::string(1, Key::DELIM) + Key::ANY);
- break;
- case 1:
- path += (std::string(1, Key::DELIM) + Key::ANY);
- path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_GROUP]));
- break;
- case 2:
- path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_USER]));
- path += (std::string(1, Key::DELIM) + get_field_str(idx_v[Key::IDX_GROUP]));
- break;
- case 3:
- default:
- path += (std::string(1, Key::DELIM) + Key::ANY);
- path += (std::string(1, Key::DELIM) + Key::ANY);
- break;
- }
- } else {
- for(size_t i = 0; i < offset; ++i) {
- const std::string as = (ctx_type == CtxType::MANDATORY) ? Key::MRY : Key::DEF;
- path += (std::string(1, Key::DELIM) + as);
- }
- }
+ path += Key::DELIM;
+ if (usrgrp_obfuscate_order & 1) // 1 3
+ path += Key::ANY;
+ else
+ path += get_field_str(idx_v[Key::IDX_USER]);
+ path += Key::DELIM;
+ if ((usrgrp_obfuscate_order+1) & 2) // 1 2
+ path += get_field_str(idx_v[Key::IDX_GROUP]);
+ else
+ path += Key::ANY;
+ } else
+ for(size_t i = 0; i < offset; ++i)
+ (path += Key::DELIM) += ctx_type == CtxType::MANDATORY ? Key::MRY : Key::DEF;
- const size_t m = 1;
const size_t n = idx_v.size() - offset;
- for(size_t i = 0; i < n; ++i) {
- std::string s = get_field_str(idx_v[i + offset]);
+ for (size_t i = 0; i < n; ++i) {
path += Key::DELIM;
- if(obfuscate_params && (pattern & (m << i))) {
- path += Key::ANY;
- } else {
- path += s;
- }
+ if (obfuscate_params && pattern & 1)
+ path += Key::ANY;
+ else
+ path += get_field_str(idx_v[i + offset]);
+ pattern >>= 1;
}
}
ErrCode service_leaf_found(const Leaf& leaf, const std::string& label, const std::vector<std::string>& idx_v) {
ErrCode err;
if(leaf.get_check()) {
- verbose::tout << __func__
- << ": cynara check needed for privilege " << leaf.get_privilege()
- << ", weight " << leaf.get_weight()
- << std::endl;
+ if (tslog::verbose())
+ std::cout << __func__
+ << ": cynara check needed for privilege " << leaf.get_privilege()
+ << ", weight " << leaf.get_weight()
+ << '\n';
//cynara check
try {
if(!found) { err = ErrCode::error("No path"); }
} catch(...) {
print_indexing_path(p, path);
- verbose::tout << "Unknown exception while indexing decision tree!" << std::endl;
+ if (tslog::verbose())
+ std::cout << "Unknown exception while indexing decision tree!\n";
if(!found) { err = ErrCode::error("Unknown err, no path"); }
}
}
if(found) {
err = service_leaf_found(leaf_found, label, idx_v);
- verbose::tout << __func__ << ": returning decision #" << err.get() << " " << err.get_str() << ", weight " << leaf_found.get_weight() << std::endl;
+ if (tslog::verbose())
+ std::cout << __func__ << ": returning decision #" << err.get() << " " << err.get_str() << ", weight " << leaf_found.get_weight() << '\n';
break;
}
}
const CtxType& ctx_type) {
ErrCode err;
- tout << "context: " << get_context_str(ctx_type) << ", indexing arguments: ";
- if(_ldp_tslog::get_enable()) { std::copy(idx_v.begin(), idx_v.end(), std::ostream_iterator<std::string>(std::cout, ", ")); }
- tout << std::endl;
+ if (tslog::enabled()) {
+ std::cout << "context: " << get_context_str(ctx_type) << ", indexing arguments: ";
+ std::copy(idx_v.begin(), idx_v.end(), std::ostream_iterator<std::string>(std::cout, ", "));
+ std::cout << '\n';
+ }
//Examine policy data and make decision
- _ldp_timer::microsec latency;
- {
- _ldp_timer::Timer<_ldp_timer::microsec> t(&latency);
- err = index_decision_tree(pt, idx_v, label, obfuscate_params, ctx_type);
- }
+ err = index_decision_tree(pt, idx_v, label, obfuscate_params, ctx_type);
- tout << __func__ << ": #" << err.get() << " " << err.get_str() << " " << get_context_str(ctx_type) << std::endl;
- tout << "tree indexing latency: " << latency << std::endl;
+ if (tslog::enabled())
+ std::cout << __func__ << ": #" << err.get() << " " << err.get_str() << " " << get_context_str(ctx_type) << '\n';
return err;
}
- ErrCode can_do_action(const std::string& bus,
- const std::string& tree_type,
+ ErrCode can_do_action(bool bus,
+ TreeType tree_type,
const std::vector<std::string>& idx_v,
const std::string& label = "",
const bool analyze_prefix = false) {
- std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
ErrCode err;
- boost::property_tree::ptree* const p_tree = get_decision_tree(bus, tree_type);
- if(p_tree) {
- err = index_decision_tree_lat(*p_tree, idx_v, label, !analyze_prefix, CtxType::MANDATORY);
- if(!err.is_ok()) {
- err = index_decision_tree_lat(*p_tree, idx_v, label, !analyze_prefix, CtxType::SPECIFIC);
- if(!err.is_ok()) {
- err = index_decision_tree_lat(*p_tree, idx_v, label, !analyze_prefix, CtxType::DEFAULT);
- }
- }
- } else {
- err = ErrCode::error("Get decision tree returned NULL ptr");
- }
- tout << __func__ << ": #" << err.get() << " " << err.get_str() << std::endl;
+ boost::property_tree::ptree const &p_tree = get_decision_tree(bus, tree_type);
+ err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::MANDATORY);
+ if(!err.is_ok()) {
+ err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::SPECIFIC);
+ if(!err.is_ok())
+ err = index_decision_tree_lat(p_tree, idx_v, label, !analyze_prefix, CtxType::DEFAULT);
+ }
+ if (tslog::enabled())
+ std::cout << __func__ << ": #" << err.get() << " " << err.get_str() << '\n';
return err;
}
public:
XmlPolicy() {
- Trees_t t;
- t.emplace("SEND", typename Trees_t::mapped_type());
- t.emplace("RECV", typename Trees_t::mapped_type());
- t.emplace("OWN", typename Trees_t::mapped_type());
- m_dec_trees.emplace("SYSTEM", t);
- m_dec_trees.emplace("SESSION", t);
- }
-
- virtual ~XmlPolicy() {}
-
- void init() {
- std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
Key::m_weight = 0;
}
- void update(const std::string& bus, const boost::property_tree::ptree& pt) {
- if(!pt.empty()) {
- std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
- const auto& children = pt.get_child(ROOT_FIELD);
- for(const auto& x : children) {
- if(x.first == ROOT_POLICY) {
- Key key(bus);
- CtxType current_ctx = CtxType::SPECIFIC;
- xml_traversal(x.second, key, current_ctx);
- }
- }
- }
+ void update(bool bus, const boost::property_tree::ptree& pt) {
+ const auto& children = pt.get_child(ROOT_FIELD);
+ for(const auto& x : children) {
+ if(x.first == ROOT_POLICY) {
+ Key key(bus);
+ CtxType current_ctx = CtxType::SPECIFIC;
+ xml_traversal(bus, x.second, key, current_ctx);
+ }
+ }
}
- ErrCode can_send_to(const std::string bus, const std::vector<std::string>& idx_v, const std::string label) {
- return can_do_action(bus, "SEND", idx_v, label);
+ ErrCode can_send_to(bool bus, const std::vector<std::string>& idx_v, const std::string label) {
+ return can_do_action(bus, TreeType::SEND, idx_v, label);
}
- ErrCode can_recv_from(const std::string bus, const std::vector<std::string>& idx_v, const std::string label) {
- return can_do_action(bus, "RECV", idx_v, label);
+ ErrCode can_recv_from(bool bus, const std::vector<std::string>& idx_v, const std::string label) {
+ return can_do_action(bus, TreeType::RECV, idx_v, label);
}
- ErrCode can_own_what(const std::string bus, const std::vector<std::string>& idx_v) {
+ ErrCode can_own_what(bool bus, const std::vector<std::string>& idx_v) {
ErrCode err;
//Evaluate own_prefix
const size_t srv_size = srv.size();
for(size_t n = 1; n <= srv_size; ++n) {
const std::string sub = srv.substr(0, n) + "*";
- verbose::tout << "own_prefix: " << sub << std::endl;
+ if (tslog::enabled())
+ std::cout << "own_prefix: " << sub << '\n';
iv.pop_back();
iv.push_back(sub);
- err = can_do_action(bus, "OWN", iv, "", true);
- if(err.is_ok()) {
+ err = can_do_action(bus, TreeType::OWN, iv, "", true);
+ if(err.is_ok())
break;
- }
}
//Evaluate own
- if(err.is_error()) {
- err = can_do_action(bus, "OWN", idx_v);
- }
+ if(err.is_error())
+ err = can_do_action(bus, TreeType::OWN, idx_v);
return err;
}
- void print_decision_trees() {
- if(_ldp_tslog::get_verbose()) {
- std::unique_lock<std::mutex> lck(m_xml_policy_mtx);
-
- for(const auto& x : m_dec_trees) {
- for(const auto& y : x.second) {
- verbose::tout << x.first << " " << y.first << " " << (y.second.empty() ? "(empty)" : "") << std::endl;
+ void print_decision_trees(bool bus) {
+ if (tslog::verbose())
+ for (unsigned i = 0; i < TABSIZE(m_dec_trees[bus]); ++i)
+ for(auto const& y : m_dec_trees[bus][i]) {
+ std::cout << i << " " << y.first << " " << (y.second.empty() ? "(empty)" : "") << '\n';
print_decision_tree(y.second);
}
- }
- }
}
}; //XmlPolicy
#define DBUSPOLICY1_EXPORT __attribute__ ((visibility("default")))
+typedef uint8_t dbus_name_len;
+#define MAX_DBUS_NAME_LEN 255
+
#endif
#include <pwd.h>
#include <grp.h>
#include <limits.h>
+#include <pthread.h>
#include <dbuspolicy1/libdbuspolicy1.h>
#include "libdbuspolicy1-private.h"
#define KDBUS_PATH_PREFIX "/sys/fs/kdbus/"
#define KDBUS_SYSTEM_BUS_PATH "/sys/fs/kdbus/0-system/bus"
+#define KDBUS_POOL_SIZE (1024UL * 1024UL)
-#define KDBUS_POOL_SIZE (16 * 1024UL * 1024UL)
+#define SYSTEM_BUS 0
+#define SESSION_BUS 1
#define ALIGN8(l) (((l) + 7) & ~7)
+#define ALIGNDN8(l) ((l) & ~7)
#define UID_INVALID ((uid_t) -1)
#define GID_INVALID ((gid_t) -1)
-#define FOREACH_STRV(i,l, s, os)\
-for(\
-({\
-i=0;\
-l = strlen(s);\
-name = malloc(sizeof(char*)*(l+1));\
-strncpy(os, s, sizeof(char*)*(l+1)-1);\
-});\
-i < l;\
-i++)
-
-#define GET_NEXT_STR(i,s,os)\
- os = s+i;\
- for(;s[i] && s[i] != ' ';i++);\
- s[i] = 0;
-
+static char const *foreach_strv_advance(char const *str) {
+ char c;
+ while ((c = *str++))
+ if (' ' == c)
+ return str;
+ return NULL;
+}
+/* iterate over STR; iterate once with "" if !STR or !*STR */
+#define FOREACH_STRV_DEFAULT(ITERLVALPTR,STR) for (\
+ ITERLVALPTR = (!STR || !*STR) ? "" : STR;\
+ ITERLVALPTR;\
+ ITERLVALPTR = foreach_strv_advance(ITERLVALPTR)\
+)
/** A process ID */
typedef unsigned long dbus_pid_t;
/** A group ID */
typedef unsigned long dbus_gid_t;
-struct kcreds {
- uid_t uid;
- gid_t gid;
- char* label;
- char** names;
-};
-
struct kconn {
int fd;
uint64_t id;
char *pool;
-};
+} g_conn[2];
+
struct udesc {
- unsigned int bus_type;
char user[256];
dbus_uid_t uid;
char group[256];
dbus_gid_t gid;
char label[256];
- struct kconn* conn;
-};
-
+} g_udesc;
static int kdbus_open_bus(const char *path)
{
return open(path, O_RDWR|O_NOCTTY|O_LARGEFILE|O_CLOEXEC);
}
-static int kdbus_hello(struct kconn *kc, uint64_t hello_flags, uint64_t attach_flags_send, uint64_t attach_flags_recv)
+static int kdbus_hello(bool bus_type, uint64_t hello_flags, uint64_t attach_flags_send, uint64_t attach_flags_recv)
{
- struct kdbus_cmd_hello kcmd_hello;
- int r;
+ struct kdbus_cmd_hello cmd;
+ int fd = g_conn[bus_type].fd;
- memset(&kcmd_hello, 0, sizeof(kcmd_hello));
- kcmd_hello.flags = hello_flags;
- kcmd_hello.attach_flags_send = attach_flags_send;
- kcmd_hello.attach_flags_recv = attach_flags_recv;
- kcmd_hello.size = sizeof(kcmd_hello);
- kcmd_hello.pool_size = KDBUS_POOL_SIZE;
+ cmd.size = sizeof(cmd);
+ cmd.flags = hello_flags;
+ cmd.attach_flags_send = attach_flags_send;
+ cmd.attach_flags_recv = attach_flags_recv;
+ cmd.pool_size = KDBUS_POOL_SIZE;
- r = ioctl(kc->fd, KDBUS_CMD_HELLO, &kcmd_hello);
- if (r < 0)
+ if (ioctl(fd, KDBUS_CMD_HELLO, &cmd) < 0)
return -errno;
- kc->id = (uint64_t)kcmd_hello.id;
- kc->pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, kc->fd, 0);
- if (kc->pool == MAP_FAILED)
+ g_conn[bus_type].id = cmd.id;
+ if (MAP_FAILED == (g_conn[bus_type].pool = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0)))
return -errno;
return 0;
}
-static int kdbus_is_unique_id(const char* name)
+static bool kdbus_is_unique_id(const char* name)
{
- return (strlen(name)>3 && name[0]==':' && isdigit(name[1]) && name[2]=='.');
+ return ':' == name[0];
}
-static int kdbus_get_creds_from_name(struct kconn* kc, struct kcreds* kcr, const char* name)
+static uint64_t kdbus_unique_id(char const *name)
{
- unsigned long long int unique_id;
- struct kdbus_cmd_info* cmd;
- struct kdbus_info* conn_info;
- struct kdbus_item *item;
- char** tmp_names;
- int j, r, l, counter;
- unsigned int size;
-
- counter = 0;
- kcr->names = calloc(counter+1, sizeof(char *));
-
- kcr->uid = UID_INVALID;
- kcr->gid = GID_INVALID;
- kcr->label = NULL;
-
- if (kdbus_is_unique_id(name)) {
- l = sizeof(unique_id);
- unique_id = strtoull(name+3, NULL, 10);
- size = sizeof(struct kdbus_cmd_info);
- cmd = aligned_alloc(8, size);
- memset(cmd, 0, sizeof(struct kdbus_cmd_info));
- cmd->id = unique_id;
- cmd->size = size;
- cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_SECLABEL | KDBUS_ATTACH_NAMES;
- } else {
- l = strlen(name) + 1;
- size = offsetof(struct kdbus_cmd_info, items) + ALIGN8((l) + offsetof(struct kdbus_item, data));
- cmd = aligned_alloc(8, size);
- memset(cmd, 0, sizeof(struct kdbus_cmd_info));
- cmd->items[0].size = l + offsetof(struct kdbus_item, data);
- cmd->items[0].type = KDBUS_ITEM_NAME;
- memcpy(cmd->items[0].str, name, l);
- cmd->size = size;
- cmd->attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_SECLABEL | KDBUS_ATTACH_NAMES;
- }
-
- r = ioctl(kc->fd, KDBUS_CMD_CONN_INFO, cmd);
- if (r < 0)
- return -errno;
-
- conn_info = (struct kdbus_info *) ((uint8_t *) kc->pool + cmd->offset);
-
- for(item = conn_info->items;
- ((uint8_t *)(item) < (uint8_t *)(conn_info) + (conn_info)->size) &&
- ((uint8_t *) item >= (uint8_t *) conn_info);
- item = ((typeof(item))(((uint8_t *)item) + ALIGN8((item)->size))) )
- {
- switch (item->type)
- {
- case KDBUS_ITEM_CREDS:
- if (item->creds.euid != UID_INVALID)
- {
- kcr->uid = (uid_t) item->creds.euid;
- }
- if (item->creds.egid != GID_INVALID)
- {
- kcr->gid = (gid_t) item->creds.egid;
- }
- break;
- case KDBUS_ITEM_SECLABEL:
- kcr->label = strdup(item->str);
- break;
- case KDBUS_ITEM_OWNED_NAME:
- counter++;
- tmp_names = calloc(counter+1, sizeof(char*));
- for (j = 0;kcr->names[j]; j++)
- {
- tmp_names[j] = kcr->names[j];
- }
- tmp_names[j] = strdup(item->name.name);
- free(kcr->names);
- kcr->names = tmp_names;
- break;
- }
- }
-
- return 0;
-}
-
-static void kcreds_free(struct kcreds* kcr)
-{
- int i = 0;
- if (kcr == NULL)
- return;
-
- free(kcr->label);
- for (i=0; kcr->names[i];i++)
- free(kcr->names[i]);
- free(kcr->names[i]);
- free(kcr->names);
- free(kcr);
+ uint64_t res;
+ unsigned i = 2;
+ int c;
+ while (!(c = name[++i] - '0'));
+ res = c;
+ while ((c = (int)(name[++i]) - '0') > 0)
+ res = res*10 + c;
+ return res;
}
-static int dbuspolicy_init_udesc(struct kconn* kc, unsigned int bus_type, struct udesc* p_udesc)
+static bool dbuspolicy_init_once(void)
{
struct passwd pwent;
struct passwd *pwd;
close(attr_fd);
- if (r < 0 || r >= (long int)sizeof(p_udesc->label)) /* read */
- return -1;
-
- snprintf(p_udesc->label, r + 1 /* additional byte for \0 */, "%s", buf);
+ if (r < 0 || r >= (long int)sizeof(g_udesc.label)) /* read */
+ return true;
- p_udesc->uid = getuid();
- p_udesc->gid = getgid();
+ snprintf(g_udesc.label, r + 1 /* additional byte for \0 */, "%s", buf);
+ if (getpwuid_r(g_udesc.uid, &pwent, buf, sizeof(buf), &pwd))
+ return true;
- if (getpwuid_r(p_udesc->uid, &pwent, buf, sizeof(buf), &pwd))
- return -1;
-
- if (getgrgid_r(p_udesc->gid, &grent, buf, sizeof(buf), &gg))
- return -1;
+ if (getgrgid_r(g_udesc.gid, &grent, buf, sizeof(buf), &gg))
+ return true;
if (!pwd || !gg)
return -1;
- snprintf(p_udesc->user, sizeof(p_udesc->user), "%s", pwd->pw_name);
- snprintf(p_udesc->group, sizeof(p_udesc->group), "%s", gg->gr_name);
+ snprintf(g_udesc.user, sizeof(g_udesc.user), "%s", pwd->pw_name);
+ snprintf(g_udesc.group, sizeof(g_udesc.group), "%s", gg->gr_name);
- p_udesc->bus_type = bus_type;
- p_udesc->conn = kc;
+ g_udesc.uid = getuid();
+ g_udesc.gid = getgid();
- return 0;
+ __internal_init_once();
+
+ return false;
}
static int bus_path_resolve(const char *bus_path, char *resolved_path, unsigned resolved_path_size, unsigned int *bus_type)
return 0;
}
+static bool init_once_done = false;
+
DBUSPOLICY1_EXPORT void* dbuspolicy1_init(const char *bus_path)
{
- uint64_t hello_flags = 0;
- uint64_t attach_flags_send = _KDBUS_ATTACH_ANY;
- uint64_t attach_flags_recv = _KDBUS_ATTACH_ALL;
- struct kconn* kc = NULL;
- struct udesc* p_udesc = NULL;
- unsigned int bus_type = -1;
- char resolved_path[PATH_MAX] = { 0 };
-
- if (bus_path_resolve(bus_path, resolved_path, sizeof(resolved_path), &bus_type) < 0)
- goto err;
-
- kc = (struct kconn*) calloc(1, sizeof(struct kconn));
- if (!kc)
- goto err;
-
- if ((kc->fd = kdbus_open_bus(resolved_path)) < 0)
- goto err;
-
- if (kdbus_hello(kc, hello_flags, attach_flags_send, attach_flags_recv) < 0)
- goto err;
-
- if (__internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY) < 0
- && __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY) < 0)
- goto err;
-
- p_udesc = (struct udesc*)malloc(sizeof(struct udesc));
- if (!p_udesc)
- goto err;
-
- if (dbuspolicy_init_udesc(kc, bus_type, p_udesc) < 0)
- goto err;
-
- return p_udesc;
-
+ unsigned int bus_type = -1;
+ char resolved_path[PATH_MAX] = { 0 };
+ int rp, rs;
+ bool rb;
+
+ _Static_assert(SYSTEM_BUS == 0, "SYSTEM_BUS not 0");
+ _Static_assert(SESSION_BUS == 1, "SESSION_BUS not 0");
+
+ if (bus_path_resolve(bus_path, resolved_path, sizeof(resolved_path), &bus_type) < 0)
+ return NULL;
+
+ if (bus_type)
+ bus_type = SESSION_BUS;
+
+ rb = false;
+ pthread_mutex_lock(&g_mutex);
+ if (!init_once_done) {
+ init_once_done = true;
+ rb = dbuspolicy_init_once();
+ }
+ pthread_mutex_unlock(&g_mutex);
+ if (rb)
+ goto err_close;
+
+ if ((g_conn[bus_type].fd = kdbus_open_bus(resolved_path)) < 0)
+ goto err;
+
+ if (kdbus_hello(bus_type, 0, _KDBUS_ATTACH_ALL, 0) < 0)
+ goto err_close;
+
+ rp = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_PRIMARY : SESSION_BUS_CONF_FILE_PRIMARY);
+ rs = __internal_init(bus_type, (bus_type == SYSTEM_BUS) ? SYSTEM_BUS_CONF_FILE_SECONDARY : SESSION_BUS_CONF_FILE_SECONDARY);
+ __internal_init_flush_logs();
+ if ((rp & rs) < 0) /* when both negative */
+ goto err_close;
+
+ return &g_conn[bus_type];
+
+err_close:
+ close(g_conn[bus_type].fd);
err:
- if (kc && kc->fd != -1)
- close(kc->fd);
- free(kc);
- free(p_udesc);
-
- return NULL;
+ return NULL;
}
DBUSPOLICY1_EXPORT void dbuspolicy1_free(void* configuration)
{
- struct udesc* p_udesc = (struct udesc*)configuration;
- if(p_udesc) {
- close(p_udesc->conn->fd);
- free(p_udesc->conn);
- free(p_udesc);
- p_udesc = NULL;
- }
+ if (configuration)
+ close(((typeof(&g_conn[0]))configuration)->fd);
}
+static bool configuration_bus_type(struct kconn const *configuration) { return configuration != g_conn; }
+
/**
* dbuspolicy1_can_send
* @param: <>
int reply_serial,
int requested_reply)
{
- struct udesc* const p_udesc = (struct udesc*)configuration;
- int i, rs, rr, l, r = 0;
- struct kcreds* p_creds = NULL;
- char gid[25], uid[25];
- char* name = NULL;
- char empty_names = 1;
-
- rs = 0;
- rr = 1;
-
- if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL || (destination != NULL && *destination != '\0') ) {
- p_creds = calloc(1, sizeof(struct kcreds));
- r = kdbus_get_creds_from_name(p_udesc->conn, p_creds, destination);
- if(r < 0) {
- kcreds_free(p_creds);
- return 0;
- }
-
- snprintf(uid, 24, "%lu", (unsigned long int)p_creds->uid);
- snprintf(gid, 24, "%lu", (unsigned long int)p_creds->gid);
- if (!p_creds->names[0])
- empty_names = 0;
-
- for (i=0;p_creds->names[i];i++)
- {
- rs = __internal_can_send(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, p_creds->names[i], path, interface, member, message_type);
- if (rs > 0)
- break;
- }
- }
+ char const *label = NULL;
+ int r;
+ uid_t uid_n = UID_INVALID;
+ gid_t gid_n = GID_INVALID;
+ bool free_offset = false;
+ bool empty_names = true;
+ bool bus_type = configuration_bus_type(configuration);
+ union {
+ struct kdbus_cmd_info cmd_info;
+ struct kdbus_cmd_free cmd_free;
+ uint8_t _buffer_[sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(MAX_DBUS_NAME_LEN+1)];
+ } cmd;
+
+ __internal_enter();
+
+ if (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type || (destination && *destination)) {
+ struct kdbus_info *conn_info;
+ struct kdbus_item *item;
+ uintptr_t items_end;
+
+ cmd.cmd_info.flags = 0;
+ cmd.cmd_info.attach_flags = KDBUS_ATTACH_CREDS | KDBUS_ATTACH_NAMES | (DBUSPOLICY_MESSAGE_TYPE_SIGNAL != message_type ? KDBUS_ATTACH_SECLABEL : 0);
+
+ if (kdbus_is_unique_id(destination)) {
+ cmd.cmd_info.size = sizeof(cmd.cmd_info);
+ cmd.cmd_info.id = kdbus_unique_id(destination);
+ } else {
+ int l = strlen(destination);
+ cmd.cmd_info.size = sizeof(struct kdbus_cmd_info) + offsetof(struct kdbus_item, data) + ALIGN8(l+1);
+ cmd.cmd_info.id = 0;
+ cmd.cmd_info.items->size = offsetof(struct kdbus_item, data) + l+1;
+ cmd.cmd_info.items->type = KDBUS_ITEM_NAME;
+ *(uint64_t*)ALIGNDN8((uintptr_t)cmd.cmd_info.items->str + l) = 0; /* trailing zero + padding */
+ memcpy(cmd.cmd_info.items->str, destination, l);
+ }
+
+ r = ioctl(g_conn[bus_type].fd, KDBUS_CMD_CONN_INFO, &cmd.cmd_info);
+ if (r < 0) {
+ r = -errno;
+ goto end;
+ }
+
+ cmd.cmd_free.size = sizeof(cmd.cmd_free);
+ /* flags already 0 */
+ _Static_assert(sizeof(cmd.cmd_info.flags) == sizeof(cmd.cmd_free.flags), "cmd_info/cmd_free: flag sizeof differs");
+ _Static_assert(offsetof(typeof(cmd.cmd_info), flags) == offsetof(typeof(cmd.cmd_free), flags), "cmd_info/cmd_free: flag offsetof differs");
+ cmd.cmd_free.offset = cmd.cmd_info.offset;
+
+ free_offset = true;
+
+ conn_info = (struct kdbus_info *) ((uint8_t *) g_conn[bus_type].pool + cmd.cmd_info.offset);
+ items_end = (uintptr_t)conn_info + (unsigned)conn_info->size;
+
+ _Static_assert((unsigned)KDBUS_ITEM_CREDS == KDBUS_ITEM_CREDS, "KDBUS_ITEM_CREDS not preserved when cast to unsigned");
+ _Static_assert((unsigned)KDBUS_ITEM_SECLABEL == KDBUS_ITEM_SECLABEL, "KDBUS_ITEM_SECLABEL not preserved when cast to unsigned");
+ _Static_assert((unsigned)KDBUS_ITEM_OWNED_NAME == KDBUS_ITEM_OWNED_NAME, "KDBUS_ITEM_OWNED_NAME not preserved when cast to unsigned");
+
+ for (item = conn_info->items; (uintptr_t)item < items_end; item = (typeof(item))ALIGN8((uintptr_t)item + (unsigned)item->size))
+ switch ((unsigned)item->type)
+ {
+ case KDBUS_ITEM_CREDS:
+ uid_n = item->creds.euid;
+ gid_n = item->creds.egid;
+ break;
+ case KDBUS_ITEM_SECLABEL:
+ label = item->str;
+ break;
+ case KDBUS_ITEM_OWNED_NAME:
+ empty_names = false;
+ if (r <= 0)
+ r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, item->name.name, path, interface, member, message_type);
+ break;
+ }
+ }
if (empty_names)
- rs = __internal_can_send(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, destination, path, interface, member, message_type);
-
- if (message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
- rr = 0;
-
- if (!sender || !(*sender))
- rr = __internal_can_recv(p_udesc->bus_type, uid, gid, p_creds->label, sender, path, interface, member, message_type);
- else
- FOREACH_STRV(i, l, sender, name) {
- char* source;
- GET_NEXT_STR(i, name, source);
- rr = __internal_can_recv(p_udesc->bus_type, uid, gid, p_creds->label, source, path, interface, member, message_type);
- if (rr > 0)
- break;
- }
+ r = __internal_can_send(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, destination, path, interface, member, message_type);
+
+ if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
+ char gid[25], uid[25];
+ char const *ptr;
+ snprintf(uid, sizeof(uid), "%lu", (unsigned long)uid_n);
+ snprintf(gid, sizeof(gid), "%lu", (unsigned long)gid_n);
+
+ FOREACH_STRV_DEFAULT(ptr, sender)
+ if (0 < (r = __internal_can_recv(bus_type, uid, gid, label, ptr, path, interface, member, message_type)))
+ break;
}
- free(name);
- kcreds_free(p_creds);
+ if (free_offset)
+ ioctl(g_conn[bus_type].fd, KDBUS_CMD_FREE, &cmd.cmd_free);
- if(rs > 0 && rr > 0) { r = 1; }
- if(rs < 0 || rr < 0) { r = -1; }
+end:
+ __internal_exit();
return r;
}
+
/**
* dbuspolicy1_can_send
* @param: <>
int reply_serial,
int requested_reply)
{
- struct udesc* const p_udesc = (struct udesc*)configuration;
- int i, rs, rr, l, r = 0;
- struct kcreds* p_creds = NULL;
+ char const *ptr;
+ int r;
char gid[25], uid[25];
- char* name = NULL;
-
- rs = 0;
- rr = 1;
-
- snprintf(uid, 24, "%lu", (unsigned long int)sender_uid);
- snprintf(gid, 24, "%lu", (unsigned long int)sender_gid);
-
- if (!destination || !(*destination))
- rs = __internal_can_send(p_udesc->bus_type, uid, gid, sender_label, destination, path, interface, member, message_type);
- else
- FOREACH_STRV(i, l, destination, name) {
- char* dest;
- GET_NEXT_STR(i, name, dest);
-
- rs = __internal_can_send(p_udesc->bus_type, uid, gid, sender_label, dest, path, interface, member, message_type);
- if (rs > 0)
- break;
- }
- free(name);
- name = NULL;
-
- if(message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL) {
- rr = 0;
-
- if (!sender || !(*sender))
- rr = __internal_can_recv(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, sender, path, interface, member, message_type);
- else
- FOREACH_STRV(i, l, sender, name) {
- char* source;
- GET_NEXT_STR(i, name, source);
- rr = __internal_can_recv(p_udesc->bus_type, p_udesc->user, p_udesc->group, p_udesc->label, source, path, interface, member, message_type);
- if(rr > 0)
- break;
- }
- free(name);
- }
- kcreds_free(p_creds);
+ bool bus_type = configuration_bus_type(configuration);
+
+ snprintf(uid, sizeof(uid), "%lu", (unsigned long)sender_uid);
+ snprintf(gid, sizeof(gid), "%lu", (unsigned long)sender_gid);
+
+ __internal_enter();
- if(rs > 0 && rr > 0) { r = 1; }
- if(rs < 0 || rr < 0) { r = -1; }
+ FOREACH_STRV_DEFAULT(ptr, destination)
+ if (0 < (r = __internal_can_send(bus_type, uid, gid, sender_label, ptr, path, interface, member, message_type)))
+ break;
+
+ if (r > 0 && message_type != DBUSPOLICY_MESSAGE_TYPE_SIGNAL)
+ FOREACH_STRV_DEFAULT(ptr, sender)
+ if (0 < (r = __internal_can_recv(bus_type, g_udesc.user, g_udesc.group, g_udesc.label, ptr, path, interface, member, message_type)))
+ break;
+
+ __internal_exit();
return r;
}
-
/**
* dbuspolicy1_can_send
* @param: <>
**/
DBUSPOLICY1_EXPORT int dbuspolicy1_can_own(void* configuration, const char* const service)
{
- struct udesc* const p_udesc = (struct udesc*)configuration;
- return __internal_can_own(p_udesc->bus_type, p_udesc->user, p_udesc->group, service);
+ int r;
+ bool bus_type = configuration_bus_type(configuration);
+ __internal_enter();
+ r = __internal_can_own(bus_type, g_udesc.user, g_udesc.group, service);
+ __internal_exit();
+ return r;
}