Remove sailjail.c

pull/1/head
reionwong 4 years ago
parent 6040742b60
commit bb3384e7fb

@ -1,624 +0,0 @@
#include "sailjail.h"
#include "report.h"
#include <stdio.h>
#include <limits.h>
#include <dbus/dbus.h>
/* Standard desktop properties */
#define DESKTOP_SECTION "Desktop Entry"
#define DESKTOP_KEY_NAME "Name"
#define DESKTOP_KEY_TYPE "Type"
#define DESKTOP_KEY_ICON "Icon"
#define DESKTOP_KEY_EXEC "Exec"
#define DESKTOP_KEY_NO_DISPLAY "NoDisplay"
/* Maemo desktop properties */
#define MAEMO_SECTION "Desktop Entry"
#define MAEMO_KEY_SERVICE "X-Maemo-Service"
#define MAEMO_KEY_OBJECT "X-Maemo-Object-Path"
#define MAEMO_KEY_METHOD "X-Maemo-Method"
/* Sailjail desktop properties */
#define SAILJAIL_SECTION_PRIMARY "X-Sailjail"
#define SAILJAIL_SECTION_SECONDARY "Sailjail"
#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"
#define OSSO_KEY_SERVICE "X-Osso-Service"
/* Sailjaild D-Bus service */
#define PERMISSIONMGR_SERVICE "org.sailfishos.sailjaild1"
#define PERMISSIONMGR_INTERFACE "org.sailfishos.sailjaild1"
#define PERMISSIONMGR_OBJECT "/org/sailfishos/sailjaild1"
#define PERMISSIONMGR_METHOD_PROMPT "PromptLaunchPermissions"
#define PERMISSIONMGR_METHOD_QUERY "QueryLaunchPermissions"
#define PERMISSIONMGR_METHOD_GET_APPLICATIONS "GetApplications"
#define PERMISSIONMGR_METHOD_GET_APPINFO "GetAppInfo"
#define PERMISSIONMGR_METHOD_GET_LICENSE "GetLicenseAgreed"
#define PERMISSIONMGR_METHOD_SET_LICENSE "SetLicenseAgreed"
#define PERMISSIONMGR_METHOD_GET_LAUNCHABLE "GetLaunchAllowed"
#define PERMISSIONMGR_METHOD_SET_LAUNCHABLE "SetLaunchAllowed"
#define PERMISSIONMGR_METHOD_GET_GRANTED "GetGrantedPermissions"
#define PERMISSIONMGR_METHOD_SET_GRANTED "SetGrantedPermissions"
#define PERMISSIONMGR_SIGNAL_APP_ADDED "ApplicationAdded"
#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: "
/* Directories */
#define BINDIR "/usr/bin"
const gchar *
path_basename(const gchar *path)
{
const gchar *base = NULL;
if( path ) {
gchar *end = strrchr(path, '/');
base = end ? end + 1 : path;
}
return base;
}
static bool
path_dirname_eq(const char *path, const char *target)
{
gchar *dir_path = g_path_get_dirname(path);
bool result = !strcmp(dir_path, target);
g_free(dir_path);
return result;
}
static DBusConnection *
sailjail_connect_bus(void)
{
DBusError err = DBUS_ERROR_INIT;
DBusConnection *con = 0;
if (!(con = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err))) {
error("system bus connect failed: %s: %s",
err.name, err.message);
} else {
warning("PRIVATE CONNECTION %p CONNECTED", con);
dbus_connection_set_exit_on_disconnect(con, false);
}
dbus_error_free(&err);
return con;
}
static void
sailjail_disconnect_bus(DBusConnection *con)
{
if (con) {
warning("PRIVATE CONNECTION %p DISCONNECTED", con);
dbus_connection_close(con);
dbus_connection_unref(con);
}
}
static GVariant *
appinfo_variant(GHashTable *info, const char *key)
{
return g_hash_table_lookup(info, key);
}
static const char *
appinfo_string(GHashTable *info, const char *key)
{
const char *value = NULL;
GVariant *variant = appinfo_variant(info, key);
if (variant) {
const GVariantType *type = g_variant_get_type(variant);
if (g_variant_type_equal(type, G_VARIANT_TYPE_STRING))
value = g_variant_get_string(variant, NULL);
}
return value;
}
static const char **
appinfo_strv(GHashTable *info, const char *key)
{
const char **value = NULL;
GVariant *variant = appinfo_variant(info, key);
if (variant) {
const GVariantType *type = g_variant_get_type(variant);
if (g_variant_type_equal(type, G_VARIANT_TYPE("as")))
value = g_variant_get_strv(variant, NULL);
}
return value;
}
static bool
iter_at(DBusMessageIter *iter, int type)
{
int have = dbus_message_iter_get_arg_type(iter);
if (have != type && type != 0)
warning("Expected: %c got: %c", type ?: '?', have ?: '?');
return have == type;
}
static GHashTable *
sailjail_application_info(DBusConnection *con, const char *desktop)
{
GHashTable *info = NULL;
DBusError err = DBUS_ERROR_INIT;
DBusMessage *req = NULL;
DBusMessage *rsp = NULL;
if (!(req = dbus_message_new_method_call(PERMISSIONMGR_SERVICE,
PERMISSIONMGR_OBJECT,
PERMISSIONMGR_INTERFACE,
PERMISSIONMGR_METHOD_GET_APPINFO))) {
error("failed to create dbus method call");
goto EXIT;
}
if (!dbus_message_append_args(req, DBUS_TYPE_STRING, &desktop, DBUS_TYPE_INVALID)) {
error("failed to add method call args");
goto EXIT;
}
if (!(rsp = dbus_connection_send_with_reply_and_block(con, req, DBUS_TIMEOUT_INFINITE, &err))) {
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;
}
if (dbus_set_error_from_message(&err, rsp)) {
error("error reply received: %s: %s", err.name, err.message);
goto EXIT;
}
DBusMessageIter bodyIter;
if (!dbus_message_iter_init(rsp, &bodyIter)) {
error("empty reply received");
goto EXIT;
}
if (!iter_at(&bodyIter, DBUS_TYPE_ARRAY)) {
error("reply is not an array");
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)) {
if (!iter_at(&ArrayIter, DBUS_TYPE_DICT_ENTRY)) {
error("reply is not an array of dict entries");
goto EXIT;
}
DBusMessageIter dictIter;
dbus_message_iter_recurse(&ArrayIter, &dictIter);
dbus_message_iter_next(&ArrayIter);
if (!iter_at(&dictIter, DBUS_TYPE_STRING)) {
error("key is not a string");
goto EXIT;
}
const char *key = NULL;
dbus_message_iter_get_basic(&dictIter, &key);
dbus_message_iter_next(&dictIter);
if (!iter_at(&dictIter, DBUS_TYPE_VARIANT)) {
error("values is not a variant");
goto EXIT;
}
DBusMessageIter variantIter;
dbus_message_iter_recurse(&dictIter, &variantIter);
dbus_message_iter_next(&dictIter);
DBusBasicValue value;
switch (dbus_message_iter_get_arg_type(&variantIter)) {
case DBUS_TYPE_INT32:
dbus_message_iter_get_basic(&variantIter, &value);
debug("%s = int32:%d", key, value.i32);
g_hash_table_insert(info, g_strdup(key), g_variant_new_int32(value.i32));
break;
case DBUS_TYPE_UINT32:
dbus_message_iter_get_basic(&variantIter, &value);
debug("%s = uint32:%d", key, value.u32);
g_hash_table_insert(info, g_strdup(key), g_variant_new_uint32(value.u32));
break;
case DBUS_TYPE_BOOLEAN:
dbus_message_iter_get_basic(&variantIter, &value);
debug("%s = bool:%d", key, value.bool_val);
g_hash_table_insert(info, g_strdup(key), g_variant_new_boolean(value.bool_val));
break;
case DBUS_TYPE_STRING:
dbus_message_iter_get_basic(&variantIter, &value);
debug("%s = string:'%s'", key, value.str);
g_hash_table_insert(info, g_strdup(key), g_variant_new_string(value.str));
break;
case DBUS_TYPE_ARRAY:
if (dbus_message_iter_get_element_type(&variantIter) != DBUS_TYPE_STRING) {
error("only arrays of strings are supported");
} else {
int n = dbus_message_iter_get_element_count(&variantIter);
DBusMessageIter valueIter;
dbus_message_iter_recurse(&variantIter, &valueIter);
char **v = g_malloc0_n(n + 1, sizeof *v);
int i = 0;
while (i < n) {
if (!iter_at(&valueIter, DBUS_TYPE_STRING))
break;
dbus_message_iter_get_basic(&valueIter, &value);
debug("%s[%d] = string:'%s'", key, i, value.str);
dbus_message_iter_next(&valueIter);
v[i++] = g_strdup(value.str);
}
v[i] = NULL;
g_hash_table_insert(info, g_strdup(key), g_variant_new_strv((const gchar *const *)v, i));
g_strfreev(v);
}
break;
default:
warning("reply contains unhandled variant types");
break;
}
}
EXIT:
if (info && g_hash_table_size(info) < 1) {
/* There should always be at least app id key. If we get
* empty hash table, either parser is not working or there
* are other kinds of problems.
*/
error("no information about application '%s'", desktop);
g_hash_table_destroy(info), info = NULL;
}
dbus_error_free(&err);
if (rsp)
dbus_message_unref(rsp);
if (req)
dbus_message_unref(req);
debug("info received = %s", info ? "true" : "false");
return info;
}
static char **
sailjail_prompt_permissions(DBusConnection *con, const char *desktop)
{
char **granted = NULL;
DBusError err = DBUS_ERROR_INIT;
DBusMessage *req = NULL;
DBusMessage *rsp = NULL;
int len = 0;
if (!(req = dbus_message_new_method_call(PERMISSIONMGR_SERVICE,
PERMISSIONMGR_OBJECT,
PERMISSIONMGR_INTERFACE,
PERMISSIONMGR_METHOD_PROMPT))) {
error("failed to create dbus method call");
goto EXIT;
}
if (!dbus_message_append_args(req,
DBUS_TYPE_STRING, &desktop,
DBUS_TYPE_INVALID)) {
error("failed to add method call args");
goto EXIT;
}
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);
goto EXIT;
}
if (dbus_set_error_from_message(&err, rsp)) {
error("error reply received: %s: %s", err.name, err.message);
goto EXIT;
}
if (!dbus_message_get_args(rsp, &err,
DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &granted, &len,
DBUS_TYPE_INVALID)) {
error("parsing reply failed: %s: %s", err.name, err.message);
dbus_free_string_array(granted), granted = NULL;
goto EXIT;
}
EXIT:
dbus_error_free(&err);
if (rsp)
dbus_message_unref(rsp);
if (req)
dbus_message_unref(req);
info("launch permitted = %s", granted ? "true" : "false");
return granted;
}
static int
sailjailclient_get_field_code(const char *arg)
{
// Non-null string starting with a '%' followed by exactly one character
return arg && arg[0] == '%' && arg[1] && !arg[2] ? arg[1] : 0;
}
static bool
sailjailclient_is_option(const char *arg)
{
// Non-null string starting with a hyphen
return arg && arg[0] == '-';
}
static bool
sailjailclient_ignore_arg(const char *arg)
{
return !g_strcmp0(arg, "-prestart");
}
static bool
sailjailclient_match_argv(const char **tpl_argv, const char **app_argv)
{
bool matching = false;
/* Match each arg in template */
for (;;) {
const char *want = *tpl_argv++;
/* Allow some slack e.g. regarding "-prestart" options */
while (*app_argv && g_strcmp0(*app_argv, want) &&
sailjailclient_ignore_arg(*app_argv)) {
warning("ignoring argument: %s", *app_argv);
++app_argv;
}
if (!want) {
/* Template args exhausted */
if (*app_argv) {
/* Excess application args */
error("argv has unwanted '%s'", *app_argv);
goto EXIT;
}
break;
}
int field_code = sailjailclient_get_field_code(want);
if (!field_code) {
/* Exact match needed */
if (g_strcmp0(*app_argv, want)) {
/* Application args has something else */
error("argv is missing '%s'", want);
goto EXIT;
}
++app_argv;
continue;
}
/* Field code explanations from "Desktop Entry Specification"
*
* https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables
*/
int code_args = 0;
switch (field_code) {
case 'f': /* A single file name (or none) */
case 'u': /* A single URL (or none) */
code_args = -1;
break;
case 'c': /* The translated name of the application */
case 'k': /* The location of the desktop file */
code_args = 1;
break;
case 'F': /* A list of files */
case 'U': /* A list of URLs */
code_args = INT_MIN;
break;
case 'i':
/* The Icon key of the desktop entry expanded as two
* arguments, first --icon and then the value of the
* Icon key. Should not expand to any arguments if
* the Icon key is empty or missing.
*/
if (!g_strcmp0(*app_argv, "--icon"))
++app_argv, code_args = 1;
break;
case 'd':
case 'D':
case 'n':
case 'N':
case 'v':
case 'm':
/* Deprecated */
error("Exec line has deprecated field code '%s'", want);
goto EXIT;
default:
/* Unknown */
error("Exec line has unknown field code '%s'", want);
goto EXIT;
}
if (code_args < 0) {
/* Variable number of args */
if (sailjailclient_get_field_code(*tpl_argv)) {
error("Can't validate '%s %s' combination", want, *tpl_argv);
goto EXIT;
}
for (; code_args < 0; ++code_args) {
if (!*app_argv || !g_strcmp0(*app_argv, *tpl_argv))
break;
if (sailjailclient_is_option(*app_argv)) {
error("option '%s' at field code '%s'", *app_argv, want);
goto EXIT;
}
++app_argv;
}
} else {
/* Specified number of args */
for (; code_args > 0; --code_args) {
if (!*app_argv) {
error("missing args for field code '%s'", want);
goto EXIT;
}
if (sailjailclient_is_option(*app_argv)) {
error("option '%s' at field code '%s'", *app_argv, want);
goto EXIT;
}
++app_argv;
}
}
}
matching = true;
EXIT:
return matching;
}
static bool
sailjailclient_validate_argv(const char *exec, const gchar **app_argv)
{
bool validated = false;
GError *err = NULL;
gchar **exec_argv = NULL;
if (!app_argv || !*app_argv) {
error("application argv not defined");
goto EXIT;
}
/* Split desktop Exec line into argv */
if (!g_shell_parse_argv(exec, NULL, &exec_argv, &err)) {
error("Exec line parse failure: %s", err->message);
goto EXIT;
}
if (!exec_argv || !*exec_argv) {
error("Exec line not defined");
goto EXIT;
}
/* Expectation: Exec line might have leading 'wrapper' executables
* such as sailjail, invoker, etc -> make an attempt to skip those
* by looking for argv[0] for command we are about to launch.
*
* App may also be defined without absolute path, in which case it
* must reside in BINDIR and it must not have any 'wrapper'
* executables. Thus check the path of app_argv[0] and compare Exec
* line to the binary name.
*/
const char **tpl_argv = (const char **)exec_argv;
if (!path_dirname_eq(app_argv[0], BINDIR) ||
g_strcmp0(*tpl_argv, path_basename(app_argv[0]))) {
/* App is not specified without path as the first argument,
* => there might be 'wrappers' and we match to full path.
*/
for( ; *tpl_argv; ++tpl_argv ) {
if( !g_strcmp0(*tpl_argv, app_argv[0]) )
break;
}
if( !*tpl_argv ) {
error("Exec line does not contain '%s'", *app_argv);
goto EXIT;
}
}
/* Argument zero has been checked already */
if (!sailjailclient_match_argv(tpl_argv + 1, app_argv + 1)) {
gchar *args = g_strjoinv(" ", (gchar **)app_argv);
error("Application args do not match Exec line template");
error("exec: %s", exec);
error("args: %s", args);
g_free(args);
goto EXIT;
}
validated = true;
EXIT:
g_strfreev(exec_argv);
g_clear_error(&err);
return validated;
}
bool
sailjail_verify_launch(const char *desktop, const char **argv)
{
bool allowed = false;
DBusConnection *con = NULL;
char **granted = NULL;
GHashTable *info = NULL;
const char **requested = NULL;
const char *exec = NULL;
if (!(con = sailjail_connect_bus()))
goto EXIT;
if (!(info = sailjail_application_info(con, desktop)))
goto EXIT;
if (!(exec = appinfo_string(info, DESKTOP_KEY_EXEC))) {
error("no Exec line defined for application '%s'", desktop);
goto EXIT;
}
if (!sailjailclient_validate_argv(exec, argv))
goto EXIT;
if (!(requested = appinfo_strv(info, SAILJAIL_KEY_PERMISSIONS))) {
error("no permissions defined for application '%s'", desktop);
goto EXIT;
}
debug("prompting permissions for application '%s'", desktop);
if (!(granted = sailjail_prompt_permissions(con, desktop)))
goto EXIT;
for (int i = 0; requested[i]; ++i) {
if (!g_strv_contains((const gchar *const *)granted, requested[i])) {
error("application '%s' has not been granted '%s' permission",
desktop, requested[i]);
goto EXIT;
}
}
allowed = true;
EXIT:
if (info)
g_hash_table_destroy(info);
g_strfreev(granted);
sailjail_disconnect_bus(con);
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;
}

