diff options
author | netblue30 <netblue30@yahoo.com> | 2017-08-27 07:26:37 -0400 |
---|---|---|
committer | netblue30 <netblue30@yahoo.com> | 2017-08-27 07:26:37 -0400 |
commit | 392d977ed119e592d08a806013960c599867aca0 (patch) | |
tree | cbe4e8d864d2b56af8ac2fa334b8ff5dfef531ed /src | |
parent | Merge pull request #1496 from SpotComms/mmc (diff) | |
download | firejail-392d977ed119e592d08a806013960c599867aca0.tar.gz firejail-392d977ed119e592d08a806013960c599867aca0.tar.zst firejail-392d977ed119e592d08a806013960c599867aca0.zip |
--private-bin: restrict full paths to the directories in the list
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/fs_bin.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/src/firejail/fs_bin.c b/src/firejail/fs_bin.c index b4755f755..110f027f7 100644 --- a/src/firejail/fs_bin.c +++ b/src/firejail/fs_bin.c | |||
@@ -94,6 +94,58 @@ static char *check_dir_or_file(const char *name) { | |||
94 | return paths[i]; | 94 | return paths[i]; |
95 | } | 95 | } |
96 | 96 | ||
97 | |||
98 | // return 1 if the file is in paths[] | ||
99 | static int valid_full_path_file(const char *name) { | ||
100 | assert(name); | ||
101 | |||
102 | char *full_name = realpath(name, NULL); | ||
103 | if (!full_name) | ||
104 | goto errexit; | ||
105 | char *fname = strrchr(full_name, '/'); | ||
106 | if (!fname) | ||
107 | goto errexit; | ||
108 | if (++fname == '\0') | ||
109 | goto errexit; | ||
110 | |||
111 | int i = 0; | ||
112 | int found = 0; | ||
113 | while (paths[i]) { | ||
114 | // private-bin-no-local can be disabled in /etc/firejail/firejail.config | ||
115 | if (checkcfg(CFG_PRIVATE_BIN_NO_LOCAL) && strstr(paths[i], "local/")) { | ||
116 | i++; | ||
117 | continue; | ||
118 | } | ||
119 | |||
120 | // check file | ||
121 | char *full_name2; | ||
122 | if (asprintf(&full_name2, "%s/%s", paths[i], fname) == -1) | ||
123 | errExit("asprintf"); | ||
124 | |||
125 | if (strcmp(full_name, full_name2) == 0) { | ||
126 | free(full_name2); | ||
127 | found = 1; | ||
128 | break; | ||
129 | } | ||
130 | |||
131 | free(full_name2); | ||
132 | i++; | ||
133 | } | ||
134 | |||
135 | if (!found) | ||
136 | goto errexit; | ||
137 | |||
138 | free(full_name); | ||
139 | return 1; | ||
140 | |||
141 | errexit: | ||
142 | if (arg_debug) | ||
143 | fwarning("file %s not found\n", name); | ||
144 | if (full_name) | ||
145 | free(full_name); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
97 | static void duplicate(char *fname, FILE *fplist) { | 149 | static void duplicate(char *fname, FILE *fplist) { |
98 | if (*fname == '~' || strstr(fname, "..")) { | 150 | if (*fname == '~' || strstr(fname, "..")) { |
99 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 151 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
@@ -110,11 +162,15 @@ static void duplicate(char *fname, FILE *fplist) { | |||
110 | // - if for example /usr/bin/which is a symlink to /bin/which, | 162 | // - if for example /usr/bin/which is a symlink to /bin/which, |
111 | // because in this case the result is a symlink pointing to | 163 | // because in this case the result is a symlink pointing to |
112 | // itself due to the file name being the same. | 164 | // itself due to the file name being the same. |
113 | // - if user wants to add a binary, which is not in the above | 165 | |
114 | // paths[] variable | 166 | if (!valid_full_path_file(fname)) |
115 | if (asprintf(&full_path, "%s", fname) == -1) | 167 | return; |
116 | errExit("asprintf"); | 168 | |
117 | } else { | 169 | full_path = strdup(fname); |
170 | if (!full_path) | ||
171 | errExit("strdup"); | ||
172 | } | ||
173 | else { | ||
118 | // Find the standard directory (by looping through paths[]) | 174 | // Find the standard directory (by looping through paths[]) |
119 | // where the filename fname is located | 175 | // where the filename fname is located |
120 | char *path = check_dir_or_file(fname); | 176 | char *path = check_dir_or_file(fname); |