aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-07-09 11:59:57 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2019-07-09 11:59:57 +0200
commit8bff773d6a7bf70c97b3d5b751df9ec0dd6c8b5d (patch)
tree3d755f5a83e7861c6c4b1a83b69849431542697d
parentmore simplification of fs_check_chroot_dir (diff)
downloadfirejail-8bff773d6a7bf70c97b3d5b751df9ec0dd6c8b5d.tar.gz
firejail-8bff773d6a7bf70c97b3d5b751df9ec0dd6c8b5d.tar.zst
firejail-8bff773d6a7bf70c97b3d5b751df9ec0dd6c8b5d.zip
add symlink resolution for home directories
-rw-r--r--etc/firejail.config3
-rw-r--r--src/firejail/checkcfg.c2
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/main.c45
4 files changed, 44 insertions, 7 deletions
diff --git a/etc/firejail.config b/etc/firejail.config
index 565796d5a..4c0cb2a41 100644
--- a/etc/firejail.config
+++ b/etc/firejail.config
@@ -2,6 +2,9 @@
2# keyword-argument pairs, one per line. Most features are enabled by default. 2# keyword-argument pairs, one per line. Most features are enabled by default.
3# Use 'yes' or 'no' as configuration values. 3# Use 'yes' or 'no' as configuration values.
4 4
5# Allow symbolic links in path of user home directories, default disabled.
6# homedir-symlink no
7
5# Enable AppArmor functionality, default enabled. 8# Enable AppArmor functionality, default enabled.
6# apparmor yes 9# apparmor yes
7 10
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index f94b95d60..84054fe76 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -50,6 +50,7 @@ int checkcfg(int val) {
50 cfg_val[CFG_DISABLE_MNT] = 0; 50 cfg_val[CFG_DISABLE_MNT] = 0;
51 cfg_val[CFG_ARP_PROBES] = DEFAULT_ARP_PROBES; 51 cfg_val[CFG_ARP_PROBES] = DEFAULT_ARP_PROBES;
52 cfg_val[CFG_XPRA_ATTACH] = 0; 52 cfg_val[CFG_XPRA_ATTACH] = 0;
53 cfg_val[CFG_HOMEDIR_SYMLINK] = 0;
53 54
54 // open configuration file 55 // open configuration file
55 const char *fname = SYSCONFDIR "/firejail.config"; 56 const char *fname = SYSCONFDIR "/firejail.config";
@@ -85,6 +86,7 @@ int checkcfg(int val) {
85 ptr = line_remove_spaces(buf); 86 ptr = line_remove_spaces(buf);
86 if (!ptr) 87 if (!ptr)
87 continue; 88 continue;
89 PARSE_YESNO(CFG_HOMEDIR_SYMLINK, "homedir-symlink")
88 PARSE_YESNO(CFG_FILE_TRANSFER, "file-transfer") 90 PARSE_YESNO(CFG_FILE_TRANSFER, "file-transfer")
89 PARSE_YESNO(CFG_DBUS, "dbus") 91 PARSE_YESNO(CFG_DBUS, "dbus")
90 PARSE_YESNO(CFG_JOIN, "join") 92 PARSE_YESNO(CFG_JOIN, "join")
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 7664c8037..4bd70697e 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -720,6 +720,7 @@ enum {
720 CFG_PRIVATE_CACHE, 720 CFG_PRIVATE_CACHE,
721 CFG_CGROUP, 721 CFG_CGROUP,
722 CFG_NAME_CHANGE, 722 CFG_NAME_CHANGE,
723 CFG_HOMEDIR_SYMLINK,
723 // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv 724 // CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv
724 CFG_MAX // this should always be the last entry 725 CFG_MAX // this should always be the last entry
725}; 726};
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 1e2488062..03956ce4d 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -242,6 +242,41 @@ static pid_t require_pid(const char *name) {
242 return pid; 242 return pid;
243} 243}
244 244
245// return 1 if there is a link somewhere in path of directory
246static int has_link(const char *dir) {
247 assert(dir);
248 int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
249 if (fd == -1) {
250 if (errno == ENOTDIR && is_dir(dir))
251 return 1;
252 }
253 else
254 close(fd);
255 return 0;
256}
257
258static void build_cfg_homedir(const char *dir) {
259 EUID_ASSERT();
260 assert(dir);
261 if (dir[0] != '/') {
262 fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir);
263 exit(1);
264 }
265 // symlinks are rejected in many places, provide a solution for home directories
266 if (checkcfg(CFG_HOMEDIR_SYMLINK)) {
267 cfg.homedir = realpath(dir, NULL);
268 if (cfg.homedir)
269 return;
270 }
271 else if (has_link(dir)) {
272 fprintf(stderr, "Error: path of user directory contains a symbolic link. "
273 "Please provide resolved path in password database (/etc/passwd) "
274 "or enable symbolic link resolution in Firejail configuration file.\n");
275 exit(1);
276 }
277 cfg.homedir = clean_pathname(dir);
278}
279
245// init configuration 280// init configuration
246static void init_cfg(int argc, char **argv) { 281static void init_cfg(int argc, char **argv) {
247 EUID_ASSERT(); 282 EUID_ASSERT();
@@ -265,15 +300,12 @@ static void init_cfg(int argc, char **argv) {
265 errExit("strdup"); 300 errExit("strdup");
266 301
267 // build home directory name 302 // build home directory name
268 cfg.homedir = NULL; 303 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); 304 fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
275 exit(1); 305 exit(1);
276 } 306 }
307 build_cfg_homedir(pw->pw_dir);
308 assert(cfg.homedir);
277 309
278 cfg.cwd = getcwd(NULL, 0); 310 cfg.cwd = getcwd(NULL, 0);
279 if (!cfg.cwd && errno != ENOENT) 311 if (!cfg.cwd && errno != ENOENT)
@@ -926,7 +958,6 @@ int main(int argc, char **argv) {
926 958
927 // check if the user is allowed to use firejail 959 // check if the user is allowed to use firejail
928 init_cfg(argc, argv); 960 init_cfg(argc, argv);
929 assert(cfg.homedir);
930 961
931 // get starting timestamp, process --quiet 962 // get starting timestamp, process --quiet
932 start_timestamp = getticks(); 963 start_timestamp = getticks();