summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2016-10-23 09:02:39 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2016-10-23 09:02:39 -0400
commit4bcab4f4e6a53f2b7d402092983ee0d71d555259 (patch)
treeb3ceecdf7c1dfcca0ec8bef6adaf58c9dd9848fe
parentstarting 0.9.45 devel version (diff)
downloadfirejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.tar.gz
firejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.tar.zst
firejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.zip
appimage type 2 support
-rw-r--r--src/firejail/appimage.c29
-rw-r--r--src/firejail/appimage_size.c143
-rw-r--r--src/firejail/firejail.h4
3 files changed, 173 insertions, 3 deletions
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c
index 375d6be24..3f03c28bf 100644
--- a/src/firejail/appimage.c
+++ b/src/firejail/appimage.c
@@ -39,7 +39,7 @@ void appimage_set(const char *appimage_path) {
39 assert(appimage_path); 39 assert(appimage_path);
40 assert(devloop == NULL); // don't call this twice! 40 assert(devloop == NULL); // don't call this twice!
41 EUID_ASSERT(); 41 EUID_ASSERT();
42 42
43#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h 43#ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h
44 // check appimage_path 44 // check appimage_path
45 if (access(appimage_path, R_OK) == -1) { 45 if (access(appimage_path, R_OK) == -1) {
@@ -47,6 +47,12 @@ void appimage_set(const char *appimage_path) {
47 exit(1); 47 exit(1);
48 } 48 }
49 49
50 // get appimage type and ELF size
51 // a value of 0 means we are dealing with a type1 appimage
52 long unsigned int size = appimage2_size(appimage_path);
53 if (arg_debug)
54 printf("AppImage ELF size %lu\n", size);
55
50 // open as user to prevent race condition 56 // open as user to prevent race condition
51 int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC); 57 int ffd = open(appimage_path, O_RDONLY|O_CLOEXEC);
52 if (ffd == -1) { 58 if (ffd == -1) {
@@ -76,6 +82,15 @@ void appimage_set(const char *appimage_path) {
76 fprintf(stderr, "Error: cannot configure the loopback device\n"); 82 fprintf(stderr, "Error: cannot configure the loopback device\n");
77 exit(1); 83 exit(1);
78 } 84 }
85
86 if (size) {
87 struct loop_info64 info;
88 memset(&info, 0, sizeof(struct loop_info64));
89 info.lo_offset = size;
90 if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1)
91 errExit("configure appimage offset");
92 }
93
79 close(lfd); 94 close(lfd);
80 close(ffd); 95 close(ffd);
81 EUID_USER(); 96 EUID_USER();
@@ -100,8 +115,16 @@ void appimage_set(const char *appimage_path) {
100 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1) 115 if (asprintf(&mode, "mode=700,uid=%d,gid=%d", getuid(), getgid()) == -1)
101 errExit("asprintf"); 116 errExit("asprintf");
102 EUID_ROOT(); 117 EUID_ROOT();
103 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0) 118
104 errExit("mounting appimage"); 119 if (size == 0) {
120 if (mount(devloop, mntdir, "iso9660",MS_MGC_VAL|MS_RDONLY, mode) < 0)
121 errExit("mounting appimage");
122 }
123 else {
124 if (mount(devloop, mntdir, "squashfs",MS_MGC_VAL|MS_RDONLY, mode) < 0)
125 errExit("mounting appimage");
126 }
127
105 if (arg_debug) 128 if (arg_debug)
106 printf("appimage mounted on %s\n", mntdir); 129 printf("appimage mounted on %s\n", mntdir);
107 EUID_USER(); 130 EUID_USER();
diff --git a/src/firejail/appimage_size.c b/src/firejail/appimage_size.c
new file mode 100644
index 000000000..c8b3d28c5
--- /dev/null
+++ b/src/firejail/appimage_size.c
@@ -0,0 +1,143 @@
1/*
2Compile with:
3gcc elfsize.c -o elfsize
4Example:
5ls -l 126584
6Calculation using the values also reported by readelf -h:
7Start of section headers e_shoff 124728
8Size of section headers e_shentsize 64
9Number of section headers e_shnum 29
10e_shoff + ( e_shentsize * e_shnum ) = 126584
11*/
12
13#include <elf.h>
14#include <byteswap.h>
15#include <stdio.h>
16#include <stdint.h>
17#include <errno.h>
18#include <stdlib.h>
19#include <unistd.h>
20#include <string.h>
21#include <fcntl.h>
22
23typedef Elf32_Nhdr Elf_Nhdr;
24
25static Elf64_Ehdr ehdr;
26static Elf64_Phdr *phdr;
27
28#if __BYTE_ORDER == __LITTLE_ENDIAN
29#define ELFDATANATIVE ELFDATA2LSB
30#elif __BYTE_ORDER == __BIG_ENDIAN
31#define ELFDATANATIVE ELFDATA2MSB
32#else
33#error "Unknown machine endian"
34#endif
35
36static uint16_t file16_to_cpu(uint16_t val) {
37 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
38 val = bswap_16(val);
39 return val;
40}
41
42
43static uint32_t file32_to_cpu(uint32_t val) {
44 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
45 val = bswap_32(val);
46 return val;
47}
48
49
50static uint64_t file64_to_cpu(uint64_t val) {
51 if (ehdr.e_ident[EI_DATA] != ELFDATANATIVE)
52 val = bswap_64(val);
53 return val;
54}
55
56
57// return 0 if error
58static long unsigned int read_elf32(int fd) {
59 Elf32_Ehdr ehdr32;
60 ssize_t ret, i;
61
62 ret = pread(fd, &ehdr32, sizeof(ehdr32), 0);
63 if (ret < 0 || (size_t)ret != sizeof(ehdr))
64 return 0;
65
66 ehdr.e_shoff = file32_to_cpu(ehdr32.e_shoff);
67 ehdr.e_shentsize = file16_to_cpu(ehdr32.e_shentsize);
68 ehdr.e_shnum = file16_to_cpu(ehdr32.e_shnum);
69
70 return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
71}
72
73
74// return 0 if error
75static long unsigned int read_elf64(int fd) {
76 Elf64_Ehdr ehdr64;
77 ssize_t ret, i;
78
79 ret = pread(fd, &ehdr64, sizeof(ehdr64), 0);
80 if (ret < 0 || (size_t)ret != sizeof(ehdr))
81 return 0;
82
83 ehdr.e_shoff = file64_to_cpu(ehdr64.e_shoff);
84 ehdr.e_shentsize = file16_to_cpu(ehdr64.e_shentsize);
85 ehdr.e_shnum = file16_to_cpu(ehdr64.e_shnum);
86
87 return(ehdr.e_shoff + (ehdr.e_shentsize * ehdr.e_shnum));
88}
89
90
91// return 0 if error
92// return 0 if this is not an appimgage2 file
93long unsigned int appimage2_size(const char *fname) {
94/* TODO, FIXME: This assumes that the section header table (SHT) is
95the last part of the ELF. This is usually the case but
96it could also be that the last section is the last part
97of the ELF. This should be checked for.
98*/
99 ssize_t ret;
100 int fd;
101 long unsigned int size = 0;
102
103 fd = open(fname, O_RDONLY);
104 if (fd < 0)
105 return 0;
106
107 ret = pread(fd, ehdr.e_ident, EI_NIDENT, 0);
108 if (ret != EI_NIDENT)
109 goto getout;
110
111 if ((ehdr.e_ident[EI_DATA] != ELFDATA2LSB) &&
112 (ehdr.e_ident[EI_DATA] != ELFDATA2MSB))
113 goto getout;
114
115 if(ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
116 size = read_elf32(fd);
117 }
118 else if(ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
119 size = read_elf64(fd);
120 }
121 else {
122 goto getout;
123 }
124 if (size == 0)
125 goto getout;
126
127
128 // look for a LZMA header at this location
129 unsigned char buf[4];
130 ret = pread(fd, buf, 4, size);
131 if (ret != 4) {
132 size = 0;
133 goto getout;
134 }
135 if (memcmp(buf, "hsqs", 4) != 0)
136 size = 0;
137
138getout:
139 close(fd);
140 return size;
141}
142
143
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index dafa5919c..9a9bb1ae7 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -681,8 +681,12 @@ void appimage_set(const char *appimage_path);
681void appimage_clear(void); 681void appimage_clear(void);
682const char *appimage_getdir(void); 682const char *appimage_getdir(void);
683 683
684// appimage_size.c
685long unsigned int appimage2_size(const char *fname);
686
684// cmdline.c 687// cmdline.c
685void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); 688void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index);
686 689
690
687#endif 691#endif
688 692