From 3e020d4a91228d5646e9e3648d7604d07547c0d8 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 3 Mar 2021 13:26:34 +1100 Subject: [PATCH 1/2] add a way to disable sandbox if we cannot use it without crashing --- .prettierignore | 1 + build/afterPackHook.js | 43 ++++++++++++++++++++++++++++++++++++++++ build/launcher-script.sh | 6 ++++++ package.json | 9 +++++++-- 4 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 build/afterPackHook.js create mode 100755 build/launcher-script.sh diff --git a/.prettierignore b/.prettierignore index 8e5246ba3..d96512f17 100644 --- a/.prettierignore +++ b/.prettierignore @@ -56,3 +56,4 @@ stylesheets/_intlTelInput.scss coverage/** .nyc_output/** session-file-server/** +release/** diff --git a/build/afterPackHook.js b/build/afterPackHook.js new file mode 100644 index 000000000..7ccd796cb --- /dev/null +++ b/build/afterPackHook.js @@ -0,0 +1,43 @@ +const path = require('path'); +const fs = require('fs'); +const util = require('util'); + +const renameAsync = util.promisify(fs.rename); +const unlinkAsync = util.promisify(fs.unlink); + +module.exports = async function (context) { + // Replace the app launcher on linux only. + if (process.platform !== 'linux') { + return; + } + const isAppImage = context.targets.find(target => target.name === 'appImage') + if (!isAppImage) { + return + } + // eslint-disable-next-line no-console + console.log('afterPack hook triggered', context); + + const executableName = context.packager.executableName; + const sourceExecutable = path.join(context.appOutDir, executableName); + const targetExecutable = path.join( + context.appOutDir, + `${executableName}-bin` + ); + const launcherScript = path.join( + context.appOutDir, + 'resources', + 'launcher-script.sh' + ); + const chromeSandbox = path.join(context.appOutDir, 'chrome-sandbox'); + + return Promise.all([ + // rename session-desktop to session-desktop-bin + renameAsync(sourceExecutable, targetExecutable), + + // rename launcher script to session-desktop + renameAsync(launcherScript, sourceExecutable), + + // remove the chrome-sandbox file since we explicitly disable it + unlinkAsync(chromeSandbox), + ]); +}; diff --git a/build/launcher-script.sh b/build/launcher-script.sh new file mode 100755 index 000000000..d5a631815 --- /dev/null +++ b/build/launcher-script.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +set -ex + +UNPRIVILEGED_USERNS_ENABLED=$(cat /proc/sys/kernel/unprivileged_userns_clone 2>/dev/null) +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +exec "$SCRIPT_DIR/session-desktop-bin" "$([[ $UNPRIVILEGED_USERNS_ENABLED == 0 ]] && echo '--no-sandbox')" "$@" diff --git a/package.json b/package.json index e205e979f..2acdd786a 100644 --- a/package.json +++ b/package.json @@ -224,6 +224,10 @@ "appId": "com.loki-project.messenger-desktop", "afterSign": "build/notarize.js", "artifactName": "${name}-${os}-${arch}-${version}.${ext}", + "extraResources": { + "from": "./build/launcher-script.sh", + "to": "./launcher-script.sh" + }, "mac": { "category": "public.app-category.social-networking", "icon": "build/icons/mac/icon.icns", @@ -334,7 +338,8 @@ "!node_modules/@journeyapps/sqlcipher/lib/binding/node-*", "!build/*.js", "!dev-app-update.yml" - ] + ], + "afterPack": "./build/afterPackHook.js" }, "husky": { "hooks": { @@ -346,4 +351,4 @@ "*/**/*.{css,js,json,scss,ts,tsx}": "prettier --write", "*.js": "eslint --cache --fix" } -} +} \ No newline at end of file From 7dfe8042cdbd9e5433bfdad7fb80e8e05e7fd3fb Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 16 Mar 2021 13:56:18 +1100 Subject: [PATCH 2/2] fix SUID issue --- build/afterPackHook.js | 6 +++--- build/launcher-script.sh | 8 +++++++- main.js | 1 + package.json | 1 - 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/build/afterPackHook.js b/build/afterPackHook.js index 7ccd796cb..ef42cc389 100644 --- a/build/afterPackHook.js +++ b/build/afterPackHook.js @@ -5,14 +5,14 @@ const util = require('util'); const renameAsync = util.promisify(fs.rename); const unlinkAsync = util.promisify(fs.unlink); -module.exports = async function (context) { +module.exports = async function(context) { // Replace the app launcher on linux only. if (process.platform !== 'linux') { return; } - const isAppImage = context.targets.find(target => target.name === 'appImage') + const isAppImage = context.targets.find(target => target.name === 'appImage'); if (!isAppImage) { - return + return; } // eslint-disable-next-line no-console console.log('afterPack hook triggered', context); diff --git a/build/launcher-script.sh b/build/launcher-script.sh index d5a631815..8c4f3185b 100755 --- a/build/launcher-script.sh +++ b/build/launcher-script.sh @@ -1,5 +1,11 @@ #!/usr/bin/env bash -set -ex +set -e + +# Some distributions do not have unprivileged_userns_clone disabled. +# If that's the case, and we run an AppImage (deb is not impacted by this), +# the app won't start unless we start it with --no-sandbox. +# This bash script is the launcher script for AppImage only, and will at runtime check +# if we need to add the --no-sandbox before running the AppImage itself. UNPRIVILEGED_USERNS_ENABLED=$(cat /proc/sys/kernel/unprivileged_userns_clone 2>/dev/null) SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" diff --git a/main.js b/main.js index 2d4f47ed5..71b551c2b 100644 --- a/main.js +++ b/main.js @@ -256,6 +256,7 @@ function isVisible(window, bounds) { async function createWindow() { const { screen } = electron; const { minWidth, minHeight, width, height } = getWindowSize(); + const windowOptions = Object.assign( { show: !startInTray, // allow to start minimised in tray diff --git a/package.json b/package.json index 3f01f6ee9..47dc3ad74 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "test-electron": "yarn grunt test", "test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --full-trace --timeout 10000 ts/test/session/integration/integration_itest.js", "test-node": "mocha --recursive --exit --timeout 10000 test/app test/modules \"./ts/test/**/*_test.js\" libloki/test/node ", - "test-audric": "mocha --recursive --exit --timeout 10000 ts/test/session/unit/", "eslint": "eslint --cache .", "eslint-fix": "eslint --fix .", "eslint-full": "eslint .",