aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-12-13 03:12:34 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2018-12-13 03:12:34 +0100
commit0d8655e4da43ce0ed1ed6cc4925c1f994f65215c (patch)
treedcf3332410d75b67f7952e9ebba32a71ddc89d3d
parentpulseaudio: use env variable fallback in more cases (diff)
downloadfirejail-0d8655e4da43ce0ed1ed6cc4925c1f994f65215c.tar.gz
firejail-0d8655e4da43ce0ed1ed6cc4925c1f994f65215c.tar.zst
firejail-0d8655e4da43ce0ed1ed6cc4925c1f994f65215c.zip
Revert "pulseaudio: use env variable fallback in more cases"
This reverts commit 93779cb9cd0d098cd3587e2f795200d98e3af1ee. That commit removed restrictions, but also added new inconsistencies. Starting again from the previous state is easier than evolving the current state, hence reverting the commit.
-rw-r--r--src/firejail/pulseaudio.c170
1 files changed, 110 insertions, 60 deletions
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index ce1692ba2..4ddaba7ed 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -102,74 +102,124 @@ void pulseaudio_init(void) {
102 if (set_perms(RUN_PULSE_DIR, getuid(), getgid(), 0700)) 102 if (set_perms(RUN_PULSE_DIR, getuid(), getgid(), 0700))
103 errExit("set_perms"); 103 errExit("set_perms");
104 104
105 // create ~/.config directory if necessary 105 // create ~/.config/pulse directory if not present
106 char *homeusercfg; 106 char *dir1;
107 if (asprintf(&homeusercfg, "%s/.config", cfg.homedir) == -1) 107 if (asprintf(&dir1, "%s/.config", cfg.homedir) == -1)
108 errExit("asprintf"); 108 errExit("asprintf");
109 create_empty_dir_as_user(homeusercfg, 0700); 109 if (lstat(dir1, &s) == -1) {
110 // set environment variable if creating ~/.config wasn't successful or if it is not a directory owned by the user 110 pid_t child = fork();
111 if (lstat(homeusercfg, &s) != 0 || !S_ISDIR(s.st_mode) || s.st_uid != getuid()) { 111 if (child < 0)
112 if (arg_debug) 112 errExit("fork");
113 printf("Setting PULSE_CLIENTCONFIG environment variable\n"); 113 if (child == 0) {
114 if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) 114 // drop privileges
115 errExit("setenv"); 115 drop_privs(0);
116 free(homeusercfg); 116
117 free(pulsecfg); 117 int rv = mkdir(dir1, 0755);
118 return; 118 if (rv == 0) {
119 if (chmod(dir1, 0755))
120 {;} // do nothing
121 }
122#ifdef HAVE_GCOV
123 __gcov_flush();
124#endif
125 _exit(0);
126 }
127 // wait for the child to finish
128 waitpid(child, NULL, 0);
129 fs_logger2("create", dir1);
119 } 130 }
120 free(homeusercfg); 131 else {
132 // we expect a user owned directory
133 if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) {
134 if (S_ISLNK(s.st_mode))
135 fprintf(stderr, "Error: user .config is a symbolic link\n");
136 else
137 fprintf(stderr, "Error: user .config is not a directory owned by the current user\n");
138 exit(1);
139 }
140 }
141 free(dir1);
142
143 if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1)
144 errExit("asprintf");
145 if (lstat(dir1, &s) == -1) {
146 pid_t child = fork();
147 if (child < 0)
148 errExit("fork");
149 if (child == 0) {
150 // drop privileges
151 drop_privs(0);
152
153 int rv = mkdir(dir1, 0700);
154 if (rv == 0) {
155 if (chmod(dir1, 0700))
156 {;} // do nothing
157 }
158#ifdef HAVE_GCOV
159 __gcov_flush();
160#endif
161 _exit(0);
162 }
163 // wait for the child to finish
164 waitpid(child, NULL, 0);
165 fs_logger2("create", dir1);
166 }
167 else {
168 // we expect a user owned directory
169 if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) {
170 if (S_ISLNK(s.st_mode))
171 fprintf(stderr, "Error: user .config/pulse is a symbolic link\n");
172 else
173 fprintf(stderr, "Error: user .config/pulse is not a directory owned by the current user\n");
174 exit(1);
175 }
176 }
177 free(dir1);
121 178
122 // create ~/.config/pulse directory if necessary 179 // if we have ~/.config/pulse mount the new directory, else set environment variable.
180 char *homeusercfg;
123 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1) 181 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1)
124 errExit("asprintf"); 182 errExit("asprintf");
125 create_empty_dir_as_user(homeusercfg, 0700); 183 if (stat(homeusercfg, &s) == 0) {
126 // set environment variable if creating ~/.config/pulse wasn't successful or if it is not a directory owned by the user 184 // get a file descriptor for ~/.config/pulse, fails if there is any symlink
127 if (lstat(homeusercfg, &s) != 0 || !S_ISDIR(s.st_mode) || s.st_uid != getuid()) { 185 int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
128 if (arg_debug) 186 if (fd == -1)
129 printf("Setting PULSE_CLIENTCONFIG environment variable\n"); 187 errExit("safe_fd");
130 if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0) 188 // confirm the actual mount destination is owned by the user
131 errExit("setenv"); 189 if (fstat(fd, &s) == -1 || s.st_uid != getuid())
132 free(homeusercfg); 190 errExit("fstat");
133 free(pulsecfg); 191 // preserve a read-only mount
134 return; 192 struct statvfs vfs;
193 if (fstatvfs(fd, &vfs) == -1)
194 errExit("fstatvfs");
195 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
196 fs_rdonly(RUN_PULSE_DIR);
197 // mount via the link in /proc/self/fd
198 char *proc;
199 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
200 errExit("asprintf");
201 if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0)
202 errExit("mount pulseaudio");
203 fs_logger2("tmpfs", homeusercfg);
204 free(proc);
205 close(fd);
206 // check /proc/self/mountinfo to confirm the mount is ok
207 MountData *mptr = get_last_mount();
208 if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0)
209 errLogExit("invalid pulseaudio mount");
210
211 char *p;
212 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1)
213 errExit("asprintf");
214 fs_logger2("create", p);
215 free(p);
135 } 216 }
136 217
137 // get a file descriptor for ~/.config/pulse, fails if there is any symlink 218 else {
138 int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 219 // set environment
139 if (fd == -1) 220 if (setenv("PULSE_CLIENTCONFIG", pulsecfg, 1) < 0)
140 errExit("safe_fd"); 221 errExit("setenv");
141 // confirm again the actual mount destination is owned by the user
142 if (fstat(fd, &s) == -1)
143 errExit("fstat");
144 if (s.st_uid != getuid()) {
145 fprintf(stderr, "Error: %s is not owned by the current user\n", homeusercfg);
146 exit(1);
147 } 222 }
148 // preserve a read-only mount
149 struct statvfs vfs;
150 if (fstatvfs(fd, &vfs) == -1)
151 errExit("fstatvfs");
152 if ((vfs.f_flag & MS_RDONLY) == MS_RDONLY)
153 fs_rdonly(RUN_PULSE_DIR);
154 // mount via the link in /proc/self/fd
155 char *proc;
156 if (asprintf(&proc, "/proc/self/fd/%d", fd) == -1)
157 errExit("asprintf");
158 if (mount(RUN_PULSE_DIR, proc, "none", MS_BIND, NULL) < 0)
159 errExit("mount pulseaudio");
160 free(proc);
161 close(fd);
162 // check /proc/self/mountinfo to confirm the mount is ok
163 MountData *mptr = get_last_mount();
164 if (strcmp(mptr->dir, homeusercfg) != 0 || strcmp(mptr->fstype, "tmpfs") != 0)
165 errLogExit("invalid pulseaudio mount");
166 fs_logger2("tmpfs", homeusercfg);
167
168 char *p;
169 if (asprintf(&p, "%s/client.conf", homeusercfg) == -1)
170 errExit("asprintf");
171 fs_logger2("create", p);
172 free(p);
173 223
174 free(pulsecfg); 224 free(pulsecfg);
175 free(homeusercfg); 225 free(homeusercfg);