diff options
Diffstat (limited to 'src/firejail/main.c')
-rw-r--r-- | src/firejail/main.c | 51 |
1 files changed, 43 insertions, 8 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c index 1e2488062..d00147c74 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <sys/mount.h> | 26 | #include <sys/mount.h> |
27 | #include <sys/wait.h> | 27 | #include <sys/wait.h> |
28 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
29 | #include <fcntl.h> | ||
30 | #include <dirent.h> | 29 | #include <dirent.h> |
31 | #include <pwd.h> | 30 | #include <pwd.h> |
32 | #include <errno.h> | 31 | #include <errno.h> |
@@ -38,6 +37,11 @@ | |||
38 | #include <net/if.h> | 37 | #include <net/if.h> |
39 | #include <sys/utsname.h> | 38 | #include <sys/utsname.h> |
40 | 39 | ||
40 | #include <fcntl.h> | ||
41 | #ifndef O_PATH | ||
42 | #define O_PATH 010000000 | ||
43 | #endif | ||
44 | |||
41 | #ifdef __ia64__ | 45 | #ifdef __ia64__ |
42 | /* clone(2) has a different interface on ia64, as it needs to know | 46 | /* clone(2) has a different interface on ia64, as it needs to know |
43 | the size of the stack */ | 47 | the size of the stack */ |
@@ -242,6 +246,41 @@ static pid_t require_pid(const char *name) { | |||
242 | return pid; | 246 | return pid; |
243 | } | 247 | } |
244 | 248 | ||
249 | // return 1 if there is a link somewhere in path of directory | ||
250 | static int has_link(const char *dir) { | ||
251 | assert(dir); | ||
252 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
253 | if (fd == -1) { | ||
254 | if (errno == ENOTDIR && is_dir(dir)) | ||
255 | return 1; | ||
256 | } | ||
257 | else | ||
258 | close(fd); | ||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | static void build_cfg_homedir(const char *dir) { | ||
263 | EUID_ASSERT(); | ||
264 | assert(dir); | ||
265 | if (dir[0] != '/') { | ||
266 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir); | ||
267 | exit(1); | ||
268 | } | ||
269 | // symlinks are rejected in many places, provide a solution for home directories | ||
270 | if (checkcfg(CFG_HOMEDIR_SYMLINK)) { | ||
271 | cfg.homedir = realpath(dir, NULL); | ||
272 | if (cfg.homedir) | ||
273 | return; | ||
274 | } | ||
275 | else if (has_link(dir)) { | ||
276 | fprintf(stderr, "Error: path of user directory contains a symbolic link. " | ||
277 | "Please provide resolved path in password database (/etc/passwd) " | ||
278 | "or enable symbolic link resolution in Firejail configuration file.\n"); | ||
279 | exit(1); | ||
280 | } | ||
281 | cfg.homedir = clean_pathname(dir); | ||
282 | } | ||
283 | |||
245 | // init configuration | 284 | // init configuration |
246 | static void init_cfg(int argc, char **argv) { | 285 | static void init_cfg(int argc, char **argv) { |
247 | EUID_ASSERT(); | 286 | EUID_ASSERT(); |
@@ -265,15 +304,12 @@ static void init_cfg(int argc, char **argv) { | |||
265 | errExit("strdup"); | 304 | errExit("strdup"); |
266 | 305 | ||
267 | // build home directory name | 306 | // build home directory name |
268 | cfg.homedir = NULL; | 307 | if (pw->pw_dir == NULL) { |
269 | if (pw->pw_dir != NULL) { | ||
270 | cfg.homedir = clean_pathname(pw->pw_dir); | ||
271 | assert(cfg.homedir); | ||
272 | } | ||
273 | else { | ||
274 | fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); | 308 | fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username); |
275 | exit(1); | 309 | exit(1); |
276 | } | 310 | } |
311 | build_cfg_homedir(pw->pw_dir); | ||
312 | assert(cfg.homedir); | ||
277 | 313 | ||
278 | cfg.cwd = getcwd(NULL, 0); | 314 | cfg.cwd = getcwd(NULL, 0); |
279 | if (!cfg.cwd && errno != ENOENT) | 315 | if (!cfg.cwd && errno != ENOENT) |
@@ -926,7 +962,6 @@ int main(int argc, char **argv) { | |||
926 | 962 | ||
927 | // check if the user is allowed to use firejail | 963 | // check if the user is allowed to use firejail |
928 | init_cfg(argc, argv); | 964 | init_cfg(argc, argv); |
929 | assert(cfg.homedir); | ||
930 | 965 | ||
931 | // get starting timestamp, process --quiet | 966 | // get starting timestamp, process --quiet |
932 | start_timestamp = getticks(); | 967 | start_timestamp = getticks(); |