aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/appimage.c129
-rw-r--r--src/firejail/appimage_size.c22
-rw-r--r--src/firejail/cmdline.c16
-rw-r--r--src/firejail/firejail.h6
-rw-r--r--src/firejail/fs.c2
-rw-r--r--src/firejail/main.c2
-rw-r--r--src/firejail/sandbox.c2
-rwxr-xr-xtest/appimage/appimage-args.exp2
-rwxr-xr-xtest/appimage/appimage-trace.exp4
-rwxr-xr-xtest/appimage/appimage-v1.exp2
-rwxr-xr-xtest/appimage/appimage-v2.exp2
-rwxr-xr-xtest/appimage/appimage.sh2
-rwxr-xr-xtest/appimage/filename.exp2
13 files changed, 67 insertions, 126 deletions
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c
index 40e53f44d..59758bf2d 100644
--- a/src/firejail/appimage.c
+++ b/src/firejail/appimage.c
@@ -29,7 +29,7 @@
29#include <errno.h> 29#include <errno.h>
30 30
31static char *devloop = NULL; // device file 31static char *devloop = NULL; // device file
32static char *mntdir = NULL; // mount point in /tmp directory 32static long unsigned size = 0; // offset into appimage file
33 33
34#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h 34#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h
35static void err_loop(void) { 35static void err_loop(void) {
@@ -44,27 +44,27 @@ void appimage_set(const char *appimage) {
44 EUID_ASSERT(); 44 EUID_ASSERT();
45 45
46#ifdef LOOP_CTL_GET_FREE 46#ifdef LOOP_CTL_GET_FREE
47 // check appimage file 47 // open appimage file
48 invalid_filename(appimage, 0); // no globbing 48 invalid_filename(appimage, 0); // no globbing
49 if (access(appimage, R_OK) == -1) { 49 int ffd = open(appimage, O_RDONLY|O_CLOEXEC);
50 fprintf(stderr, "Error: cannot access AppImage file\n"); 50 if (ffd == -1) {
51 fprintf(stderr, "Error: cannot read AppImage file\n");
52 exit(1);
53 }
54 struct stat s;
55 if (fstat(ffd, &s) == -1)
56 errExit("fstat");
57 if (!S_ISREG(s.st_mode)) {
58 fprintf(stderr, "Error: invalid AppImage file\n");
51 exit(1); 59 exit(1);
52 } 60 }
53 61
54 // get appimage type and ELF size 62 // get appimage type and ELF size
55 // a value of 0 means we are dealing with a type1 appimage 63 // a value of 0 means we are dealing with a type1 appimage
56 long unsigned int size = appimage2_size(appimage); 64 size = appimage2_size(ffd);
57 if (arg_debug) 65 if (arg_debug)
58 printf("AppImage ELF size %lu\n", size); 66 printf("AppImage ELF size %lu\n", size);
59 67
60 // open appimage file
61 /* coverity[toctou] */
62 int ffd = open(appimage, O_RDONLY|O_CLOEXEC);
63 if (ffd == -1) {
64 fprintf(stderr, "Error: cannot open AppImage file\n");
65 exit(1);
66 }
67
68 // find or allocate a free loop device to use 68 // find or allocate a free loop device to use
69 EUID_ROOT(); 69 EUID_ROOT();
70 int cfd = open("/dev/loop-control", O_RDWR); 70 int cfd = open("/dev/loop-control", O_RDWR);
@@ -77,6 +77,7 @@ void appimage_set(const char *appimage) {
77 if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) 77 if (asprintf(&devloop, "/dev/loop%d", devnr) == -1)
78 errExit("asprintf"); 78 errExit("asprintf");
79 79
80 // associate loop device with appimage
80 int lfd = open(devloop, O_RDONLY); 81 int lfd = open(devloop, O_RDONLY);
81 if (lfd == -1) 82 if (lfd == -1)
82 err_loop(); 83 err_loop();
@@ -90,64 +91,24 @@ void appimage_set(const char *appimage) {
90 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) 91 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1)
91 err_loop(); 92 err_loop();
92 } 93 }
93
94 close(lfd); 94 close(lfd);
95 close(ffd); 95 close(ffd);
96 EUID_USER(); 96 EUID_USER();
97 97
98 // creates appimage mount point perms 0700 98 // set environment
99 if (asprintf(&mntdir, "%s/.appimage-%u", RUN_FIREJAIL_APPIMAGE_DIR, getpid()) == -1)
100 errExit("asprintf");
101 EUID_ROOT();
102 mkdir_attr(mntdir, 0700, getuid(), getgid());
103 EUID_USER();
104
105 // mount
106 char *mode;
107 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1)
108 errExit("asprintf");
109 unsigned long flags = MS_MGC_VAL|MS_RDONLY;
110 if (getuid())
111 flags |= MS_NODEV|MS_NOSUID;
112
113 EUID_ROOT();
114 if (size == 0) {
115 fmessage("Mounting appimage type 1\n");
116 if (mount(devloop, mntdir, "iso9660", flags, mode) < 0)
117 errExit("mounting appimage");
118 }
119 else {
120 fmessage("Mounting appimage type 2\n");
121 if (mount(devloop, mntdir, "squashfs", flags, NULL) < 0)
122 errExit("mounting appimage");
123 }
124
125 if (arg_debug)
126 printf("appimage mounted on %s\n", mntdir);
127 EUID_USER();
128
129 char* abspath = realpath(appimage, NULL); 99 char* abspath = realpath(appimage, NULL);
130 if (abspath == NULL) 100 if (abspath == NULL)
131 errExit("Failed to obtain absolute path"); 101 errExit("Failed to obtain absolute path");
132
133 // set environment
134 env_store_name_val("APPIMAGE", abspath, SETENV); 102 env_store_name_val("APPIMAGE", abspath, SETENV);
103 free(abspath);
135 104
136 if (mntdir) 105 env_store_name_val("APPDIR", RUN_FIREJAIL_APPIMAGE_DIR, SETENV);
137 env_store_name_val("APPDIR", mntdir, SETENV);
138 106
139 if (size != 0) 107 if (size != 0)
140 env_store_name_val("ARGV0", appimage, SETENV); 108 env_store_name_val("ARGV0", appimage, SETENV);
141 109
142 if (cfg.cwd) 110 if (cfg.cwd)
143 env_store_name_val("OWD", cfg.cwd, SETENV); 111 env_store_name_val("OWD", cfg.cwd, SETENV);
144
145 // build new command line
146 if (asprintf(&cfg.command_line, "%s/AppRun", mntdir) == -1)
147 errExit("asprintf");
148
149 free(abspath);
150 free(mode);
151#ifdef HAVE_GCOV 112#ifdef HAVE_GCOV
152 __gcov_flush(); 113 __gcov_flush();
153#endif 114#endif
@@ -157,44 +118,38 @@ void appimage_set(const char *appimage) {
157#endif 118#endif
158} 119}
159 120
160void appimage_clear(void) { 121// mount appimage into sandbox file system
161 int rv; 122void appimage_mount(void) {
123 if (!devloop)
124 return;
162 125
163 EUID_ROOT(); 126 unsigned long flags = MS_MGC_VAL|MS_RDONLY;
164 if (mntdir) { 127 if (getuid())
165 int i; 128 flags |= MS_NODEV|MS_NOSUID;
166 int rv = 0;
167 for (i = 0; i < 5; i++) {
168 rv = umount2(mntdir, MNT_FORCE);
169 if (rv == 0) {
170 fmessage("AppImage unmounted\n");
171
172 break;
173 }
174 if (rv == -1 && errno == EBUSY) {
175 fwarning("EBUSY error trying to unmount %s\n", mntdir);
176 sleep(2);
177 continue;
178 }
179
180 // rv = -1
181 if (!arg_quiet) {
182 fwarning("error trying to unmount %s\n", mntdir);
183 perror("umount");
184 }
185 }
186 129
187 if (rv == 0) { 130 if (size == 0) {
188 rmdir(mntdir); 131 fmessage("Mounting appimage type 1\n");
189 free(mntdir); 132 char *mode;
190 } 133 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1)
134 errExit("asprintf");
135 if (mount(devloop, RUN_FIREJAIL_APPIMAGE_DIR, "iso9660", flags, mode) < 0)
136 errExit("mounting appimage");
137 free(mode);
191 } 138 }
139 else {
140 fmessage("Mounting appimage type 2\n");
141 if (mount(devloop, RUN_FIREJAIL_APPIMAGE_DIR, "squashfs", flags, NULL) < 0)
142 errExit("mounting appimage");
143 }
144}
192 145
146void appimage_clear(void) {
147 EUID_ROOT();
193 if (devloop) { 148 if (devloop) {
194 int lfd = open(devloop, O_RDONLY); 149 int lfd = open(devloop, O_RDONLY);
195 if (lfd != -1) { 150 if (lfd != -1) {
196 rv = ioctl(lfd, LOOP_CLR_FD, 0); 151 if (ioctl(lfd, LOOP_CLR_FD, 0) != -1)
197 (void) rv; 152 fmessage("AppImage detached\n");
198 close(lfd); 153 close(lfd);
199 } 154 }
200 } 155 }
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c
index 4640cb8a5..43ca501da 100644
--- a/src/firejail/appimage_size.c
+++ b/src/firejail/appimage_size.c
@@ -132,22 +132,20 @@ static long unsigned int read_elf64(int fd) {
132 132
133// return 0 if error 133// return 0 if error
134// return 0 if this is not an appimgage2 file 134// return 0 if this is not an appimgage2 file
135long unsigned int appimage2_size(const char *fname) { 135long unsigned int appimage2_size(int fd) {
136 ssize_t ret; 136 ssize_t ret;
137 int fd;
138 long unsigned int size = 0; 137 long unsigned int size = 0;
139 138
140 fd = open(fname, O_RDONLY);
141 if (fd < 0) 139 if (fd < 0)
142 return 0; 140 return 0;
143 141
144 ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0); 142 ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
145 if (ret != EI_NIDENT) 143 if (ret != EI_NIDENT)
146 goto getout; 144 return 0;
147 145
148 if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) && 146 if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
149 (ehdr.e_ident[EI_DATA] != ELFDATA2MSB)) 147 (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
150 goto getout; 148 return 0;
151 149
152 if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) { 150 if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
153 size = read_elf32(fd); 151 size = read_elf32(fd);
@@ -156,23 +154,19 @@ long unsigned int appimage2_size(const char *fname) {
156 size = read_elf64(fd); 154 size = read_elf64(fd);
157 } 155 }
158 else { 156 else {
159 goto getout; 157 return 0;
160 } 158 }
161 if (size == 0) 159 if (size == 0)
162 goto getout; 160 return 0;
163 161
164 162
165 // look for a LZMA header at this location 163 // look for a LZMA header at this location
166 unsigned char buf[4]; 164 unsigned char buf[4];
167 ret = pread(fd, buf, 4, size); 165 ret = pread(fd, buf, 4, size);
168 if (ret != 4) { 166 if (ret != 4)
169 size = 0; 167 return 0;
170 goto getout;
171 }
172 if (memcmp(buf, "hsqs", 4) != 0) 168 if (memcmp(buf, "hsqs", 4) != 0)
173 size = 0; 169 return 0;
174 170
175getout:
176 close(fd);
177 return size; 171 return size;
178} 172}
diff --git a/src/firejail/cmdline.c b/src/firejail/cmdline.c
index 0cdcb32bf..f902c4e1c 100644
--- a/src/firejail/cmdline.c
+++ b/src/firejail/cmdline.c
@@ -161,18 +161,16 @@ void build_cmdline(char **command_line, char **window_title, int argc, char **ar
161 assert(*window_title); 161 assert(*window_title);
162} 162}
163 163
164void build_appimage_cmdline(char **command_line, char **window_title, int argc, char **argv, int index, char *apprun_path) { 164void build_appimage_cmdline(char **command_line, char **window_title, int argc, char **argv, int index) {
165 // index == -1 could happen if we have --shell=none and no program was specified 165 // index == -1 could happen if we have --shell=none and no program was specified
166 // the program should exit with an error before entering this function 166 // the program should exit with an error before entering this function
167 assert(index != -1); 167 assert(index != -1);
168 168
169 if (arg_debug) 169 char *apprun_path = RUN_FIREJAIL_APPIMAGE_DIR "/AppRun";
170 printf("Building AppImage command line: %s\n", *command_line);
171
172 170
173 int len1 = cmdline_length(argc, argv, index); // length of argv w/o changes 171 int len1 = cmdline_length(argc, argv, index); // length of argv w/o changes
174 int len2 = cmdline_length(1, &argv[index], 0); // apptest.AppImage 172 int len2 = cmdline_length(1, &argv[index], 0); // apptest.AppImage
175 int len3 = cmdline_length(1, &apprun_path, 0); // /run/firejail/appimage/.appimage-23304/AppRun 173 int len3 = cmdline_length(1, &apprun_path, 0); // /run/firejail/appimage/AppRun
176 int len4 = (len1 - len2 + len3) + 1; // apptest.AppImage is replaced by /path/to/AppRun 174 int len4 = (len1 - len2 + len3) + 1; // apptest.AppImage is replaced by /path/to/AppRun
177 175
178 if (len4 > ARG_MAX) { 176 if (len4 > ARG_MAX) {
@@ -180,11 +178,6 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
180 errExit("cmdline_length"); 178 errExit("cmdline_length");
181 } 179 }
182 180
183 // save created apprun in cfg.command_line
184 char *tmp1 = strdup(*command_line);
185 if (!tmp1)
186 errExit("strdup");
187
188 // TODO: deal with extra allocated memory. 181 // TODO: deal with extra allocated memory.
189 char *command_line_tmp = malloc(len1 + len3 + 1); 182 char *command_line_tmp = malloc(len1 + len3 + 1);
190 if (!command_line_tmp) 183 if (!command_line_tmp)
@@ -200,13 +193,12 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
200 assert(*window_title); 193 assert(*window_title);
201 194
202 // 'fix' command_line now 195 // 'fix' command_line now
203 if (asprintf(command_line, "'%s' %s", tmp1, command_line_tmp + len2) == -1) 196 if (asprintf(command_line, "'%s' %s", apprun_path, command_line_tmp + len2) == -1)
204 errExit("asprintf"); 197 errExit("asprintf");
205 198
206 if (arg_debug) 199 if (arg_debug)
207 printf("AppImage quoted command line: %s\n", *command_line); 200 printf("AppImage quoted command line: %s\n", *command_line);
208 201
209 // free strdup 202 // free strdup
210 free(tmp1);
211 free(command_line_tmp); 203 free(command_line_tmp);
212} 204}
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index b21b5bef6..ca4c988fa 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -798,15 +798,15 @@ void print_compiletime_support(void);
798 798
799// appimage.c 799// appimage.c
800void appimage_set(const char *appimage_path); 800void appimage_set(const char *appimage_path);
801void appimage_mount(void);
801void appimage_clear(void); 802void appimage_clear(void);
802const char *appimage_getdir(void);
803 803
804// appimage_size.c 804// appimage_size.c
805long unsigned int appimage2_size(const char *fname); 805long unsigned int appimage2_size(int fd);
806 806
807// cmdline.c 807// cmdline.c
808void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); 808void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index);
809void build_appimage_cmdline(char **command_line, char **window_title, int argc, char **argv, int index, char *apprun_path); 809void build_appimage_cmdline(char **command_line, char **window_title, int argc, char **argv, int index);
810 810
811// sbox.c 811// sbox.c
812// programs 812// programs
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 8b7e49611..fc67a15f3 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -801,8 +801,6 @@ void disable_config(void) {
801 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR); 801 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_PROFILE_DIR);
802 if (stat(RUN_FIREJAIL_X11_DIR, &s) == 0) 802 if (stat(RUN_FIREJAIL_X11_DIR, &s) == 0)
803 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR); 803 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_X11_DIR);
804 if (!arg_appimage && stat(RUN_FIREJAIL_APPIMAGE_DIR, &s) == 0)
805 disable_file(BLACKLIST_FILE, RUN_FIREJAIL_APPIMAGE_DIR);
806} 804}
807 805
808 806
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 9705c2436..b3524fcf5 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -2790,7 +2790,7 @@ int main(int argc, char **argv, char **envp) {
2790 if (arg_debug) 2790 if (arg_debug)
2791 printf("Configuring appimage environment\n"); 2791 printf("Configuring appimage environment\n");
2792 appimage_set(cfg.command_name); 2792 appimage_set(cfg.command_name);
2793 build_appimage_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index, cfg.command_line); 2793 build_appimage_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
2794 } 2794 }
2795 else { 2795 else {
2796 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); 2796 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 36a54d6fe..60c097cf2 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -630,6 +630,8 @@ int sandbox(void* sandbox_arg) {
630 errExit("mounting " RUN_FIREJAIL_LIB_DIR); 630 errExit("mounting " RUN_FIREJAIL_LIB_DIR);
631 // keep a copy of dhclient executable before the filesystem is modified 631 // keep a copy of dhclient executable before the filesystem is modified
632 dhcp_store_exec(); 632 dhcp_store_exec();
633 // mount appimage before the filesystem is modified
634 appimage_mount();
633 635
634 //**************************** 636 //****************************
635 // log sandbox data 637 // log sandbox data
diff --git a/test/appimage/appimage-args.exp b/test/appimage/appimage-args.exp
index 16ab7f54d..eecb9bf82 100755
--- a/test/appimage/appimage-args.exp
+++ b/test/appimage/appimage-args.exp
@@ -96,7 +96,7 @@ send -- "firejail --shutdown=appimage-test\r"
96set spawn_id $appimage_id 96set spawn_id $appimage_id
97expect { 97expect {
98 timeout {puts "shutdown\n";exit} 98 timeout {puts "shutdown\n";exit}
99 "AppImage unmounted" 99 "AppImage detached"
100} 100}
101 101
102after 100 102after 100
diff --git a/test/appimage/appimage-trace.exp b/test/appimage/appimage-trace.exp
index 5f05e2846..2f67eb531 100755
--- a/test/appimage/appimage-trace.exp
+++ b/test/appimage/appimage-trace.exp
@@ -31,7 +31,7 @@ expect {
31} 31}
32expect { 32expect {
33 timeout {puts "shutdown\n"} 33 timeout {puts "shutdown\n"}
34 "AppImage unmounted" 34 "AppImage detached"
35} 35}
36sleep 1 36sleep 1
37 37
@@ -58,7 +58,7 @@ expect {
58} 58}
59expect { 59expect {
60 timeout {puts "shutdown\n"} 60 timeout {puts "shutdown\n"}
61 "AppImage unmounted" 61 "AppImage detached"
62} 62}
63sleep 1 63sleep 1
64 64
diff --git a/test/appimage/appimage-v1.exp b/test/appimage/appimage-v1.exp
index d90793bb3..b8b6e0c96 100755
--- a/test/appimage/appimage-v1.exp
+++ b/test/appimage/appimage-v1.exp
@@ -84,7 +84,7 @@ send -- "firejail --shutdown=appimage-test\r"
84set spawn_id $appimage_id 84set spawn_id $appimage_id
85expect { 85expect {
86 timeout {puts "shutdown\n"} 86 timeout {puts "shutdown\n"}
87 "AppImage unmounted" 87 "AppImage detached"
88} 88}
89 89
90after 100 90after 100
diff --git a/test/appimage/appimage-v2.exp b/test/appimage/appimage-v2.exp
index b606c7a77..243824f75 100755
--- a/test/appimage/appimage-v2.exp
+++ b/test/appimage/appimage-v2.exp
@@ -83,7 +83,7 @@ send -- "firejail --shutdown=appimage-test\r"
83set spawn_id $appimage_id 83set spawn_id $appimage_id
84expect { 84expect {
85 timeout {puts "shutdown\n"} 85 timeout {puts "shutdown\n"}
86 "AppImage unmounted" 86 "AppImage detached"
87} 87}
88 88
89after 100 89after 100
diff --git a/test/appimage/appimage.sh b/test/appimage/appimage.sh
index 548cd7fdf..e766b1acd 100755
--- a/test/appimage/appimage.sh
+++ b/test/appimage/appimage.sh
@@ -20,4 +20,4 @@ echo "TESTING: AppImage argsv1 (test/appimage/appimage-args.exp)"
20./appimage-args.exp 20./appimage-args.exp
21 21
22echo "TESTING: AppImage trace (test/appimage/appimage-trace.exp)" 22echo "TESTING: AppImage trace (test/appimage/appimage-trace.exp)"
23./appimage-args.exp 23./appimage-trace.exp
diff --git a/test/appimage/filename.exp b/test/appimage/filename.exp
index 7b64129b7..54d8d722d 100755
--- a/test/appimage/filename.exp
+++ b/test/appimage/filename.exp
@@ -17,7 +17,7 @@ after 100
17send -- "firejail --appimage /etc/shadow\r" 17send -- "firejail --appimage /etc/shadow\r"
18expect { 18expect {
19 timeout {puts "TESTING ERROR 2\n";exit} 19 timeout {puts "TESTING ERROR 2\n";exit}
20 "cannot access" 20 "cannot read"
21} 21}
22after 100 22after 100
23 23