From a8dea6a958abf4d9a8649a817026b267cd16ef7e Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Sat, 4 Apr 2020 17:55:53 +0200 Subject: [PATCH] [booster] Expose privilege values for use. JB#49488 --- src/launcherlib/appdata.cpp | 81 +++++++++++++++++++++++++++++++++++++ src/launcherlib/appdata.h | 9 +++++ src/launcherlib/booster.cpp | 79 +----------------------------------- src/launcherlib/booster.h | 2 + 4 files changed, 93 insertions(+), 78 deletions(-) diff --git a/src/launcherlib/appdata.cpp b/src/launcherlib/appdata.cpp index 53b399e..eeb6e13 100644 --- a/src/launcherlib/appdata.cpp +++ b/src/launcherlib/appdata.cpp @@ -20,7 +20,10 @@ #include "appdata.h" #include "protocol.h" #include +#include #include +#include +#include AppData::AppData() : m_options(0), @@ -99,6 +102,7 @@ const string & AppData::appName() const void AppData::setFileName(const string & newFileName) { m_fileName = newFileName; + checkPrivileges(); } const string & AppData::fileName() const @@ -162,6 +166,83 @@ gid_t AppData::groupId() const return m_gid; } +string AppData::getPrivileges(const char *path) +{ + /* + Returns string of the declared privileges for this app. + The privileges file has the following format: + /full/path/to/app, + where the permissions_list is a string of characters + defining different categories of permissions + eg: p = people/contacts data + example: + /usr/bin/vcardconverter,p + Currently, permission means both read+write permission. + Comment lines start with # and are ignored. + */ + + std::ifstream infile(path); + if (infile) { + std::string line; + while (std::getline(infile, line)) { + if (line.find('#') == 0) { + // Comment line + continue; + } + + size_t pos = line.find(','); + if (pos != std::string::npos) { + std::string filename = line.substr(0, pos); + std::string permissions = line.substr(pos+1); + + if (filename == m_fileName) { + return permissions; + } + } + } + } + + return ""; +} + +void AppData::checkPrivileges() +{ + /* + This function checks the standard paths to find privileges definition file + and sets the m_privileges string. + First it will check + /usr/share/mapplauncherd/privileges + And then, any file in + /usr/share/mapplauncherd/privileges.d/ + */ + static const char *BOOSTER_APP_PRIVILEGES_LIST = "/usr/share/mapplauncherd/privileges"; + static const char *BOOSTER_APP_PRIVILEGES_DIR = "/usr/share/mapplauncherd/privileges.d"; + m_privileges = getPrivileges(BOOSTER_APP_PRIVILEGES_LIST); + + DIR *privilegesDir = opendir(BOOSTER_APP_PRIVILEGES_DIR); + if (privilegesDir) { + dirent *dir = NULL; + while ((dir = readdir(privilegesDir))) { + std::string privilegesFile (BOOSTER_APP_PRIVILEGES_DIR); + privilegesFile += "/"; + privilegesFile += dir->d_name; + m_privileges += getPrivileges(privilegesFile.c_str()); + } + closedir(privilegesDir); + } +} + +bool AppData::isPrivileged() const +{ + return m_privileges.length() > 0; +} + +string AppData::privileges() const +{ + return m_privileges; +} + + AppData::~AppData() { } diff --git a/src/launcherlib/appdata.h b/src/launcherlib/appdata.h index 3d44803..d840674 100644 --- a/src/launcherlib/appdata.h +++ b/src/launcherlib/appdata.h @@ -120,10 +120,18 @@ public: //! Get group ID of calling process gid_t groupId() const; + //! Returns true if the child process should be privileged + bool isPrivileged() const; + + //! Get privilege string for this app + string privileges() const; + private: AppData(const AppData & r); AppData & operator= (const AppData & r); + string getPrivileges(const char *path); + void checkPrivileges(); uint32_t m_options; int m_argc; @@ -136,6 +144,7 @@ private: vector m_ioDescriptors; gid_t m_gid; uid_t m_uid; + string m_privileges; }; #endif // APPDATA_H diff --git a/src/launcherlib/booster.cpp b/src/launcherlib/booster.cpp index 235f2a0..b82de92 100644 --- a/src/launcherlib/booster.cpp +++ b/src/launcherlib/booster.cpp @@ -334,79 +334,6 @@ void Booster::renameProcess(int parentArgc, char** parentArgv, } } -static bool isPrivileged(AppData *appData, const char *path) -{ - /* - Returns true if privileged, false if not privileged. - The privileges file has the following format: - /full/path/to/app, - where the permissions_list is a string of characters - defining different categories of permissions - eg: p = people/contacts data - example: - /usr/bin/vcardconverter,p - Currently, permission means both read+write permission. - Comment lines start with # and are ignored. - */ - - std::ifstream infile(path); - if (infile) { - std::string line; - while (std::getline(infile, line)) { - if (line.find('#') == 0) { - // Comment line - continue; - } - - size_t pos = line.find(','); - if (pos != std::string::npos) { - std::string filename = line.substr(0, pos); - std::string permissions = line.substr(pos+1); - - // TODO: Actually do something with "permissions" - - if (filename == appData->fileName()) { - return true; - } - } - } - } - - return false; -} - -static bool isPrivileged(AppData *appData) -{ - /* - Return true if privileged, false if not privileged. - - This function checks the standard paths to find privileges definition file. - First it will check - /usr/share/mapplauncherd/privileges - And then, any file in - /usr/share/mapplauncherd/privileges.d/ - */ - static const char *BOOSTER_APP_PRIVILEGES_LIST = "/usr/share/mapplauncherd/privileges"; - static const char *BOOSTER_APP_PRIVILEGES_DIR = "/usr/share/mapplauncherd/privileges.d"; - if (isPrivileged(appData, BOOSTER_APP_PRIVILEGES_LIST)) - return true; - - DIR *privilegesDir = opendir(BOOSTER_APP_PRIVILEGES_DIR); - if (!privilegesDir) - return false; - - bool privileged = false; - dirent *dir = NULL; - while ((dir = readdir(privilegesDir)) && !privileged) { - std::string privilegesFile (BOOSTER_APP_PRIVILEGES_DIR); - privilegesFile += "/"; - privilegesFile += dir->d_name; - privileged = isPrivileged(appData, privilegesFile.c_str()); - } - closedir(privilegesDir); - return privileged; -} - struct NotCharacter { char c; @@ -507,11 +434,7 @@ void Booster::setEnvironmentBeforeLaunch() setCgroup(m_appData->fileName()); - // Currently, we only have two levels of privileges: - // privileged and non-privileged. - // Going forward, this could be improved to support - // a larger range of privileges via ACLs. - if (!isPrivileged(m_appData)) { + if (!m_appData->isPrivileged()) { // The application is not privileged. Drop group ID // inherited from the booster executable. gid_t gid = getgid(); diff --git a/src/launcherlib/booster.h b/src/launcherlib/booster.h index feafada..347b32d 100644 --- a/src/launcherlib/booster.h +++ b/src/launcherlib/booster.h @@ -213,6 +213,8 @@ private: //! True, if being run in boot mode. bool m_bootMode; + std::string m_privileges; + #ifdef UNIT_TEST friend class Ut_Booster; #endif