[mapplauncherd] Check sailjaild for sandboxing of apps. JB#54498 OMP#JOLLA-178

Check before executing if the arguments don't contain sailjaild and the
if the app should be launched in a sandbox. In that case prepend the
arguments with sailjail.

This is not sufficient alone as the apps are launched via silica-qt5
booster which can't execute sailjail so this must be also taken into
account already before arguments reach booster.

Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
pull/1/head
Tomi Leppänen 4 years ago
parent 3f37dedbbc
commit 479435fb1e

@ -26,6 +26,7 @@
#define SAILJAIL_KEY_ORGANIZATION_NAME "OrganizationName"
#define SAILJAIL_KEY_APPLICATION_NAME "ApplicationName"
#define SAILJAIL_KEY_PERMISSIONS "Permissions"
#define SAILJAIL_KEY_MODE "Mode"
#define NEMO_KEY_APPLICATION_TYPE "X-Nemo-Application-Type"
#define NEMO_KEY_SINGLE_INSTANCE "X-Nemo-Single-Instance"
#define MAEMO_KEY_FIXED_ARGS "X-Maemo-Fixed-Args"
@ -49,6 +50,10 @@
#define PERMISSIONMGR_SIGNAL_APP_CHANGED "ApplicationChanged"
#define PERMISSIONMGR_SIGNAL_APP_REMOVED "ApplicationRemoved"
/* Sailjaild errors */
#define CODE_INVALID_ARGS "org.freedesktop.DBus.Error.InvalidArgs"
#define ERROR_INVALID_APPNAME "Invalid application name: "
static DBusConnection *
sailjail_connect_bus(void)
{
@ -121,7 +126,7 @@ iter_at(DBusMessageIter *iter, int type)
static GHashTable *
sailjail_application_info(DBusConnection *con, const char *desktop)
{
GHashTable *info = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
GHashTable *info = NULL;
DBusError err = DBUS_ERROR_INIT;
DBusMessage *req = NULL;
DBusMessage *rsp = NULL;
@ -140,7 +145,10 @@ sailjail_application_info(DBusConnection *con, const char *desktop)
}
if (!(rsp = dbus_connection_send_with_reply_and_block(con, req, DBUS_TIMEOUT_INFINITE, &err))) {
error("method call failed: %s: %s", err.name, err.message);
if (strcmp(err.name, CODE_INVALID_ARGS) ||
strncmp(err.message, ERROR_INVALID_APPNAME, strlen(ERROR_INVALID_APPNAME))) {
error("method call failed: %s: %s", err.name, err.message);
}
goto EXIT;
}
@ -160,6 +168,8 @@ sailjail_application_info(DBusConnection *con, const char *desktop)
goto EXIT;
}
info = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify)g_variant_unref);
DBusMessageIter ArrayIter;
dbus_message_iter_recurse(&bodyIter, &ArrayIter);
while (!iter_at(&ArrayIter, DBUS_TYPE_INVALID)) {
@ -557,3 +567,29 @@ EXIT:
return allowed;
}
bool sailjail_sandbox(const char *desktop)
{
bool sandboxed = false;
DBusConnection *con = NULL;
GHashTable *info = NULL;
const char *mode;
if (!(con = sailjail_connect_bus()))
goto EXIT;
if (!(info = sailjail_application_info(con, desktop)))
goto EXIT;
if ((mode = appinfo_string(info, SAILJAIL_KEY_MODE)) && g_strcmp0(mode, "None")) {
// Mode is either "Normal" or "Compatibility"
sandboxed = true;
}
EXIT:
if (info)
g_hash_table_destroy(info);
sailjail_disconnect_bus(con);
return sandboxed;
}

@ -6,8 +6,12 @@
G_BEGIN_DECLS
#define SAILJAIL_PATH "/usr/bin/sailjail"
bool sailjail_verify_launch(const char *desktop, const char **argv);
bool sailjail_sandbox(const char *desktop);
G_END_DECLS
#endif // SAILJAIL_H_

@ -19,6 +19,7 @@
#include "appdata.h"
#include "protocol.h"
#include "sailjail.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
@ -100,6 +101,16 @@ void AppData::setArgv(const char ** newArgv)
}
}
void AppData::prependArgv(const char * arg)
{
char **oldArgv = m_argv;
m_argv = (char **)calloc(++m_argc + 1, sizeof *m_argv);
m_argv[0] = strdup(arg);
for (int i = 1; i < m_argc + 1; ++i)
m_argv[i] = oldArgv[i-1];
free(oldArgv);
}
const char ** AppData::argv() const
{
return (const char **)m_argv;
@ -237,6 +248,16 @@ void AppData::checkPrivileges()
And then, any file in
/usr/share/mapplauncherd/privileges.d/
*/
/* Sailjail does not use this system to gain privileged group.
* It is skipped to avoid unintended consequenses when launching
* other apps via sailjail.
*/
if (m_fileName == SAILJAIL_PATH) {
m_privileges.clear();
return;
}
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);

@ -72,6 +72,9 @@ public:
//! Set address of the argument vector
void setArgv(const char ** argv);
//! Prepend to argv
void prependArgv(const char *arg);
//! Return address of the argument vector
const char ** argv() const;

@ -57,6 +57,11 @@
#include "sailjail.h"
static std::string basename(const std::string &str)
{
return str.substr(str.find_last_of("/") + 1);
}
Booster::Booster() :
m_appData(new AppData),
m_connection(NULL),
@ -287,6 +292,12 @@ int Booster::run(SocketManager * socketManager)
if (boostedApplication() != "default") {
if (!sailjail_verify_launch(boostedApplication().c_str(), m_appData->argv()))
throw std::runtime_error("Booster: Binary doesn't have launch permissions\n");
} else if (m_appData->fileName() != SAILJAIL_PATH &&
sailjail_sandbox(basename(m_appData->fileName()).c_str())) {
Logger::logDebug("Sandboxing '%s'", m_appData->fileName());
// Prepend sailjail to arguments
m_appData->prependArgv(SAILJAIL_PATH);
m_appData->setFileName(SAILJAIL_PATH);
}
return launchProcess();
@ -701,7 +712,7 @@ void Booster::resetOomAdj()
std::string Booster::getFinalName(const std::string &name)
{
if (name == "/usr/bin/sailjail") {
if (name == SAILJAIL_PATH) {
// This doesn't implement sailjail's parsing logic but instead
// has some assumptions about the arguments:
// - If there is --, then the application is

Loading…
Cancel
Save