aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/mountinfo.c
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-11-04 19:03:49 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2018-11-04 19:03:49 +0100
commit35d2aec567c0e9c9b5c79678b1dc762916d5492c (patch)
tree40335d4a7320d830cc5f1717fb8afd6e95532330 /src/firejail/mountinfo.c
parentmount appimages nodev,nosuid (diff)
downloadfirejail-35d2aec567c0e9c9b5c79678b1dc762916d5492c.tar.gz
firejail-35d2aec567c0e9c9b5c79678b1dc762916d5492c.tar.zst
firejail-35d2aec567c0e9c9b5c79678b1dc762916d5492c.zip
recursive remounts: add fallback for old kernels, some improvements
* vanilla kernels before 3.15 don't expose a mount id in /proc/pid/fdinfo files. This is still relevant on Ubuntu 14.04 with 3.13 kernel, CentOS 7 doesn't have this problem. In this case fall back to simple a remount and print a warning. * drop euid switching as it doesn't really serve a purpose here (paths are not opened in reading or writing mode, and we are not doing anything with it) and potentially causes problems when suid programs are sandboxed * more rigorous error handling
Diffstat (limited to 'src/firejail/mountinfo.c')
-rw-r--r--src/firejail/mountinfo.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index b7e6c6fdd..ab1e501a7 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -153,7 +153,6 @@ MountData *get_last_mount(void) {
153 153
154// Extract the mount id from /proc/self/fdinfo and return it. 154// Extract the mount id from /proc/self/fdinfo and return it.
155int get_mount_id(const char *path) { 155int get_mount_id(const char *path) {
156 EUID_ASSERT();
157 int fd = open(path, O_PATH|O_CLOEXEC); 156 int fd = open(path, O_PATH|O_CLOEXEC);
158 if (fd == -1) 157 if (fd == -1)
159 return -1; 158 return -1;
@@ -161,32 +160,41 @@ int get_mount_id(const char *path) {
161 char *fdinfo; 160 char *fdinfo;
162 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 161 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1)
163 errExit("asprintf"); 162 errExit("asprintf");
164 EUID_ROOT();
165 FILE *fp = fopen(fdinfo, "re"); 163 FILE *fp = fopen(fdinfo, "re");
166 EUID_USER(); 164 if (!fp) {
167 if (!fp) 165 perror("fopen");
168 goto errexit; 166 fprintf(stderr, "Error: cannot open %s\n", fdinfo);
167 exit(1);
168 }
169 169
170 // read the file 170 // read the file
171 char buf[MAX_BUF]; 171 char buf[MAX_BUF];
172 while (fgets(buf, MAX_BUF, fp)) { 172 if (fgets(buf, MAX_BUF, fp) == NULL) {
173 fprintf(stderr, "Error: cannot read %s\n", fdinfo);
174 exit(1);
175 }
176 do {
173 if (strncmp(buf, "mnt_id:", 7) == 0) { 177 if (strncmp(buf, "mnt_id:", 7) == 0) {
174 char *ptr = buf + 7; 178 char *ptr = buf + 7;
175 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) { 179 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
176 ptr++; 180 ptr++;
177 } 181 }
178 if (*ptr == '\0') 182 if (*ptr == '\0') {
179 goto errexit; 183 fprintf(stderr, "Error: cannot read %s\n", fdinfo);
184 exit(1);
185 }
180 fclose(fp); 186 fclose(fp);
181 close(fd); 187 close(fd);
182 free(fdinfo); 188 free(fdinfo);
183 return atoi(ptr); 189 return atoi(ptr);
184 } 190 }
185 } 191 } while (fgets(buf, MAX_BUF, fp));
186 192
187errexit: 193 // fallback, kernels older than 3.15 don't expose the mount id in this place
188 fprintf(stderr, "Error: cannot read %s\n", fdinfo); 194 fclose(fp);
189 exit(1); 195 close(fd);
196 free(fdinfo);
197 return -2;
190} 198}
191 199
192// Return array with all paths that might need a remount. 200// Return array with all paths that might need a remount.
@@ -208,7 +216,11 @@ char **build_mount_array(const int mountid, const char *path) {
208 // read /proc/self/mountinfo 216 // read /proc/self/mountinfo
209 size_t pathlen = strlen(path); 217 size_t pathlen = strlen(path);
210 int found = 0; 218 int found = 0;
211 while (fgets(mbuf, MAX_BUF, fp)) { 219 if (fgets(mbuf, MAX_BUF, fp) == NULL) {
220 fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n");
221 exit(1);
222 }
223 do {
212 // find mount point with mount id 224 // find mount point with mount id
213 if (!found) { 225 if (!found) {
214 parse_line(mbuf, &mdata); 226 parse_line(mbuf, &mdata);
@@ -230,7 +242,8 @@ char **build_mount_array(const int mountid, const char *path) {
230 else 242 else
231 continue; 243 continue;
232 } 244 }
233 // from here on add all mount points below path 245 // from here on add all mount points below path,
246 // don't remount blacklisted paths
234 parse_line(mbuf, &mdata); 247 parse_line(mbuf, &mdata);
235 if (strncmp(mdata.dir, path, pathlen) == 0 && 248 if (strncmp(mdata.dir, path, pathlen) == 0 &&
236 mdata.dir[pathlen] == '/' && 249 mdata.dir[pathlen] == '/' &&
@@ -248,7 +261,8 @@ char **build_mount_array(const int mountid, const char *path) {
248 errExit("strdup"); 261 errExit("strdup");
249 cnt++; 262 cnt++;
250 } 263 }
251 } 264 } while (fgets(mbuf, MAX_BUF, fp));
265
252 if (cnt == size) { 266 if (cnt == size) {
253 size++; 267 size++;
254 rv = realloc(rv, size * sizeof(*rv)); 268 rv = realloc(rv, size * sizeof(*rv));