From d798c507fa7c2c212cd0fd6f2f5a46a30bb796c3 Mon Sep 17 00:00:00 2001 From: Peter Millerchip Date: Sat, 22 Aug 2015 15:01:56 +0100 Subject: Implement the expand_home util function --- src/firejail/firejail.h | 1 + src/firejail/fs.c | 13 ++----------- src/firejail/fs_home.c | 50 ++++++++++++++++++++++++++++++++++++------------- src/firejail/profile.c | 10 +--------- src/firejail/util.c | 27 ++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 33 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 3acaeb6fb..83fc7b8d2 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -263,6 +263,7 @@ void check_private_dir(void); void update_map(char *mapping, char *map_file); void wait_for_other(int fd); void notify_other(int fd); +char *expand_home(const char *path, const char* homedir); // fs_var.c void fs_var_log(void); // mounting /var/log diff --git a/src/firejail/fs.c b/src/firejail/fs.c index 428ea0819..cec170521 100644 --- a/src/firejail/fs.c +++ b/src/firejail/fs.c @@ -291,17 +291,8 @@ void fs_blacklist(const char *homedir) { } // replace home macro in blacklist array - char *new_name = NULL; - if (strncmp(ptr, "${HOME}", 7) == 0) { - if (asprintf(&new_name, "%s%s", homedir, ptr + 7) == -1) - errExit("asprintf"); - ptr = new_name; - } - else if (strncmp(ptr, "~/", 2) == 0) { - if (asprintf(&new_name, "%s%s", homedir, ptr + 1) == -1) - errExit("asprintf"); - ptr = new_name; - } + char *new_name = expand_home(ptr, homedir); + ptr = new_name; // expand path macro - look for the file in /bin, /usr/bin, /sbin and /usr/sbin directories if (strncmp(ptr, "${PATH}", 7) == 0) { diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index e726d6f10..6f8bef60f 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -269,9 +269,19 @@ void fs_private(void) { static void check_dir_or_file(const char *name) { assert(name); struct stat s; - char *fname; - if (asprintf(&fname, "%s/%s", cfg.homedir, name) == -1) - errExit("asprintf"); + char *fname = expand_home(name, cfg.homedir); + if (!fname) { + fprintf(stderr, "Error: file %s not found.\n", name); + exit(1); + } + if (fname[0] != '/') { + // If it doesn't start with '/', it must be relative to homedir + char* tmp; + if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1) + errExit("asprintf"); + free(fname); + fname = tmp; + } if (arg_debug) printf("Checking %s\n", fname); if (stat(fname, &s) == -1) { @@ -323,15 +333,15 @@ void fs_check_home_list(void) { // check new private home directory (--private= option) - exit if it fails void fs_check_private_dir(void) { - // if the directory starts with ~, expand the home directory - if (*cfg.home_private == '~') { - char *tmp; - if (asprintf(&tmp, "%s%s", cfg.homedir, cfg.home_private + 1) == -1) - errExit("asprintf"); - cfg.home_private = tmp; - } + // Expand the home directory + char *tmp = expand_home(cfg.home_private, cfg.homedir); + cfg.home_private = realpath(tmp, NULL); + free(tmp); - if (!is_dir(cfg.home_private) || is_link(cfg.home_private) || strstr(cfg.home_private, "..")) { + if (!cfg.home_private + || !is_dir(cfg.home_private) + || is_link(cfg.home_private) + || strstr(cfg.home_private, "..")) { fprintf(stderr, "Error: invalid private directory\n"); exit(1); } @@ -371,11 +381,25 @@ static int mkpath(char* file_path, mode_t mode) { } #endif -static void duplicate(char *fname) { +static void duplicate(char *name) { char *cmd; + + char *fname = expand_home(name, cfg.homedir); + if (!fname) { + fprintf(stderr, "Error: file %s not found.\n", name); + exit(1); + } + if (fname[0] != '/') { + // If it doesn't start with '/', it must be relative to homedir + char* tmp; + if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1) + errExit("asprintf"); + free(fname); + fname = tmp; + } // copy the file - if (asprintf(&cmd, "cp -a --parents %s/%s %s", cfg.homedir, fname, HOME_DIR) == -1) + if (asprintf(&cmd, "cp -a --parents %s %s", fname, HOME_DIR) == -1) errExit("asprintf"); if (arg_debug) printf("%s\n", cmd); diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 86db82da0..4341434ac 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -433,15 +433,7 @@ void profile_read(const char *fname, const char *skip1, const char *skip2) { } // expand ${HOME}/ in front of the new profile file - char *newprofile2 = NULL; - if (strncmp(newprofile, "${HOME}", 7) == 0) { - if (asprintf(&newprofile2, "%s%s", cfg.homedir, newprofile + 7) == -1) - errExit("asprintf"); - } - else if (strncmp(newprofile, "~/", 2) == 0) { - if (asprintf(&newprofile2, "%s%s", cfg.homedir, newprofile + 1) == -1) - errExit("asprintf"); - } + char *newprofile2 = expand_home(newprofile, cfg.homedir); // recursivity profile_read((newprofile2)? newprofile2:newprofile, newskip1, newskip2); diff --git a/src/firejail/util.c b/src/firejail/util.c index 29eb101fb..59b975b4f 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -455,3 +455,30 @@ void notify_other(int fd) { fflush(stream); fclose(stream); } + +// This function takes a pathname supplied by the user and expands '~' and +// '${HOME}' at the start, to refer to a path relative to the user's home +// directory (supplied). +// The return value is allocated using malloc and must be freed by the caller. +// The function returns NULL if there are any errors. +char *expand_home(const char *path, const char* homedir) +{ + assert(path); + assert(homedir); + + // Replace home macro + char *new_name = NULL; + if (strncmp(path, "${HOME}", 7) == 0) { + if (asprintf(&new_name, "%s%s", homedir, path + 7) == -1) + errExit("asprintf"); + return new_name; + } + else if (strncmp(path, "~/", 2) == 0) { + if (asprintf(&new_name, "%s%s", homedir, path + 1) == -1) + errExit("asprintf"); + return new_name; + } + + return strdup(path); +} + -- cgit v1.2.3-70-g09d2