aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/pulseaudio.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/pulseaudio.c')
-rw-r--r--src/firejail/pulseaudio.c98
1 files changed, 28 insertions, 70 deletions
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index 4ddaba7ed..c683eea3a 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -92,7 +92,7 @@ void pulseaudio_init(void) {
92 errExit("asprintf"); 92 errExit("asprintf");
93 if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644)) // root needed 93 if (copy_file("/etc/pulse/client.conf", pulsecfg, -1, -1, 0644)) // root needed
94 errExit("copy_file"); 94 errExit("copy_file");
95 FILE *fp = fopen(pulsecfg, "a+"); 95 FILE *fp = fopen(pulsecfg, "a");
96 if (!fp) 96 if (!fp)
97 errExit("fopen"); 97 errExit("fopen");
98 fprintf(fp, "%s", "\nenable-shm = no\n"); 98 fprintf(fp, "%s", "\nenable-shm = no\n");
@@ -103,91 +103,49 @@ void pulseaudio_init(void) {
103 errExit("set_perms"); 103 errExit("set_perms");
104 104
105 // create ~/.config/pulse directory if not present 105 // create ~/.config/pulse directory if not present
106 char *dir1; 106 char *homeusercfg;
107 if (asprintf(&dir1, "%s/.config", cfg.homedir) == -1) 107 if (asprintf(&homeusercfg, "%s/.config", cfg.homedir) == -1)
108 errExit("asprintf"); 108 errExit("asprintf");
109 if (lstat(dir1, &s) == -1) { 109 if (lstat(homeusercfg, &s) == -1) {
110 pid_t child = fork(); 110 if (create_empty_dir_as_user(homeusercfg, 0700))
111 if (child < 0) 111 fs_logger2("create", homeusercfg);
112 errExit("fork");
113 if (child == 0) {
114 // drop privileges
115 drop_privs(0);
116
117 int rv = mkdir(dir1, 0755);
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);
130 } 112 }
131 else { 113 else if (!S_ISDIR(s.st_mode)) {
132 // we expect a user owned directory 114 if (S_ISLNK(s.st_mode))
133 if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) { 115 fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg);
134 if (S_ISLNK(s.st_mode)) 116 else
135 fprintf(stderr, "Error: user .config is a symbolic link\n"); 117 fprintf(stderr, "Error: %s is not a directory\n", homeusercfg);
136 else 118 exit(1);
137 fprintf(stderr, "Error: user .config is not a directory owned by the current user\n");
138 exit(1);
139 }
140 } 119 }
141 free(dir1); 120 free(homeusercfg);
142 121
143 if (asprintf(&dir1, "%s/.config/pulse", cfg.homedir) == -1) 122 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1)
144 errExit("asprintf"); 123 errExit("asprintf");
145 if (lstat(dir1, &s) == -1) { 124 if (lstat(homeusercfg, &s) == -1) {
146 pid_t child = fork(); 125 if (create_empty_dir_as_user(homeusercfg, 0700))
147 if (child < 0) 126 fs_logger2("create", homeusercfg);
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 } 127 }
167 else { 128 else if (!S_ISDIR(s.st_mode)) {
168 // we expect a user owned directory 129 if (S_ISLNK(s.st_mode))
169 if (!S_ISDIR(s.st_mode) || s.st_uid != getuid()) { 130 fprintf(stderr, "Error: %s is a symbolic link\n", homeusercfg);
170 if (S_ISLNK(s.st_mode)) 131 else
171 fprintf(stderr, "Error: user .config/pulse is a symbolic link\n"); 132 fprintf(stderr, "Error: %s is not a directory\n", homeusercfg);
172 else 133 exit(1);
173 fprintf(stderr, "Error: user .config/pulse is not a directory owned by the current user\n");
174 exit(1);
175 }
176 } 134 }
177 free(dir1);
178 135
179 // if we have ~/.config/pulse mount the new directory, else set environment variable. 136 // if we have ~/.config/pulse mount the new directory, else set environment variable.
180 char *homeusercfg;
181 if (asprintf(&homeusercfg, "%s/.config/pulse", cfg.homedir) == -1)
182 errExit("asprintf");
183 if (stat(homeusercfg, &s) == 0) { 137 if (stat(homeusercfg, &s) == 0) {
184 // get a file descriptor for ~/.config/pulse, fails if there is any symlink 138 // get a file descriptor for ~/.config/pulse, fails if there is any symlink
185 int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 139 int fd = safe_fd(homeusercfg, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
186 if (fd == -1) 140 if (fd == -1)
187 errExit("safe_fd"); 141 errExit("safe_fd");
188 // confirm the actual mount destination is owned by the user 142 // confirm the actual mount destination is owned by the user
189 if (fstat(fd, &s) == -1 || s.st_uid != getuid()) 143 if (fstat(fd, &s) == -1)
190 errExit("fstat"); 144 errExit("fstat");
145 if (s.st_uid != getuid()) {
146 fprintf(stderr, "Error: %s is not owned by the current user\n", homeusercfg);
147 exit(1);
148 }
191 // preserve a read-only mount 149 // preserve a read-only mount
192 struct statvfs vfs; 150 struct statvfs vfs;
193 if (fstatvfs(fd, &vfs) == -1) 151 if (fstatvfs(fd, &vfs) == -1)