diff options
author | smitsohu <smitsohu@gmail.com> | 2018-12-13 03:12:34 +0100 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2018-12-13 03:12:34 +0100 |
commit | 0d8655e4da43ce0ed1ed6cc4925c1f994f65215c (patch) | |
tree | dcf3332410d75b67f7952e9ebba32a71ddc89d3d /src | |
parent | pulseaudio: use env variable fallback in more cases (diff) | |
download | firejail-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/pulseaudio.c | 170 |
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); |