@ -1,17 +0,0 @@
#ifndef SAILJAIL_H_
# define SAILJAIL_H_
# include <stdbool.h>
# include <glib.h>
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_

@ -6,7 +6,7 @@ pkg_check_modules(DBUS dbus-1 REQUIRED)
pkg_check_modules(GLIB glib-2.0 REQUIRED)
# Set sources
set(SRC invokelib.c invoker.c ${COMMON}/report.c search.c ${COMMON}/sailjail.c)
set(SRC invokelib.c invoker.c ${COMMON}/report.c search.c)
# Set include dirs
include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${DBUS_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${COMMON})

@ -48,7 +48,6 @@
#include "protocol.h"
#include "invokelib.h"
#include "search.h"
#include "sailjail.h"
#define BOOSTER_SESSION "silica-session"
#define BOOSTER_GENERIC "generic"
@ -647,38 +646,6 @@ static unsigned int get_delay(char *delay_arg, char *param_name,
return delay;
}
static void notify_app_launch(const char *desktop_file)
{
DBusConnection *connection;
DBusMessage *message;
DBusError error;
dbus_error_init (&error);
connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
if (connection) {
message = dbus_message_new_method_call("org.nemomobile.lipstick", "/LauncherModel",
"org.nemomobile.lipstick.LauncherModel", "notifyLaunching");
dbus_message_append_args(message, DBUS_TYPE_STRING, &desktop_file, DBUS_TYPE_INVALID);
dbus_connection_send(connection, message, NULL);
dbus_message_unref(message);
dbus_connection_flush(connection);
} else {
info("Failed to connect to the DBus session bus: %s", error.message);
dbus_error_free(&error);
return;
}
}
static bool ask_for_sandboxing(const char *app)
{
char *path = strdup(app);
bool ret_val = sailjail_sandbox(basename(path));
free(path);
return ret_val;
}
static int wait_for_launched_process_to_exit(int socket_fd)
{
int exit_status = EXIT_FAILURE;
@ -819,9 +786,6 @@ static int invoke_remote(int socket_fd, const InvokeArgs *args)
invoker_send_env(socket_fd);
invoker_send_end(socket_fd);
if (args->desktop_file)
notify_app_launch(args->desktop_file);
if (args->wait_term) {
exit_status = wait_for_launched_process_to_exit(socket_fd),
socket_fd = -1;
@ -1124,41 +1088,6 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
// If sailjail is already used or app specific booster is used, skip checking for sandboxing
if (!strcmp(args.prog_name, SAILJAIL_PATH) || strcmp(args.app_name, UNDEFINED_APPLICATION)) {
args.sandboxing_id = NULL;
} else if (!args.sandboxing_id) {
// When id is not defined, assume it can be derived from binary path
char *path = strdup(args.prog_name);
args.sandboxing_id = strdup(basename(path));
free(path);
}
// Application specific boosters are running in sandbox and can
// thus launch only sandboxed processes, otherwise
// If arguments don't define sailjail and sailjaild says the app must be sandboxed,
// we force sandboxing here
if (args.sandboxing_id && ask_for_sandboxing(args.sandboxing_id)) {
warning("enforcing sandboxing for '%s'", args.prog_name);
// We must use generic booster here as nothing else would work
// to run sailjail which is not compiled for launching via booster
args.app_type = BOOSTER_GENERIC;
// Prepend sailjail
char **old_argv = args.prog_argv;
args.prog_argc += 4;
args.prog_argv = (char **)calloc(args.prog_argc + 1, sizeof *args.prog_argv);
args.prog_argv[0] = SAILJAIL_PATH;
args.prog_argv[1] = "-p";
args.prog_argv[2] = args.sandboxing_id,
args.sandboxing_id = NULL;
args.prog_argv[3] = "--";
for (int i = 4; i < args.prog_argc + 1; ++i)
args.prog_argv[i] = old_argv[i-4];
// Don't free old_argv because it's probably not dynamically allocated
free(args.prog_name);
args.prog_name = strdup(SAILJAIL_PATH);
}
// Send commands to the launcher daemon
info("Invoking execution: '%s'\n", args.prog_name);
int ret_val = invoke(&args);

@ -16,8 +16,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
# Set sources
set(SRC appdata.cpp booster.cpp connection.cpp daemon.cpp logger.cpp
singleinstance.cpp socketmanager.cpp
../common/report.c
../common/sailjail.c)
../common/report.c)
set(HEADERS appdata.h booster.h connection.h daemon.h logger.h launcherlib.h
singleinstance.h socketmanager.h ${COMMON}/protocol.h)

@ -19,7 +19,6 @@
#include "appdata.h"
#include "protocol.h"
#include "sailjail.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
@ -129,7 +128,6 @@ const string & AppData::appName() const
void AppData::setFileName(const string & newFileName)
{
m_fileName = newFileName;
checkPrivileges();
}
const string & AppData::fileName() const
@ -238,43 +236,6 @@ string AppData::getPrivileges(const char *path)
return permissions;
}
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/
*/
/* 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);
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;

@ -134,7 +134,6 @@ private:
AppData(const AppData & r);
AppData & operator= (const AppData & r);
string getPrivileges(const char *path);
void checkPrivileges();
uint32_t m_options;
int m_argc;

@ -55,8 +55,6 @@
#include "coverage.h"
#include "sailjail.h"
static std::string basename(const std::string &str)
{
return str.substr(str.find_last_of("/") + 1);
@ -121,8 +119,8 @@ void Booster::initialize(int initialArgc, char ** initialArgv, int newBoosterLau
SingleInstancePluginEntry * pluginEntry = singleInstance->pluginEntry();
if (pluginEntry)
{
std::string lockedAppName = getFinalName(m_appData->appName());
if (!pluginEntry->lockFunc(lockedAppName.c_str()))
std::string lockedAppName = m_appData->appName();
if (!pluginEntry->lockFunc(m_appData->appName().c_str()))
{
// Try to activate the window of the existing instance
if (!pluginEntry->activateExistingInstanceFunc(lockedAppName.c_str()))
@ -285,21 +283,6 @@ int Booster::run(SocketManager * socketManager)
// Execute the binary
Logger::logDebug("Booster: invoking '%s' ", m_appData->fileName().c_str());
try {
if (access(m_appData->fileName().c_str(), X_OK) != 0) {
throw std::runtime_error("Booster: Binary doesn't have execute permissions\n");
}
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();
} catch (const std::runtime_error &e) {
Logger::logError("Booster: Failed to invoke: %s\n", e.what());
@ -463,7 +446,7 @@ void Booster::setEnvironmentBeforeLaunch()
if (!errno && cur_prio < m_appData->priority())
setpriority(PRIO_PROCESS, 0, m_appData->priority());
std::string fileName = getFinalName(m_appData->fileName());
std::string fileName = m_appData->fileName();
setCgroup(fileName);
if (!m_appData->isPrivileged()) {
@ -709,35 +692,3 @@ void Booster::resetOomAdj()
Logger::logError("Couldn't open '%s' for writing", PROC_OOM_ADJ_FILE);
}
}
std::string Booster::getFinalName(const std::string &name)
{
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
// the next argument after that.
// - If there is an argument that begins with /usr/bin/,
// then the application is that argument.
// The one that is found first is used as the application name.
// Otherwise it can not be deduced and the original value is used.
//
// If you want to give a value to sailjail that begins with /usr/bin/,
// use the long format with '=' character between the argument and the
// value.
// If the application is specified without /usr/bin,
// then adding -- before the application name allows this to work.
const char **ptr = m_appData->argv()+1;
for (int i = 1; i < m_appData->argc(); i++, ptr++) {
if (strcmp(*ptr, "--") == 0) {
if (i+1 < m_appData->argc()) {
return std::string(*(++ptr));
}
} else if (strncmp(*ptr, "/usr/bin/", 9) == 0) {
return std::string(*ptr);
}
}
}
return name;
}

Loading…
Cancel
Save