aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2017-01-10 10:07:20 -0500
committerLibravatar netblue30 <netblue30@yahoo.com>2017-01-10 10:07:20 -0500
commit9aa81442afc6e00ca177bf0e3e7a025195102f7d (patch)
treecedef10be6c5efa2b3a87ec2568836891e696c61 /src
parentMerge pull request #1027 from reinerh/cve-references2 (diff)
downloadfirejail-9aa81442afc6e00ca177bf0e3e7a025195102f7d.tar.gz
firejail-9aa81442afc6e00ca177bf0e3e7a025195102f7d.tar.zst
firejail-9aa81442afc6e00ca177bf0e3e7a025195102f7d.zip
security fix
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/fs_home.c148
-rw-r--r--src/firejail/pulseaudio.c1
-rw-r--r--src/firejail/util.c46
4 files changed, 85 insertions, 112 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 36cf47435..a8208233f 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -450,6 +450,8 @@ void logmsg(const char *msg);
450void logargs(int argc, char **argv) ; 450void logargs(int argc, char **argv) ;
451void logerr(const char *msg); 451void logerr(const char *msg);
452int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode); 452int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
453void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode);
454void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode);
453int is_dir(const char *fname); 455int is_dir(const char *fname);
454int is_link(const char *fname); 456int is_link(const char *fname);
455char *line_remove_spaces(const char *buf); 457char *line_remove_spaces(const char *buf);
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c
index 4de082b06..e4b19d5cc 100644
--- a/src/firejail/fs_home.c
+++ b/src/firejail/fs_home.c
@@ -42,19 +42,17 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
42 // don't copy it if we already have the file 42 // don't copy it if we already have the file
43 if (stat(fname, &s) == 0) 43 if (stat(fname, &s) == 0)
44 return; 44 return;
45 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
46 fprintf(stderr, "Error: invalid %s file\n", fname);
47 exit(1);
48 }
45 if (stat("/etc/skel/.zshrc", &s) == 0) { 49 if (stat("/etc/skel/.zshrc", &s) == 0) {
46 if (copy_file("/etc/skel/.zshrc", fname, u, g, 0644) == 0) { 50 copy_file_as_user("/etc/skel/.zshrc", fname, u, g, 0644);
47 fs_logger("clone /etc/skel/.zshrc"); 51 fs_logger("clone /etc/skel/.zshrc");
48 }
49 } 52 }
50 else { // 53 else {
51 FILE *fp = fopen(fname, "w"); 54 touch_file_as_user(fname, u, g, 0644);
52 if (fp) { 55 fs_logger2("touch", fname);
53 fprintf(fp, "\n");
54 SET_PERMS_STREAM(fp, u, g, S_IRUSR | S_IWUSR);
55 fclose(fp);
56 fs_logger2("touch", fname);
57 }
58 } 56 }
59 free(fname); 57 free(fname);
60 } 58 }
@@ -64,23 +62,21 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
64 if (asprintf(&fname, "%s/.cshrc", homedir) == -1) 62 if (asprintf(&fname, "%s/.cshrc", homedir) == -1)
65 errExit("asprintf"); 63 errExit("asprintf");
66 struct stat s; 64 struct stat s;
65
67 // don't copy it if we already have the file 66 // don't copy it if we already have the file
68 if (stat(fname, &s) == 0) 67 if (stat(fname, &s) == 0)
69 return; 68 return;
69 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
70 fprintf(stderr, "Error: invalid %s file\n", fname);
71 exit(1);
72 }
70 if (stat("/etc/skel/.cshrc", &s) == 0) { 73 if (stat("/etc/skel/.cshrc", &s) == 0) {
71 if (copy_file("/etc/skel/.cshrc", fname, u, g, 0644) == 0) { 74 copy_file_as_user("/etc/skel/.cshrc", fname, u, g, 0644);
72 fs_logger("clone /etc/skel/.cshrc"); 75 fs_logger("clone /etc/skel/.cshrc");
73 }
74 } 76 }
75 else { // 77 else {
76 /* coverity[toctou] */ 78 touch_file_as_user(fname, u, g, 0644);
77 FILE *fp = fopen(fname, "w"); 79 fs_logger2("touch", fname);
78 if (fp) {
79 fprintf(fp, "\n");
80 SET_PERMS_STREAM(fp, u, g, S_IRUSR | S_IWUSR);
81 fclose(fp);
82 fs_logger2("touch", fname);
83 }
84 } 80 }
85 free(fname); 81 free(fname);
86 } 82 }
@@ -93,10 +89,13 @@ static void skel(const char *homedir, uid_t u, gid_t g) {
93 // don't copy it if we already have the file 89 // don't copy it if we already have the file
94 if (stat(fname, &s) == 0) 90 if (stat(fname, &s) == 0)
95 return; 91 return;
92 if (is_link(fname)) { // stat on dangling symlinks fails, try again using lstat
93 fprintf(stderr, "Error: invalid %s file\n", fname);
94 exit(1);
95 }
96 if (stat("/etc/skel/.bashrc", &s) == 0) { 96 if (stat("/etc/skel/.bashrc", &s) == 0) {
97 if (copy_file("/etc/skel/.bashrc", fname, u, g, 0644) == 0) { 97 copy_file_as_user("/etc/skel/.bashrc", fname, u, g, 0644);
98 fs_logger("clone /etc/skel/.bashrc"); 98 fs_logger("clone /etc/skel/.bashrc");
99 }
100 } 99 }
101 free(fname); 100 free(fname);
102 } 101 }
@@ -106,7 +105,7 @@ static int store_xauthority(void) {
106 // put a copy of .Xauthority in XAUTHORITY_FILE 105 // put a copy of .Xauthority in XAUTHORITY_FILE
107 char *src; 106 char *src;
108 char *dest = RUN_XAUTHORITY_FILE; 107 char *dest = RUN_XAUTHORITY_FILE;
109 // create an empty file 108 // create an empty file as root, and change ownership to user
110 FILE *fp = fopen(dest, "w"); 109 FILE *fp = fopen(dest, "w");
111 if (fp) { 110 if (fp) {
112 fprintf(fp, "\n"); 111 fprintf(fp, "\n");
@@ -124,27 +123,8 @@ static int store_xauthority(void) {
124 return 0; 123 return 0;
125 } 124 }
126 125
127 pid_t child = fork(); 126 copy_file_as_user(src, dest, getuid(), getgid(), 0600);
128 if (child < 0) 127 fs_logger2("clone", dest);
129 errExit("fork");
130 if (child == 0) {
131 // drop privileges
132 drop_privs(0);
133
134 // copy, set permissions and ownership
135 int rv = copy_file(src, dest, getuid(), getgid(), 0600);
136 if (rv)
137 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
138 else {
139 fs_logger2("clone", dest);
140 }
141#ifdef HAVE_GCOV
142 __gcov_flush();
143#endif
144 _exit(0);
145 }
146 // wait for the child to finish
147 waitpid(child, NULL, 0);
148 return 1; // file copied 128 return 1; // file copied
149 } 129 }
150 130
@@ -152,9 +132,10 @@ static int store_xauthority(void) {
152} 132}
153 133
154static int store_asoundrc(void) { 134static int store_asoundrc(void) {
135 // put a copy of .Xauthority in XAUTHORITY_FILE
155 char *src; 136 char *src;
156 char *dest = RUN_ASOUNDRC_FILE; 137 char *dest = RUN_ASOUNDRC_FILE;
157 // create an empty file 138 // create an empty file as root, and change ownership to user
158 FILE *fp = fopen(dest, "w"); 139 FILE *fp = fopen(dest, "w");
159 if (fp) { 140 if (fp) {
160 fprintf(fp, "\n"); 141 fprintf(fp, "\n");
@@ -182,27 +163,8 @@ static int store_asoundrc(void) {
182 free(rp); 163 free(rp);
183 } 164 }
184 165
185 pid_t child = fork(); 166 copy_file_as_user(src, dest, getuid(), getgid(), 0644);
186 if (child < 0) 167 fs_logger2("clone", dest);
187 errExit("fork");
188 if (child == 0) {
189 // drop privileges
190 drop_privs(0);
191
192 // copy, set permissions and ownership
193 int rv = copy_file(src, dest, getuid(), getgid(), 0644);
194 if (rv)
195 fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n");
196 else {
197 fs_logger2("clone", dest);
198 }
199#ifdef HAVE_GCOV
200 __gcov_flush();
201#endif
202 _exit(0);
203 }
204 // wait for the child to finish
205 waitpid(child, NULL, 0);
206 return 1; // file copied 168 return 1; // file copied
207 } 169 }
208 170
@@ -222,27 +184,8 @@ static void copy_xauthority(void) {
222 exit(1); 184 exit(1);
223 } 185 }
224 186
225 pid_t child = fork(); 187 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
226 if (child < 0) 188 fs_logger2("clone", dest);
227 errExit("fork");
228 if (child == 0) {
229 // drop privileges
230 drop_privs(0);
231
232 // copy, set permissions and ownership
233 int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
234 if (rv)
235 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
236 else {
237 fs_logger2("clone", dest);
238 }
239#ifdef HAVE_GCOV
240 __gcov_flush();
241#endif
242 _exit(0);
243 }
244 // wait for the child to finish
245 waitpid(child, NULL, 0);
246 189
247 // delete the temporary file 190 // delete the temporary file
248 unlink(src); 191 unlink(src);
@@ -261,27 +204,8 @@ static void copy_asoundrc(void) {
261 exit(1); 204 exit(1);
262 } 205 }
263 206
264 pid_t child = fork(); 207 copy_file_as_user(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
265 if (child < 0) 208 fs_logger2("clone", dest);
266 errExit("fork");
267 if (child == 0) {
268 // drop privileges
269 drop_privs(0);
270
271 // copy, set permissions and ownership
272 int rv = copy_file(src, dest, getuid(), getgid(), S_IRUSR | S_IWUSR);
273 if (rv)
274 fprintf(stderr, "Warning: cannot transfer .asoundrc in private home directory\n");
275 else {
276 fs_logger2("clone", dest);
277 }
278#ifdef HAVE_GCOV
279 __gcov_flush();
280#endif
281 _exit(0);
282 }
283 // wait for the child to finish
284 waitpid(child, NULL, 0);
285 209
286 // delete the temporary file 210 // delete the temporary file
287 unlink(src); 211 unlink(src);
diff --git a/src/firejail/pulseaudio.c b/src/firejail/pulseaudio.c
index 14a7f03dd..f0f95a80e 100644
--- a/src/firejail/pulseaudio.c
+++ b/src/firejail/pulseaudio.c
@@ -22,6 +22,7 @@
22#include <sys/stat.h> 22#include <sys/stat.h>
23#include <sys/mount.h> 23#include <sys/mount.h>
24#include <dirent.h> 24#include <dirent.h>
25#include <sys/wait.h>
25 26
26static void disable_file(const char *path, const char *file) { 27static void disable_file(const char *path, const char *file) {
27 assert(file); 28 assert(file);
diff --git a/src/firejail/util.c b/src/firejail/util.c
index 5b94aa288..2d3563093 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -28,6 +28,7 @@
28#include <grp.h> 28#include <grp.h>
29#include <sys/ioctl.h> 29#include <sys/ioctl.h>
30#include <termios.h> 30#include <termios.h>
31#include <sys/wait.h>
31 32
32#define MAX_GROUPS 1024 33#define MAX_GROUPS 1024
33// drop privileges 34// drop privileges
@@ -218,6 +219,51 @@ int copy_file(const char *srcname, const char *destname, uid_t uid, gid_t gid, m
218 return 0; 219 return 0;
219} 220}
220 221
222// return -1 if error, 0 if no error
223void copy_file_as_user(const char *srcname, const char *destname, uid_t uid, gid_t gid, mode_t mode) {
224 pid_t child = fork();
225 if (child < 0)
226 errExit("fork");
227 if (child == 0) {
228 // drop privileges
229 drop_privs(0);
230
231 // copy, set permissions and ownership
232 int rv = copy_file(srcname, destname, uid, gid, mode);
233 if (rv)
234 fprintf(stderr, "Warning: cannot transfer .Xauthority in private home directory\n");
235#ifdef HAVE_GCOV
236 __gcov_flush();
237#endif
238 _exit(0);
239 }
240 // wait for the child to finish
241 waitpid(child, NULL, 0);
242}
243
244// return -1 if error, 0 if no error
245void touch_file_as_user(const char *fname, uid_t uid, gid_t gid, mode_t mode) {
246 pid_t child = fork();
247 if (child < 0)
248 errExit("fork");
249 if (child == 0) {
250 // drop privileges
251 drop_privs(0);
252
253 FILE *fp = fopen(fname, "w");
254 if (fp) {
255 fprintf(fp, "\n");
256 SET_PERMS_STREAM(fp, uid, gid, mode);
257 fclose(fp);
258 }
259#ifdef HAVE_GCOV
260 __gcov_flush();
261#endif
262 _exit(0);
263 }
264 // wait for the child to finish
265 waitpid(child, NULL, 0);
266}
221 267
222// return 1 if the file is a directory 268// return 1 if the file is a directory
223int is_dir(const char *fname) { 269int is_dir(const char *fname) {