refactoring: group checker functions into a class 05/203205/4
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 10 Apr 2019 14:22:21 +0000 (16:22 +0200)
committerAdrian Szyndela <adrian.s@samsung.com>
Thu, 11 Apr 2019 15:16:45 +0000 (17:16 +0200)
This introduces local Checker class that helps with initializing
and selecting NaivePolicyChecker instances.

Change-Id: Ia859e63903b4ea173fe4cae5de9cfadc1aa94d4a

src/libdbuspolicy1.cpp

index 812363e..eb8a802 100644 (file)
@@ -43,6 +43,7 @@ using ldp_xml_parser::DecisionResult;
 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,
@@ -101,20 +102,61 @@ extern "C" void __dbuspolicy1_change_creds(uid_t uid, gid_t gid, const char* lab
        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);
@@ -182,41 +224,10 @@ static std::shared_ptr<const char> bus_path_resolve(const char *bus_path, BusTyp
        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");
@@ -238,17 +249,10 @@ static kconn *init_shared_fd(BusType bus_type, int fd)
                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");
@@ -266,7 +270,7 @@ DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd)
        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 {