From e1a24494343016d00100e5e8e7e8716ac77363f6 Mon Sep 17 00:00:00 2001 From: LaurentGH <31282893+LaurentGH@users.noreply.github.com> Date: Thu, 24 Aug 2017 15:35:05 +0200 Subject: Allow private-bin parameters to be an absolute path With Ubuntu 16.04, /usr/bin/which is a symlink to /bin/which. So, using "private-bin which" finds "which" in /usr/bin and adds the symlink to "which" in /bin mapped directory. The /bin directory thus contains a symlink named "which" pointing to "/bin/which" (itself). This creates a symlink loop, and does not work. In order to solve this, the full path can now be used, such as "private-bin /bin/which". --- src/firejail/fs_bin.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index f70bd095b..b4755f755 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c @@ -95,20 +95,34 @@ static char *check_dir_or_file(const char *name) { } static void duplicate(char *fname, FILE *fplist) { - if (*fname == '~' || *fname == '/' || strstr(fname, "..")) { + if (*fname == '~' || strstr(fname, "..")) { fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); exit(1); } invalid_filename(fname); - char *path = check_dir_or_file(fname); - if (!path) - return; - - // expand path, just in case this is a symbolic link char *full_path; - if (asprintf(&full_path, "%s/%s", path, fname) == -1) - errExit("asprintf"); + if (*fname == '/') { + // If the absolute filename is indicated, directly use it. This + // is required for the following three cases: + // - if user's $PATH order is not the same as the above + // paths[] variable order + // - if for example /usr/bin/which is a symlink to /bin/which, + // because in this case the result is a symlink pointing to + // itself due to the file name being the same. + // - if user wants to add a binary, which is not in the above + // paths[] variable + if (asprintf(&full_path, "%s", fname) == -1) + errExit("asprintf"); + } else { + // Find the standard directory (by looping through paths[]) + // where the filename fname is located + char *path = check_dir_or_file(fname); + if (!path) + return; + if (asprintf(&full_path, "%s/%s", path, fname) == -1) + errExit("asprintf"); + } if (fplist) fprintf(fplist, "%s\n", full_path); -- cgit v1.2.3-54-g00ecf