Skip to content

Commit d66df36

Browse files
spiiroinkmk3
authored andcommitted
modif: populate /run/firejail while holding flock
There are reports of firejail sandboxed applications occasionally taking a long time (12 seconds) to start up. When this happens, it affects all sandboxed applications until the device is rebooted. The reason for the slowdown seems to be a timing hazard in the way remounts under /run/firejail are handled. This gets triggered when multiple firejail processes are launched in parallel as part of user session bring up and results in some, dozens, hundreds, or even thousands of stray /run/firejail/xxx mounts. The amount of mount points then affects every mount operation that is done during sandbox filesystem construction. To stop this from happening, arrange it so that only one firejail process at time is inspecting and/or modifying mountpoints under /run/firejail by doing: 1. Create /run/firejail directory (without locking) 2. Create and obtain a lock for /run/firejail/firejail-run.lock 3. Setup files, directories and mounts under /run/firejail 4. Release /run/firejail/firejail-run.lock
1 parent 1ed54ba commit d66df36

File tree

4 files changed

+23
-8
lines changed

4 files changed

+23
-8
lines changed

src/firejail/chroot.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,10 @@ void fs_chroot(const char *rootdir) {
273273
errExit("mounting /proc");
274274

275275
// create all other /run/firejail files and directories
276-
preproc_build_firejail_dir();
276+
preproc_build_firejail_dir_unlocked();
277+
preproc_lock_firejail_dir();
278+
preproc_build_firejail_dir_locked();
279+
preproc_unlock_firejail_dir();
277280

278281
// update /var directory in order to support multiple sandboxes running on the same root directory
279282
// if (!arg_private_dev)

src/firejail/firejail.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ void preproc_lock_firejail_dir(void);
435435
void preproc_unlock_firejail_dir(void);
436436
void preproc_lock_firejail_network_dir(void);
437437
void preproc_unlock_firejail_network_dir(void);
438-
void preproc_build_firejail_dir(void);
438+
void preproc_build_firejail_dir_unlocked(void);
439+
void preproc_build_firejail_dir_locked(void);
439440
void preproc_mount_mnt_dir(void);
440441
void preproc_clean_run(void);
441442

src/firejail/main.c

+5-5
Original file line numberDiff line numberDiff line change
@@ -1166,13 +1166,13 @@ int main(int argc, char **argv, char **envp) {
11661166
#endif
11671167

11681168
// build /run/firejail directory structure
1169-
preproc_build_firejail_dir();
1169+
preproc_build_firejail_dir_unlocked();
1170+
preproc_lock_firejail_dir();
1171+
preproc_build_firejail_dir_locked();
11701172
const char *container_name = env_get("container");
1171-
if (!container_name || strcmp(container_name, "firejail")) {
1172-
preproc_lock_firejail_dir();
1173+
if (!container_name || strcmp(container_name, "firejail"))
11731174
preproc_clean_run();
1174-
preproc_unlock_firejail_dir();
1175-
}
1175+
preproc_unlock_firejail_dir();
11761176

11771177
delete_run_files(getpid());
11781178
atexit(clear_atexit);

src/firejail/preproc.c

+12-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,10 @@ void preproc_unlock_firejail_network_dir(void) {
105105
}
106106

107107
// build /run/firejail directory
108-
void preproc_build_firejail_dir(void) {
108+
//
109+
// Note: This creates the base directory of the rundir lockfile;
110+
// it should be called before preproc_lock_firejail_dir().
111+
void preproc_build_firejail_dir_unlocked(void) {
109112
struct stat s;
110113

111114
// CentOS 6 doesn't have /run directory
@@ -114,6 +117,14 @@ void preproc_build_firejail_dir(void) {
114117
}
115118

116119
create_empty_dir_as_root(RUN_FIREJAIL_DIR, 0755);
120+
}
121+
122+
// build directory hierarchy under /run/firejail
123+
//
124+
// Note: Remounts have timing hazards. This function should
125+
// only be called after acquiring the directory lock via
126+
// preproc_lock_firejail_dir().
127+
void preproc_build_firejail_dir_locked(void) {
117128
create_empty_dir_as_root(RUN_FIREJAIL_NETWORK_DIR, 0755);
118129
create_empty_dir_as_root(RUN_FIREJAIL_BANDWIDTH_DIR, 0755);
119130
create_empty_dir_as_root(RUN_FIREJAIL_NAME_DIR, 0755);

0 commit comments

Comments
 (0)