diff options
-rw-r--r-- | src/firejail/appimage.c | 54 |
1 files changed, 32 insertions, 22 deletions
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index f93891af2..a4f727c0a 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -33,12 +33,10 @@ static char *devloop = NULL; // device file | |||
33 | static long unsigned size = 0; // offset into appimage file | 33 | static long unsigned size = 0; // offset into appimage file |
34 | #define MAXBUF 4096 | 34 | #define MAXBUF 4096 |
35 | 35 | ||
36 | #ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h | 36 | static void err_loop(char *msg) { |
37 | static void err_loop(void) { | 37 | fprintf(stderr, "%s\n", msg); |
38 | fprintf(stderr, "Error: cannot configure loopback device\n"); | ||
39 | exit(1); | 38 | exit(1); |
40 | } | 39 | } |
41 | #endif | ||
42 | 40 | ||
43 | // return 1 if found | 41 | // return 1 if found |
44 | int appimage_find_profile(const char *archive) { | 42 | int appimage_find_profile(const char *archive) { |
@@ -75,7 +73,6 @@ void appimage_set(const char *appimage) { | |||
75 | assert(devloop == NULL); // don't call this twice! | 73 | assert(devloop == NULL); // don't call this twice! |
76 | EUID_ASSERT(); | 74 | EUID_ASSERT(); |
77 | 75 | ||
78 | #ifdef LOOP_CTL_GET_FREE | ||
79 | // open appimage file | 76 | // open appimage file |
80 | invalid_filename(appimage, 0); // no globbing | 77 | invalid_filename(appimage, 0); // no globbing |
81 | int ffd = open(appimage, O_RDONLY|O_CLOEXEC); | 78 | int ffd = open(appimage, O_RDONLY|O_CLOEXEC); |
@@ -99,29 +96,46 @@ void appimage_set(const char *appimage) { | |||
99 | 96 | ||
100 | // find or allocate a free loop device to use | 97 | // find or allocate a free loop device to use |
101 | EUID_ROOT(); | 98 | EUID_ROOT(); |
102 | int cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC); | 99 | int cfd; // loop control fd |
103 | if (cfd == -1) | 100 | if ((cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC)) == -1) { |
104 | err_loop(); | 101 | sleep(1); // sleep 1 second and try again |
105 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); | 102 | if ((cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC)) == -1) |
106 | if (devnr == -1) | 103 | err_loop("cannot open /dev/loop-control"); |
107 | err_loop(); | 104 | } |
105 | |||
106 | int devnr; // loop device number | ||
107 | if ((devnr = ioctl(cfd, LOOP_CTL_GET_FREE)) == -1) { | ||
108 | sleep(1); // sleep 1 second and try again | ||
109 | if ((devnr = ioctl(cfd, LOOP_CTL_GET_FREE)) == -1) | ||
110 | err_loop("cannot get a free loop device number"); | ||
111 | } | ||
108 | close(cfd); | 112 | close(cfd); |
109 | if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) | 113 | if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) |
110 | errExit("asprintf"); | 114 | errExit("asprintf"); |
111 | 115 | ||
116 | int lfd; // loopback fd | ||
117 | if ((lfd = open(devloop, O_RDONLY|O_CLOEXEC)) == -1) { | ||
118 | sleep (1); // sleep 1 second and try again | ||
119 | if ((lfd = open(devloop, O_RDONLY|O_CLOEXEC)) == -1) | ||
120 | err_loop("cannot open loop device"); | ||
121 | } | ||
122 | |||
112 | // associate loop device with appimage | 123 | // associate loop device with appimage |
113 | int lfd = open(devloop, O_RDONLY|O_CLOEXEC); | 124 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) { |
114 | if (lfd == -1) | 125 | sleep(1); // sleep 1 second and try again |
115 | err_loop(); | 126 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) |
116 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) | 127 | err_loop("cannot associate loop device with appimage file"); |
117 | err_loop(); | 128 | } |
118 | 129 | ||
119 | if (size) { | 130 | if (size) { |
120 | struct loop_info64 info; | 131 | struct loop_info64 info; |
121 | memset(&info, 0, sizeof(struct loop_info64)); | 132 | memset(&info, 0, sizeof(struct loop_info64)); |
122 | info.lo_offset = size; | 133 | info.lo_offset = size; |
123 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) | 134 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) { |
124 | err_loop(); | 135 | sleep(1); // sleep 1 second and try again |
136 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) | ||
137 | err_loop("cannot set loop status"); | ||
138 | } | ||
125 | } | 139 | } |
126 | close(lfd); | 140 | close(lfd); |
127 | close(ffd); | 141 | close(ffd); |
@@ -143,10 +157,6 @@ void appimage_set(const char *appimage) { | |||
143 | env_store_name_val("OWD", cfg.cwd, SETENV); | 157 | env_store_name_val("OWD", cfg.cwd, SETENV); |
144 | 158 | ||
145 | __gcov_flush(); | 159 | __gcov_flush(); |
146 | #else | ||
147 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); | ||
148 | exit(1); | ||
149 | #endif | ||
150 | } | 160 | } |
151 | 161 | ||
152 | // mount appimage into sandbox file system | 162 | // mount appimage into sandbox file system |