Skip to content

Commit

Permalink
simplify recursive remounting
Browse files Browse the repository at this point in the history
  • Loading branch information
smitsohu committed Oct 5, 2021
1 parent d2389ec commit 84d5469
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ typedef struct {

// mountinfo.c
MountData *get_last_mount(void);
int get_mount_id(const char *path);
int get_mount_id(int fd);
char **build_mount_array(const int mount_id, const char *path);

// fs_var.c
Expand Down
38 changes: 17 additions & 21 deletions src/firejail/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,34 +633,30 @@ static void fs_remount_simple(const char *path, OPERATION op) {
}

// remount recursively; requires a resolved path
static void fs_remount_rec(const char *dir, OPERATION op) {
static void fs_remount_rec(const char *path, OPERATION op) {
EUID_ASSERT();
assert(dir);
assert(op < OPERATION_MAX);
assert(path);

struct stat s;
if (stat(dir, &s) != 0)
return;
if (!S_ISDIR(s.st_mode)) {
// no need to search in /proc/self/mountinfo for submounts if not a directory
fs_remount_simple(dir, op);
// no need to search /proc/self/mountinfo for submounts if not a directory
int fd = open(path, O_PATH|O_DIRECTORY|O_|O_CLOEXEC);
if (fd < 0) {
fs_remount_simple(path, op);
return;
}
// get mount point of the directory
int mountid = get_mount_id(dir);
if (mountid == -1)
return;
if (mountid == -2) {
// falling back to a simple remount on old kernels
static int mount_warning = 0;
if (!mount_warning) {
fwarning("read-only, read-write and noexec options are not applied recursively\n");
mount_warning = 1;
}
fs_remount_simple(dir, op);

// get mount id of the directory
int mountid = get_mount_id(fd);
close(fd);
if (mountid < 0) {
// falling back to a simple remount
fwarning("%s %s not applied recursively\n", opstr[op], path);
fs_remount_simple(path, op);
return;
}

// build array with all mount points that need to get remounted
char **arr = build_mount_array(mountid, dir);
char **arr = build_mount_array(mountid, path);
assert(arr);
// remount
char **tmp = arr;
Expand Down
40 changes: 12 additions & 28 deletions src/firejail/mountinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,47 +151,31 @@ MountData *get_last_mount(void) {
return &mdata;
}

// Extract the mount id from /proc/self/fdinfo and return it.
int get_mount_id(const char *path) {
EUID_ASSERT();
assert(path);

int fd = open(path, O_PATH|O_CLOEXEC);
if (fd == -1)
return -1;
// Needs kernel 3.15 or better
int get_mount_id(int fd) {
int rv = -1;

char *fdinfo;
if (asprintf(&fdinfo, "/proc/self/fdinfo/%d", fd) == -1)
char *proc;
if (asprintf(&proc, "/proc/self/fdinfo/%d", fd) == -1)
errExit("asprintf");
EUID_ROOT();
FILE *fp = fopen(fdinfo, "re");
FILE *fp = fopen(proc, "re");
EUID_USER();
free(fdinfo);
if (!fp)
goto errexit;

// read the file
char buf[MAX_BUF];
if (fgets(buf, MAX_BUF, fp) == NULL)
goto errexit;
do {
while (fgets(buf, MAX_BUF, fp)) {
if (strncmp(buf, "mnt_id:", 7) == 0) {
char *ptr = buf + 7;
while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) {
ptr++;
}
if (*ptr == '\0')
if (sscanf(buf + 7, "%d", &rv) != 1)
goto errexit;
fclose(fp);
close(fd);
return atoi(ptr);
break;
}
} while (fgets(buf, MAX_BUF, fp));
}

// fallback, kernels older than 3.15 don't expose the mount id in this place
free(proc);
fclose(fp);
close(fd);
return -2;
return rv;

errexit:
fprintf(stderr, "Error: cannot read proc file\n");
Expand Down

0 comments on commit 84d5469

Please sign in to comment.