aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2020-08-27 22:47:24 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2020-08-27 22:47:24 +0200
commitad61473afe2b9aee44330595e4874d24ff93836e (patch)
treea496268c803d1ccca51bc7d19b663a42ba8a16ac
parentchroot: little tweaks (diff)
downloadfirejail-ad61473afe2b9aee44330595e4874d24ff93836e.tar.gz
firejail-ad61473afe2b9aee44330595e4874d24ff93836e.tar.zst
firejail-ad61473afe2b9aee44330595e4874d24ff93836e.zip
expose pulseaudio in chroot if FIREJAIL_CHROOT_PULSE is set
issue #3568
-rw-r--r--src/firejail/chroot.c61
1 files changed, 50 insertions, 11 deletions
diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c
index 26a91faba..7411a2b48 100644
--- a/src/firejail/chroot.c
+++ b/src/firejail/chroot.c
@@ -60,27 +60,29 @@ errout:
60 exit(1); 60 exit(1);
61} 61}
62 62
63// copy /etc/resolv.conf in chroot directory 63// copy /etc/resolv.conf or /etc/machine-id in chroot directory
64static void copy_resolvconf(int parentfd) { 64static void update_file(int parentfd, const char *fname) {
65 int in = open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC); 65 assert(fname);
66 assert(fname[0] == '/');
67
68 int in = open(fname, O_RDONLY|O_CLOEXEC);
66 if (in == -1) 69 if (in == -1)
67 goto errout; 70 goto errout;
68 struct stat src; 71 struct stat src;
69 if (fstat(in, &src) == -1) 72 if (fstat(in, &src) == -1)
70 errExit("fstat"); 73 errExit("fstat");
71 // try to detect if resolv.conf has been bind mounted into the chroot 74 // try to detect if file has been bind mounted into the chroot
72 // do nothing in this case in order to not unlink the real file
73 struct stat dst; 75 struct stat dst;
74 if (fstatat(parentfd, "etc/resolv.conf", &dst, 0) == 0) { 76 if (fstatat(parentfd, fname+1, &dst, 0) == 0) {
75 if (src.st_dev == dst.st_dev && src.st_ino == dst.st_ino) { 77 if (src.st_dev == dst.st_dev && src.st_ino == dst.st_ino) {
76 close(in); 78 close(in);
77 return; 79 return;
78 } 80 }
79 } 81 }
80 if (arg_debug) 82 if (arg_debug)
81 printf("Updating /etc/resolv.conf in chroot\n"); 83 printf("Updating %s in chroot\n", fname);
82 unlinkat(parentfd, "etc/resolv.conf", 0); 84 unlinkat(parentfd, fname+1, 0);
83 int out = openat(parentfd, "etc/resolv.conf", O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); 85 int out = openat(parentfd, fname+1, O_WRONLY|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
84 if (out == -1) { 86 if (out == -1) {
85 close(in); 87 close(in);
86 goto errout; 88 goto errout;
@@ -92,7 +94,7 @@ static void copy_resolvconf(int parentfd) {
92 return; 94 return;
93 95
94errout: 96errout:
95 fwarning("/etc/resolv.conf not initialized\n"); 97 fwarning("%s not initialized\n", fname);
96} 98}
97 99
98// exit if error 100// exit if error
@@ -187,6 +189,43 @@ void fs_chroot(const char *rootdir) {
187 errExit("mkdir"); 189 errExit("mkdir");
188 check_subdir(parentfd, "run", 1); 190 check_subdir(parentfd, "run", 1);
189 191
192 // pulseaudio; only support for default directory /run/user/$UID/pulse
193 if (getenv("FIREJAIL_CHROOT_PULSE")) {
194 char *pulse;
195 if (asprintf(&pulse, "%s/run/user/%d/pulse", cfg.chrootdir, getuid()) == -1)
196 errExit("asprintf");
197 char *orig_pulse = pulse + strlen(cfg.chrootdir);
198
199 if (arg_debug)
200 printf("Mounting %s on chroot %s\n", orig_pulse, orig_pulse);
201 int src = safe_fd(orig_pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
202 if (src == -1) {
203 fprintf(stderr, "Error: cannot open %s\n", orig_pulse);
204 exit(1);
205 }
206 int dst = safe_fd(pulse, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
207 if (dst == -1) {
208 fprintf(stderr, "Error: cannot open %s\n", pulse);
209 exit(1);
210 }
211 free(pulse);
212
213 char *proc_src, *proc_dst;
214 if (asprintf(&proc_src, "/proc/self/fd/%d", src) == -1)
215 errExit("asprintf");
216 if (asprintf(&proc_dst, "/proc/self/fd/%d", dst) == -1)
217 errExit("asprintf");
218 if (mount(proc_src, proc_dst, NULL, MS_BIND|MS_REC, NULL) < 0)
219 errExit("mount bind");
220 free(proc_src);
221 free(proc_dst);
222 close(src);
223 close(dst);
224
225 // update /etc/machine-id in chroot
226 update_file(parentfd, "/etc/machine-id");
227 }
228
190 // create /run/firejail directory in chroot 229 // create /run/firejail directory in chroot
191 if (mkdirat(parentfd, RUN_FIREJAIL_DIR+1, 0755) == -1 && errno != EEXIST) 230 if (mkdirat(parentfd, RUN_FIREJAIL_DIR+1, 0755) == -1 && errno != EEXIST)
192 errExit("mkdir"); 231 errExit("mkdir");
@@ -223,7 +262,7 @@ void fs_chroot(const char *rootdir) {
223 close(fd); 262 close(fd);
224 263
225 // update chroot resolv.conf 264 // update chroot resolv.conf
226 copy_resolvconf(parentfd); 265 update_file(parentfd, "/etc/resolv.conf");
227 266
228#ifdef HAVE_GCOV 267#ifdef HAVE_GCOV
229 __gcov_flush(); 268 __gcov_flush();