aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/mountinfo.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/mountinfo.c')
-rw-r--r--src/firejail/mountinfo.c71
1 files changed, 45 insertions, 26 deletions
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index 64a94bd84..304f80eee 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -19,6 +19,7 @@
19*/ 19*/
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include <errno.h>
22 23
23#include <fcntl.h> 24#include <fcntl.h>
24#ifndef O_PATH 25#ifndef O_PATH
@@ -151,53 +152,71 @@ MountData *get_last_mount(void) {
151 return &mdata; 152 return &mdata;
152} 153}
153 154
154// Extract the mount id from /proc/self/fdinfo and return it. 155// Returns mount id, or -1 if fd refers to a procfs or sysfs file
155int get_mount_id(const char *path) { 156static int get_mount_id_from_handle(int fd) {
156 EUID_ASSERT(); 157 EUID_ASSERT();
157 assert(path);
158 158
159 int fd = open(path, O_PATH|O_CLOEXEC); 159 char *proc;
160 if (fd == -1) 160 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
161 return -1; 161 errExit("asprintf");
162 struct file_handle *fh = malloc(sizeof *fh);
163 if (!fh)
164 errExit("malloc");
165 fh->handle_bytes = 0;
166
167 int rv = -1;
168 int tmp;
169 if (name_to_handle_at(-1, proc, fh, &tmp, AT_SYMLINK_FOLLOW) != -1) {
170 fprintf(stderr, "Error: unexpected result from name_to_handle_at\n");
171 exit(1);
172 }
173 if (errno == EOVERFLOW && fh->handle_bytes)
174 rv = tmp;
175
176 free(proc);
177 free(fh);
178 return rv;
179}
180
181// Returns mount id, or -1 on kernels < 3.15
182static int get_mount_id_from_fdinfo(int fd) {
183 EUID_ASSERT();
184 int rv = -1;
162 185
163 char *fdinfo; 186 char *proc;
164 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 187 if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1)
165 errExit("asprintf"); 188 errExit("asprintf");
166 EUID_ROOT(); 189 EUID_ROOT();
167 FILE *fp = fopen(fdinfo, "re"); 190 FILE *fp = fopen(proc, "re");
168 EUID_USER(); 191 EUID_USER();
169 free(fdinfo);
170 if (!fp) 192 if (!fp)
171 goto errexit; 193 goto errexit;
172 194
173 // read the file
174 char buf[MAX_BUF]; 195 char buf[MAX_BUF];
175 if (fgets(buf, MAX_BUF, fp) == NULL) 196 while (fgets(buf, MAX_BUF, fp)) {
176 goto errexit;
177 do {
178 if (strncmp(buf, "mnt_id:", 7) == 0) { 197 if (strncmp(buf, "mnt_id:", 7) == 0) {
179 char *ptr = buf + 7; 198 if (sscanf(buf + 7, "%d", &rv) != 1)
180 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
181 ptr++;
182 }
183 if (*ptr == '\0')
184 goto errexit; 199 goto errexit;
185 fclose(fp); 200 break;
186 close(fd);
187 return atoi(ptr);
188 } 201 }
189 } while (fgets(buf, MAX_BUF, fp)); 202 }
190 203
191 // fallback, kernels older than 3.15 don't expose the mount id in this place 204 free(proc);
192 fclose(fp); 205 fclose(fp);
193 close(fd); 206 return rv;
194 return -2;
195 207
196errexit: 208errexit:
197 fprintf(stderr, "Error: cannot read proc file\n"); 209 fprintf(stderr, "Error: cannot read proc file\n");
198 exit(1); 210 exit(1);
199} 211}
200 212
213int get_mount_id(int fd) {
214 int rv = get_mount_id_from_fdinfo(fd);
215 if (rv < 0)
216 rv = get_mount_id_from_handle(fd);
217 return rv;
218}
219
201// Check /proc/self/mountinfo if path contains any mounts points. 220// Check /proc/self/mountinfo if path contains any mounts points.
202// Returns an array that can be iterated over for recursive remounting. 221// Returns an array that can be iterated over for recursive remounting.
203char **build_mount_array(const int mount_id, const char *path) { 222char **build_mount_array(const int mount_id, const char *path) {