aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-06-05 10:38:02 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2016-06-05 10:38:02 -0400
commita4444baae73f99dc57b6eb337182f26c553b0094 (patch)
tree78af4aa55c16b6db787ddddb59714829e99fdded
parentnetworking fixes (diff)
downloadfirejail-a4444baae73f99dc57b6eb337182f26c553b0094.tar.gz
firejail-a4444baae73f99dc57b6eb337182f26c553b0094.tar.zst
firejail-a4444baae73f99dc57b6eb337182f26c553b0094.zip
appimage support
-rw-r--r--README.md29
-rw-r--r--src/firejail/appimage.c94
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/main.c29
-rw-r--r--src/firejail/usage.c1
-rw-r--r--src/man/firejail.txt13
6 files changed, 165 insertions, 3 deletions
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/
36````` 36`````
37# Current development version: 0.9.41 37# Current development version: 0.9.41
38 38
39## AppImage
40
41AppImage (http://appimage.org/) is a distribution-agnostic packaging format.
42The package is a regular ISO file containing all binaries, libraries and resources
43necessary for the program to run.
44
45We introduce in this release support for sandboxing AppImage applications. Example:
46`````
47$ firejail --appimage krita-3.0-x86_64.appimage
48`````
49All Firejail sandboxing options should be available. A private home directory:
50`````
51$ firejail --appimage --private krita-3.0-x86_64.appimage
52`````
53or some basic X11 sandboxing:
54`````
55$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage
56`````
57Major software applications distributing AppImage packages:
58
59..* Krita: https://krita.org/download/krita-desktop/
60..* OpenShot: http://www.openshot.org/download/
61..* Scribus: https://www.scribus.net/downloads/unstable-branch/
62..* MuseScore: https://musescore.org/en/download
63
64More packages build by AppImage developer Simon Peter: https://bintray.com/probono/AppImages
65
66AppImage project home: https://github.com/probonopd/AppImageKit
67
39## New security profiles 68## New security profiles
40 69
41Gitter 70Gitter
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 @@
1/*
2 * Copyright (C) 2014-2016 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20// http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=770fe30a46a12b6fb6b63fbe1737654d28e84844
21// sudo mount -o loop krita-3.0-x86_64.appimage mnt
22
23#include "firejail.h"
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/mount.h>
27#include <fcntl.h>
28#include <linux/loop.h>
29
30
31
32char *appimage_set(const char *appimage_path) {
33 assert(appimage_path);
34 EUID_ASSERT();
35
36 // check appimage_path
37 if (access(appimage_path, R_OK) == -1) {
38 fprintf(stderr, "Error: cannot access AppImage file\n");
39 exit(1);
40 }
41
42 EUID_ROOT();
43
44 // find or allocate a free loop device to use
45 int cfd = open("/dev/loop-control", O_RDWR);
46 int devnr = ioctl(cfd, LOOP_CTL_GET_FREE);
47 if (devnr == -1) {
48 fprintf(stderr, "Error: cannot allocate a new loopback device\n");
49 exit(1);
50 }
51 close(cfd);
52 char *devloop;
53 if (asprintf(&devloop, "/dev/loop%d", devnr) == -1)
54 errExit("asprintf");
55
56 int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC);
57 int lfd = open(devloop, O_RDONLY);
58 if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) {
59 fprintf(stderr, "Error: cannot configure the loopback device\n");
60 exit(1);
61 }
62 close(lfd);
63 close(ffd);
64
65 char dirname[] = "/tmp/firejail-mnt-XXXXXX";
66 char *mntdir = strdup(mkdtemp(dirname));
67 if (mntdir == NULL) {
68 fprintf(stderr, "Error: cannot create temporary directory\n");
69 exit(1);
70 }
71 mkdir(mntdir, 755);
72 chown(mntdir, getuid(), getgid());
73 chmod(mntdir, 755);
74
75 char *mode;
76 if (asprintf(&mode, "mode=755,uid=%d,gid=%d", getuid(), getgid()) == -1)
77 errExit("asprintf");
78
79 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0)
80 errExit("mounting appimage");
81
82 if (arg_debug)
83 printf("appimage mounted on %s\n", mntdir);
84 EUID_USER();
85
86 // build new command line
87 if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1)
88 errExit("asprintf");
89
90 free(devloop);
91 free(mode);
92
93 return mntdir;
94}
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);
575void fs_rdwr_add(const char *path); 575void fs_rdwr_add(const char *path);
576void fs_rdwr(void); 576void fs_rdwr(void);
577 577
578// appimage.c
579char *appimage_set(const char *appimage_path);
578 580
579#endif 581#endif
580 582
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
107int fullargc = 0; 107int fullargc = 0;
108static pid_t child = 0; 108static pid_t child = 0;
109pid_t sandbox_pid; 109pid_t sandbox_pid;
110static char *appimage_mntdir = NULL;
110 111
111static void set_name_file(pid_t pid); 112static void set_name_file(pid_t pid);
112static void delete_name_file(pid_t pid); 113static void delete_name_file(pid_t pid);
@@ -129,7 +130,12 @@ static void myexit(int rv) {
129 // delete sandbox files in shared memory 130 // delete sandbox files in shared memory
130 EUID_ROOT(); 131 EUID_ROOT();
131 clear_run_files(sandbox_pid); 132 clear_run_files(sandbox_pid);
132 133 if (appimage_mntdir) {
134 umount2(appimage_mntdir, MNT_FORCE);
135 rmdir(appimage_mntdir);
136 free(appimage_mntdir);
137 }
138
133 exit(rv); 139 exit(rv);
134} 140}
135 141
@@ -701,6 +707,7 @@ int main(int argc, char **argv) {
701#ifdef HAVE_SECCOMP 707#ifdef HAVE_SECCOMP
702 int highest_errno = errno_highest_nr(); 708 int highest_errno = errno_highest_nr();
703#endif 709#endif
710 int arg_appimage = 0;
704 711
705 // drop permissions by default and rise them when required 712 // drop permissions by default and rise them when required
706 EUID_INIT(); 713 EUID_INIT();
@@ -1400,7 +1407,7 @@ int main(int argc, char **argv) {
1400 } 1407 }
1401 else if (strncmp(argv[i], "--env=", 6) == 0) 1408 else if (strncmp(argv[i], "--env=", 6) == 0)
1402 env_store(argv[i] + 6); 1409 env_store(argv[i] + 6);
1403 else if (strncmp(argv[i], "--nosound", 9) == 0) { 1410 else if (strcmp(argv[i], "--nosound") == 0) {
1404 arg_nosound = 1; 1411 arg_nosound = 1;
1405 arg_private_dev = 1; 1412 arg_private_dev = 1;
1406 } 1413 }
@@ -1766,6 +1773,8 @@ int main(int argc, char **argv) {
1766 //************************************* 1773 //*************************************
1767 // command 1774 // command
1768 //************************************* 1775 //*************************************
1776 else if (strcmp(argv[i], "--appimage") == 0)
1777 arg_appimage = 1;
1769 else if (strcmp(argv[i], "--csh") == 0) { 1778 else if (strcmp(argv[i], "--csh") == 0) {
1770 if (arg_shell_none) { 1779 if (arg_shell_none) {
1771 1780
@@ -1847,7 +1856,13 @@ int main(int argc, char **argv) {
1847 } 1856 }
1848 1857
1849 // we have a program name coming 1858 // we have a program name coming
1850 extract_command_name(i, argv); 1859 if (arg_appimage) {
1860 cfg.command_name = strdup(argv[i]);
1861 if (!cfg.command_name)
1862 errExit("strdup");
1863 }
1864 else
1865 extract_command_name(i, argv);
1851 prog_index = i; 1866 prog_index = i;
1852 break; 1867 break;
1853 } 1868 }
@@ -1900,6 +1915,13 @@ int main(int argc, char **argv) {
1900 cfg.window_title = "/bin/bash"; 1915 cfg.window_title = "/bin/bash";
1901 cfg.command_name = "bash"; 1916 cfg.command_name = "bash";
1902 } 1917 }
1918 else if (arg_appimage) {
1919 if (arg_debug)
1920 printf("Configuring appimage environment\n");
1921 appimage_mntdir = appimage_set(cfg.command_name);
1922 cfg.window_title = "appimage";
1923 //todo: set window title
1924 }
1903 else { 1925 else {
1904 // calculate the length of the command 1926 // calculate the length of the command
1905 int i; 1927 int i;
@@ -1939,6 +1961,7 @@ int main(int argc, char **argv) {
1939 assert(cfg.command_name); 1961 assert(cfg.command_name);
1940 if (arg_debug) 1962 if (arg_debug)
1941 printf("Command name #%s#\n", cfg.command_name); 1963 printf("Command name #%s#\n", cfg.command_name);
1964
1942 1965
1943 // load the profile 1966 // load the profile
1944 if (!arg_noprofile) { 1967 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) {
34 printf("\n"); 34 printf("\n");
35 printf("Options:\n\n"); 35 printf("Options:\n\n");
36 printf(" -- - signal the end of options and disables further option processing.\n\n"); 36 printf(" -- - signal the end of options and disables further option processing.\n\n");
37 printf(" --appimage - sandbox an AppImage application\n\n");
37#ifdef HAVE_NETWORK 38#ifdef HAVE_NETWORK
38 printf(" --bandwidth=name|pid - set bandwidth limits for the sandbox identified\n"); 39 printf(" --bandwidth=name|pid - set bandwidth limits for the sandbox identified\n");
39 printf("\tby name or PID, see Traffic Shaping section fo more details.\n\n"); 40 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
75\fB\-\- 75\fB\-\-
76Signal the end of options and disables further option processing. 76Signal the end of options and disables further option processing.
77.TP 77.TP
78\fB\-\-appimage
79Sandbox an AppImage (http://appimage.org/) application.
80.br
81
82.br
83Example:
84.br
85$ firejail --appimage krita-3.0-x86_64.appimage
86.br
87$ firejail --appimage --private krita-3.0-x86_64.appimage
88.br
89$ firejail --appimage --net=none --x11 krita-3.0-x86_64.appimage
90.TP
78\fB\-\-bandwidth=name|pid 91\fB\-\-bandwidth=name|pid
79Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details. 92Set bandwidth limits for the sandbox identified by name or PID, see \fBTRAFFIC SHAPING\fR section for more details.
80.TP 93.TP