using ldp_xml_parser::MatchItemSend;
using ldp_xml_parser::MatchItemReceive;
using ldp_xml_parser::MatchItemOwn;
+using ldp_xml_parser::NaivePolicyChecker;
typedef enum {
SYSTEM_BUS = 0,
g_udesc.change_creds(uid, gid, label);
}
+/*
+ * This class decorates NaivePolicyChecker with initialization mechanisms.
+ * Thread-safety is ensured by C++ and static initialization in static member functions.
+ */
+class Checker {
+public:
+ Checker(NaivePolicyChecker &checker, const char *primary_file_name, const char *secondary_file_name)
+ : _checker{checker}
+ {
+ std::string primary_file_name_serialized = primary_file_name;
+ primary_file_name_serialized.append(".serialized");
+
+ auto ok = _checker.initDb(primary_file_name, primary_file_name_serialized.c_str());
+ if (!ok)
+ ok = _checker.initDb(secondary_file_name);
+
+ assert(ok && "failed database initialization");
+
+ _checker.updateGroupDb(g_udesc.uid, g_udesc.gid);
+ }
+
+ NaivePolicyChecker &checker() { return _checker; }
+
+ // this checks if this process can open a bus owned by bus_owner
+ inline bool can_open_owned_by(uid_t bus_owner) {
+ return _checker.check(bus_owner, g_udesc.uid, g_udesc.gid, g_udesc.label) == DecisionResult::ALLOW;
+ }
+
+ static Checker &system() {
+ static Checker checker{policy_checker_system(), system_bus_conf_file_primary(), SYSTEM_BUS_CONF_FILE_SECONDARY};
+ return checker;
+ }
+
+ static Checker &session() {
+ static Checker checker{policy_checker_session(), session_bus_conf_file_primary(), SESSION_BUS_CONF_FILE_SECONDARY};
+ return checker;
+ }
+
+ static inline Checker &get(BusType bus_type) {
+ if (SESSION_BUS == bus_type)
+ return session();
+ return system();
+ }
+
+private:
+ NaivePolicyChecker &_checker;
+};
+
struct kconn {
KdbusConnection conn;
ldp_xml_parser::NaivePolicyChecker *checker;
} g_conn[2];
-static std::once_flag init_once_db[2];
static std::once_flag init_once_conn[2];
-inline ldp_xml_parser::NaivePolicyChecker &policy_checker(BusType bus_type) {
- if (SESSION_BUS == bus_type)
- return policy_checker_session();
- return policy_checker_system();
-}
-
static std::shared_ptr<const char> bus_type_from_path(const char *bus_path, BusType &bus_type)
{
assert(bus_path);
return resolved_path;
}
-static const char *primary_conf_file(BusType bus_type)
-{
- if (SYSTEM_BUS == bus_type)
- return system_bus_conf_file_primary();
- return session_bus_conf_file_primary();
-}
-
-static const char *secondary_conf_file(BusType bus_type)
-{
- if (SYSTEM_BUS == bus_type)
- return SYSTEM_BUS_CONF_FILE_SECONDARY;
- return SESSION_BUS_CONF_FILE_SECONDARY;
-}
-
-static void init_common_locked(BusType bus_type)
-{
- auto primary_file_name = primary_conf_file(bus_type);
- std::string primary_file_name_serialized = primary_file_name;
- primary_file_name_serialized.append(".serialized");
-
- auto &checker = policy_checker(bus_type);
-
- auto ok = checker.initDb(primary_file_name, primary_file_name_serialized.c_str());
- if (!ok)
- ok = checker.initDb(secondary_conf_file(bus_type));
-
- assert(ok && "failed database initialization");
-
- checker.updateGroupDb(g_udesc.uid, g_udesc.gid);
-}
-
static void init_global_conn_locked(BusType bus_type, std::shared_ptr<const char> resolved_path)
{
struct kconn *kconn = &g_conn[bus_type];
- kconn->checker = &policy_checker(bus_type);
+ kconn->checker = &Checker::get(bus_type).checker();
if (kconn->conn.connect(resolved_path.get(), 0, _KDBUS_ATTACH_ALL, 0) < 0) {
assert(false && "failed kdbus_connect");
return nullptr;
}
result->conn.shared_init_fd(fd);
- result->checker = &policy_checker(bus_type);
+ result->checker = &Checker::get(bus_type).checker();
return result;
}
-static DecisionResult can_open(BusType bus_type, uid_t bus_owner) noexcept
-{
- std::call_once(init_once_db[bus_type], init_common_locked, bus_type);
-
- return policy_checker(bus_type).check(bus_owner, g_udesc.uid, g_udesc.gid, g_udesc.label);
-}
-
DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd)
{
static_assert(SYSTEM_BUS == 0, "SYSTEM_BUS not 0");
g_udesc.init();
struct kconn *result = nullptr;
- if (can_open(bus_type, bus_owner) == DecisionResult::ALLOW) {
+ if (Checker::get(bus_type).can_open_owned_by(bus_owner)) {
if (-1 == fd) {
result = get_global_conn(bus_type, resolved_path);
} else {