diff options
author | netblue30 <netblue30@yahoo.com> | 2016-10-23 09:02:39 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2016-10-23 09:02:39 -0400 |
commit | 4bcab4f4e6a53f2b7d402092983ee0d71d555259 (patch) | |
tree | b3ceecdf7c1dfcca0ec8bef6adaf58c9dd9848fe /src | |
parent | starting 0.9.45 devel version (diff) | |
download | firejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.tar.gz firejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.tar.zst firejail-4bcab4f4e6a53f2b7d402092983ee0d71d555259.zip |
appimage type 2 support
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/appimage.c | 29 | ||||
-rw-r--r-- | src/firejail/appimage_size.c | 143 | ||||
-rw-r--r-- | src/firejail/firejail.h | 4 |
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 | /* | ||
2 | Compile with: | ||
3 | gcc elfsize.c -o elfsize | ||
4 | Example: | ||
5 | ls -l 126584 | ||
6 | Calculation using the values also reported by readelf -h: | ||
7 | Start of section headers e_shoff 124728 | ||
8 | Size of section headers e_shentsize 64 | ||
9 | Number of section headers e_shnum 29 | ||
10 | e_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 | |||
23 | typedef Elf32_Nhdr Elf_Nhdr; | ||
24 | |||
25 | static Elf64_Ehdr ehdr; | ||
26 | static 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 | |||
36 | static 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 | |||
43 | static 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 | |||
50 | static 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 | ||
58 | static 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 | ||
75 | static 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 | ||
93 | long unsigned int appimage2_size(const char *fname) { | ||
94 | /* TODO, FIXME: This assumes that the section header table (SHT) is | ||
95 | the last part of the ELF. This is usually the case but | ||
96 | it could also be that the last section is the last part | ||
97 | of 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 | |||
138 | getout: | ||
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); | |||
681 | void appimage_clear(void); | 681 | void appimage_clear(void); |
682 | const char *appimage_getdir(void); | 682 | const char *appimage_getdir(void); |
683 | 683 | ||
684 | // appimage_size.c | ||
685 | long unsigned int appimage2_size(const char *fname); | ||
686 | |||
684 | // cmdline.c | 687 | // cmdline.c |
685 | void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); | 688 | void build_cmdline(char **command_line, char **window_title, int argc, char **argv, int index); |
686 | 689 | ||
690 | |||
687 | #endif | 691 | #endif |
688 | 692 | ||