add symlink resolution for home directories

This commit is contained in:
smitsohu 2019-07-09 11:59:57 +02:00
parent 704ab975cb
commit 8bff773d6a
4 changed files with 44 additions and 7 deletions

View file

@ -2,6 +2,9 @@
# keyword-argument pairs, one per line. Most features are enabled by default.
# Use 'yes' or 'no' as configuration values.
# Allow symbolic links in path of user home directories, default disabled.
# homedir-symlink no
# Enable AppArmor functionality, default enabled.
# apparmor yes

View file

@ -50,6 +50,7 @@ int checkcfg(int val) {
cfg_val[CFG_DISABLE_MNT] = 0;
cfg_val[CFG_ARP_PROBES] = DEFAULT_ARP_PROBES;
cfg_val[CFG_XPRA_ATTACH] = 0;
cfg_val[CFG_HOMEDIR_SYMLINK] = 0;
// open configuration file
const char *fname = SYSCONFDIR "/firejail.config";
@ -85,6 +86,7 @@ int checkcfg(int val) {
ptr = line_remove_spaces(buf);
if (!ptr)
continue;
PARSE_YESNO(CFG_HOMEDIR_SYMLINK, "homedir-symlink")
PARSE_YESNO(CFG_FILE_TRANSFER, "file-transfer")
PARSE_YESNO(CFG_DBUS, "dbus")
PARSE_YESNO(CFG_JOIN, "join")

View file

@ -720,6 +720,7 @@ enum {
CFG_PRIVATE_CACHE,
CFG_CGROUP,
CFG_NAME_CHANGE,
CFG_HOMEDIR_SYMLINK,
// CFG_FILE_COPY_LIMIT - file copy limit handled using setenv/getenv
CFG_MAX // this should always be the last entry
};

View file

@ -242,6 +242,41 @@ static pid_t require_pid(const char *name) {
return pid;
}
// return 1 if there is a link somewhere in path of directory
static int has_link(const char *dir) {
assert(dir);
int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
if (fd == -1) {
if (errno == ENOTDIR && is_dir(dir))
return 1;
}
else
close(fd);
return 0;
}
static void build_cfg_homedir(const char *dir) {
EUID_ASSERT();
assert(dir);
if (dir[0] != '/') {
fprintf(stderr, "Error: invalid user directory \"%s\"\n", dir);
exit(1);
}
// symlinks are rejected in many places, provide a solution for home directories
if (checkcfg(CFG_HOMEDIR_SYMLINK)) {
cfg.homedir = realpath(dir, NULL);
if (cfg.homedir)
return;
}
else if (has_link(dir)) {
fprintf(stderr, "Error: path of user directory contains a symbolic link. "
"Please provide resolved path in password database (/etc/passwd) "
"or enable symbolic link resolution in Firejail configuration file.\n");
exit(1);
}
cfg.homedir = clean_pathname(dir);
}
// init configuration
static void init_cfg(int argc, char **argv) {
EUID_ASSERT();
@ -265,15 +300,12 @@ static void init_cfg(int argc, char **argv) {
errExit("strdup");
// build home directory name
cfg.homedir = NULL;
if (pw->pw_dir != NULL) {
cfg.homedir = clean_pathname(pw->pw_dir);
assert(cfg.homedir);
}
else {
if (pw->pw_dir == NULL) {
fprintf(stderr, "Error: user %s doesn't have a user directory assigned\n", cfg.username);
exit(1);
}
build_cfg_homedir(pw->pw_dir);
assert(cfg.homedir);
cfg.cwd = getcwd(NULL, 0);
if (!cfg.cwd && errno != ENOENT)
@ -926,7 +958,6 @@ int main(int argc, char **argv) {
// check if the user is allowed to use firejail
init_cfg(argc, argv);
assert(cfg.homedir);
// get starting timestamp, process --quiet
start_timestamp = getticks();