diff options
Diffstat (limited to 'src/firejail/pulseaudio.c')
-rw-r--r-- | src/firejail/pulseaudio.c | 98 |
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) |