aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2021-10-05 16:21:09 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2021-10-05 16:45:16 +0200
commit84d5469a40bdc65aa5607d11a9060bb710bfd9b9 (patch)
tree31abf79ee6e0117ec71e53b210ab094a6441981f
parentMerge pull request #4585 from smitsohu/euid (diff)
downloadfirejail-84d5469a40bdc65aa5607d11a9060bb710bfd9b9.tar.gz
firejail-84d5469a40bdc65aa5607d11a9060bb710bfd9b9.tar.zst
firejail-84d5469a40bdc65aa5607d11a9060bb710bfd9b9.zip
simplify recursive remounting
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs.c38
-rw-r--r--src/firejail/mountinfo.c40
3 files changed, 30 insertions, 50 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 2a7d88575..e1ba8f48a 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -563,7 +563,7 @@ typedef struct {
563 563
564// mountinfo.c 564// mountinfo.c
565MountData *get_last_mount(void); 565MountData *get_last_mount(void);
566int get_mount_id(const char *path); 566int get_mount_id(int fd);
567char **build_mount_array(const int mount_id, const char *path); 567char **build_mount_array(const int mount_id, const char *path);
568 568
569// fs_var.c 569// fs_var.c
diff --git a/src/firejail/fs.c b/src/firejail/fs.c
index 6d01b5e5d..3144156a3 100644
--- a/src/firejail/fs.c
+++ b/src/firejail/fs.c
@@ -633,34 +633,30 @@ out:
633} 633}
634 634
635// remount recursively; requires a resolved path 635// remount recursively; requires a resolved path
636static void fs_remount_rec(const char *dir, OPERATION op) { 636static void fs_remount_rec(const char *path, OPERATION op) {
637 EUID_ASSERT(); 637 EUID_ASSERT();
638 assert(dir); 638 assert(op < OPERATION_MAX);
639 assert(path);
639 640
640 struct stat s; 641 // no need to search /proc/self/mountinfo for submounts if not a directory
641 if (stat(dir, &s) != 0) 642 int fd = open(path, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
642 return; 643 if (fd < 0) {
643 if (!S_ISDIR(s.st_mode)) { 644 fs_remount_simple(path, op);
644 // no need to search in /proc/self/mountinfo for submounts if not a directory
645 fs_remount_simple(dir, op);
646 return; 645 return;
647 } 646 }
648 // get mount point of the directory 647
649 int mountid = get_mount_id(dir); 648 // get mount id of the directory
650 if (mountid == -1) 649 int mountid = get_mount_id(fd);
651 return; 650 close(fd);
652 if (mountid == -2) { 651 if (mountid < 0) {
653 // falling back to a simple remount on old kernels 652 // falling back to a simple remount
654 static int mount_warning = 0; 653 fwarning("%s %s not applied recursively\n", opstr[op], path);
655 if (!mount_warning) { 654 fs_remount_simple(path, op);
656 fwarning("read-only, read-write and noexec options are not applied recursively\n");
657 mount_warning = 1;
658 }
659 fs_remount_simple(dir, op);
660 return; 655 return;
661 } 656 }
657
662 // build array with all mount points that need to get remounted 658 // build array with all mount points that need to get remounted
663 char **arr = build_mount_array(mountid, dir); 659 char **arr = build_mount_array(mountid, path);
664 assert(arr); 660 assert(arr);
665 // remount 661 // remount
666 char **tmp = arr; 662 char **tmp = arr;
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c
index 64a94bd84..f1eb9c924 100644
--- a/src/firejail/mountinfo.c
+++ b/src/firejail/mountinfo.c
@@ -151,47 +151,31 @@ MountData *get_last_mount(void) {
151 return &mdata; 151 return &mdata;
152} 152}
153 153
154// Extract the mount id from /proc/self/fdinfo and return it. 154// Needs kernel 3.15 or better
155int get_mount_id(const char *path) { 155int get_mount_id(int fd) {
156 EUID_ASSERT(); 156 int rv = -1;
157 assert(path);
158
159 int fd = open(path, O_PATH|O_CLOEXEC);
160 if (fd == -1)
161 return -1;
162 157
163 char *fdinfo; 158 char *proc;
164 if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1) 159 if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1)
165 errExit("asprintf"); 160 errExit("asprintf");
166 EUID_ROOT(); 161 EUID_ROOT();
167 FILE *fp = fopen(fdinfo, "re"); 162 FILE *fp = fopen(proc, "re");
168 EUID_USER(); 163 EUID_USER();
169 free(fdinfo);
170 if (!fp) 164 if (!fp)
171 goto errexit; 165 goto errexit;
172 166
173 // read the file
174 char buf[MAX_BUF]; 167 char buf[MAX_BUF];
175 if (fgets(buf, MAX_BUF, fp) == NULL) 168 while (fgets(buf, MAX_BUF, fp)) {
176 goto errexit;
177 do {
178 if (strncmp(buf, "mnt_id:", 7) == 0) { 169 if (strncmp(buf, "mnt_id:", 7) == 0) {
179 char *ptr = buf + 7; 170 if (sscanf(buf + 7, "%d", &rv) != 1)
180 while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
181 ptr++;
182 }
183 if (*ptr == '\0')
184 goto errexit; 171 goto errexit;
185 fclose(fp); 172 break;
186 close(fd);
187 return atoi(ptr);
188 } 173 }
189 } while (fgets(buf, MAX_BUF, fp)); 174 }
190 175
191 // fallback, kernels older than 3.15 don't expose the mount id in this place 176 free(proc);
192 fclose(fp); 177 fclose(fp);
193 close(fd); 178 return rv;
194 return -2;
195 179
196errexit: 180errexit:
197 fprintf(stderr, "Error: cannot read proc file\n"); 181 fprintf(stderr, "Error: cannot read proc file\n");