From a4444baae73f99dc57b6eb337182f26c553b0094 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sun, 5 Jun 2016 10:38:02 -0400 Subject: appimage support --- README.md | 29 +++++++++++++++ src/firejail/appimage.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ src/firejail/firejail.h | 2 ++ src/firejail/main.c | 29 +++++++++++++-- src/firejail/usage.c | 1 + src/man/firejail.txt | 13 +++++++ 6 files changed, 165 insertions(+), 3 deletions(-) create mode 100644 src/firejail/appimage.c diff --git a/README.md b/README.md index 543565fe4..2c8d0875a 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,35 @@ FAQ: https://firejail.wordpress.com/support/frequently-asked-questions/ ````` # Current development version: 0.9.41 +## AppImage + +AppImage (http://appimage.org/) is a distribution-agnostic packaging format. +The package is a regular ISO file containing all binaries, libraries and resources +necessary for the program to run. + +We introduce in this release support for sandboxing AppImage applications. Example: +````` +$ firejail --appimage krita-3.0-x86_64.appimage +````` +All Firejail sandboxing options should be available. A private home directory: +````` +$ firejail --appimage --private krita-3.0-x86_64.appimage +````` +or some basic X11 sandboxing: +````` +$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage +````` +Major software applications distributing AppImage packages: + +..* Krita: https://krita.org/download/krita-desktop/ +..* OpenShot: http://www.openshot.org/download/ +..* Scribus: https://www.scribus.net/downloads/unstable-branch/ +..* MuseScore: https://musescore.org/en/download + +More packages build by AppImage developer Simon Peter: https://bintray.com/probono/AppImages + +AppImage project home: https://github.com/probonopd/AppImageKit + ## New security profiles Gitter diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c new file mode 100644 index 000000000..e25d50a2d --- /dev/null +++ b/src/firejail/appimage.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2014-2016 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +// http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=770fe30a46a12b6fb6b63fbe1737654d28e84844 +// sudo mount -o loop krita-3.0-x86_64.appimage mnt + +#include "firejail.h" +#include +#include +#include +#include +#include + + + +char *appimage_set(const char *appimage_path) { + assert(appimage_path); + EUID_ASSERT(); + + // check appimage_path + if (access(appimage_path, R_OK) == -1) { + fprintf(stderr, "Error: cannot access AppImage file\n"); + exit(1); + } + + EUID_ROOT(); + + // find or allocate a free loop device to use + int cfd = open("/dev/loop-control", O_RDWR); + int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); + if (devnr == -1) { + fprintf(stderr, "Error: cannot allocate a new loopback device\n"); + exit(1); + } + close(cfd); + char *devloop; + if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) + errExit("asprintf"); + + int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC); + int lfd = open(devloop, O_RDONLY); + if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) { + fprintf(stderr, "Error: cannot configure the loopback device\n"); + exit(1); + } + close(lfd); + close(ffd); + + char dirname[] = "/tmp/firejail-mnt-XXXXXX"; + char *mntdir = strdup(mkdtemp(dirname)); + if (mntdir == NULL) { + fprintf(stderr, "Error: cannot create temporary directory\n"); + exit(1); + } + mkdir(mntdir, 755); + chown(mntdir, getuid(), getgid()); + chmod(mntdir, 755); + + char *mode; + if (asprintf(&mode, "mode=755,uid=%d,gid=%d", getuid(), getgid()) == -1) + errExit("asprintf"); + + if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0) + errExit("mounting appimage"); + + if (arg_debug) + printf("appimage mounted on %s\n", mntdir); + EUID_USER(); + + // build new command line + if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1) + errExit("asprintf"); + + free(devloop); + free(mode); + + return mntdir; +} diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index b0a3ac90d..00674c047 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -575,6 +575,8 @@ int checkcfg(int val); void fs_rdwr_add(const char *path); void fs_rdwr(void); +// appimage.c +char *appimage_set(const char *appimage_path); #endif diff --git a/src/firejail/main.c b/src/firejail/main.c index 0c843de9c..c2ac4a3fa 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -107,6 +107,7 @@ char *fullargv[MAX_ARGS]; // expanded argv for restricted shell int fullargc = 0; static pid_t child = 0; pid_t sandbox_pid; +static char *appimage_mntdir = NULL; static void set_name_file(pid_t pid); static void delete_name_file(pid_t pid); @@ -129,7 +130,12 @@ static void myexit(int rv) { // delete sandbox files in shared memory EUID_ROOT(); clear_run_files(sandbox_pid); - + if (appimage_mntdir) { + umount2(appimage_mntdir, MNT_FORCE); + rmdir(appimage_mntdir); + free(appimage_mntdir); + } + exit(rv); } @@ -701,6 +707,7 @@ int main(int argc, char **argv) { #ifdef HAVE_SECCOMP int highest_errno = errno_highest_nr(); #endif + int arg_appimage = 0; // drop permissions by default and rise them when required EUID_INIT(); @@ -1400,7 +1407,7 @@ int main(int argc, char **argv) { } else if (strncmp(argv[i], "--env=", 6) == 0) env_store(argv[i] + 6); - else if (strncmp(argv[i], "--nosound", 9) == 0) { + else if (strcmp(argv[i], "--nosound") == 0) { arg_nosound = 1; arg_private_dev = 1; } @@ -1766,6 +1773,8 @@ int main(int argc, char **argv) { //************************************* // command //************************************* + else if (strcmp(argv[i], "--appimage") == 0) + arg_appimage = 1; else if (strcmp(argv[i], "--csh") == 0) { if (arg_shell_none) { @@ -1847,7 +1856,13 @@ int main(int argc, char **argv) { } // we have a program name coming - extract_command_name(i, argv); + if (arg_appimage) { + cfg.command_name = strdup(argv[i]); + if (!cfg.command_name) + errExit("strdup"); + } + else + extract_command_name(i, argv); prog_index = i; break; } @@ -1900,6 +1915,13 @@ int main(int argc, char **argv) { cfg.window_title = "/bin/bash"; cfg.command_name = "bash"; } + else if (arg_appimage) { + if (arg_debug) + printf("Configuring appimage environment\n"); + appimage_mntdir = appimage_set(cfg.command_name); + cfg.window_title = "appimage"; + //todo: set window title + } else { // calculate the length of the command int i; @@ -1939,6 +1961,7 @@ int main(int argc, char **argv) { assert(cfg.command_name); if (arg_debug) printf("Command name #%s#\n", cfg.command_name); + // load the profile if (!arg_noprofile) { diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 45bf2e3b1..d2f7d9460 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -34,6 +34,7 @@ void usage(void) { printf("\n"); printf("Options:\n\n"); printf(" -- - signal the end of options and disables further option processing.\n\n"); + printf(" --appimage - sandbox an AppImage application\n\n"); #ifdef HAVE_NETWORK printf(" --bandwidth=name|pid - set bandwidth limits for the sandbox identified\n"); printf("\tby name or PID, see Traffic Shaping section fo more details.\n\n"); diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 3c4de9ed5..e57b8fb93 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -75,6 +75,19 @@ $ firejail [OPTIONS] firefox # starting Mozilla Firefox \fB\-\- Signal the end of options and disables further option processing. .TP +\fB\-\-appimage +Sandbox an AppImage (http://appimage.org/) application. +.br + +.br +Example: +.br +$ firejail --appimage krita-3.0-x86_64.appimage +.br +$ firejail --appimage --private krita-3.0-x86_64.appimage +.br +$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage +.TP \fB\-\-bandwidth=name|pid Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details. .TP -- cgit v1.2.3-54-g00ecf