#include <sys/types.h>
#include <unistd.h>
-#define KDBUS_PATH_PREFIX "/sys/fs/kdbus/"
-#define KDBUS_SYSTEM_BUS_PATH KDBUS_PATH_PREFIX"0-system/bus"
-
using ldp_xml_parser::DecisionResult;
using ldp_xml_parser::MatchItemSend;
using ldp_xml_parser::MatchItemReceive;
};
-static std::shared_ptr<const char> bus_type_from_path(const char *bus_path, BusType &bus_type)
-{
- assert(bus_path);
-
- std::shared_ptr<const char> p(realpath(bus_path, nullptr), [](const char *a) { free(const_cast<char*>(a)); });
- if (!p)
- return nullptr;
-
- if (0 == strcmp(p.get(), KDBUS_SYSTEM_BUS_PATH)) {
- bus_type = SYSTEM_BUS;
- return p;
- }
-
- if (0 == strncmp(p.get(), KDBUS_PATH_PREFIX, strlen(KDBUS_PATH_PREFIX))) {
- bus_type = SESSION_BUS;
- return p;
- }
-
- return nullptr;
-}
-
-// We will never get 0 as a session bus owner (0 uses "0-system" bus),
-// so it's OK to assume that bus_owner==0 always means error.
-static uid_t bus_owner_from_path(const char *resolved_path) noexcept
-{
- boost::string_ref user_suffix("-user/bus");
- boost::string_ref ps(resolved_path);
-
- if (!ps.ends_with(user_suffix))
- return 0;
-
- ps.remove_suffix(user_suffix.length());
-
- size_t last_slash = ps.find_last_of('/');
- if (last_slash == boost::string_ref::npos || last_slash == ps.length() - 1)
- return 0;
-
- ps = ps.substr(last_slash+1);
+/*
+ * This class encapsulates functions used to analyze passed path to kdbus bus file.
+ * It recognizes system and session paths.
+ * If it recognizes path as a session bus, then it extracts owner's uid.
+ */
+class BusPathResolver {
+ std::shared_ptr<const char> resolved_path;
+ BusType type{SESSION_BUS};
+ uid_t owner{0};
+ bool ok{false};
+
+ // We will never get 0 as a session bus owner (0 uses "0-system" bus),
+ // so it's OK to assume that bus_owner==0 always means error.
+ bool extract_bus_owner() noexcept
+ {
+ boost::string_ref user_suffix("-user/bus");
+ boost::string_ref ps(resolved_path.get());
- errno = 0;
- uid_t bus_owner = strtol(ps.data(), NULL, 10);
- if (errno)
- return 0;
+ if (!ps.ends_with(user_suffix))
+ return false;
- return bus_owner;
-}
+ ps.remove_suffix(user_suffix.length());
-static std::shared_ptr<const char> bus_path_resolve(const char *bus_path, BusType &bus_type, uid_t &bus_owner)
-{
- assert(bus_path);
+ size_t last_slash = ps.find_last_of('/');
+ if (last_slash == boost::string_ref::npos || last_slash == ps.length() - 1)
+ return false;
- auto resolved_path = bus_type_from_path(bus_path, bus_type);
+ ps = ps.substr(last_slash+1);
- if (nullptr == resolved_path)
- return nullptr;
+ errno = 0;
+ uid_t bus_owner = strtol(ps.data(), NULL, 10);
+ if (errno)
+ return false;
- if (bus_type == SESSION_BUS) {
- auto result = bus_owner_from_path(resolved_path.get());
- if (result > 0)
- bus_owner = result;
- else
- return nullptr;
+ owner = bus_owner;
+ type = SESSION_BUS;
+ return true;
}
+#define STR_SIZE(x) (x), sizeof(x)-1
+ static constexpr boost::string_ref KDBUS_PATH_PREFIX{STR_SIZE("/sys/fs/kdbus/")};
+ static constexpr boost::string_ref KDBUS_SYSTEM_BUS_PATH{STR_SIZE("/sys/fs/kdbus/0-system/bus")};
+#undef STR_SIZE
- return resolved_path;
-}
+public:
+ BusPathResolver(const char *bus_path)
+ : resolved_path(realpath(bus_path, nullptr), [](const char *a) { free(const_cast<char*>(a)); })
+ {
+ if (!resolved_path)
+ return;
+
+ // recognize bus type
+ if (KDBUS_SYSTEM_BUS_PATH == resolved_path.get()) {
+ type = SYSTEM_BUS;
+ ok = true;
+ } else if (boost::string_ref(resolved_path.get()).starts_with(KDBUS_PATH_PREFIX)) {
+ ok = extract_bus_owner();
+ }
+ }
+ operator bool() { return ok; }
+ const char *path() { return resolved_path.get(); }
+ BusType bus_type() { return type; }
+ uid_t bus_owner() { return owner; }
+};
DBUSPOLICY1_EXPORT void* dbuspolicy1_init_shared(const char *bus_path, int fd)
{
- BusType bus_type = SESSION_BUS;
- uid_t bus_owner = 0;
+ assert(bus_path);
- auto resolved_path = bus_path_resolve(bus_path, bus_type, bus_owner);
- if (nullptr == resolved_path) {
+ BusPathResolver path_resolver(bus_path);
+ if (!path_resolver) {
LOGE("Error resolving bus path: %s", bus_path);
return nullptr;
}
g_udesc.init();
+ auto bus_type = path_resolver.bus_type();
+
kconn *result = nullptr;
- if (Checker::get(bus_type).can_open_owned_by(bus_owner)) {
+ if (Checker::get(bus_type).can_open_owned_by(path_resolver.bus_owner())) {
if (-1 == fd) {
- result = &kconn::get(bus_type, resolved_path.get());
+ result = &kconn::get(bus_type, path_resolver.path());
} else {
result = kconn::get_shared(bus_type, fd);
}