diff options
author | Simo Piiroinen <simo.piiroinen@jolla.com> | 2020-10-09 12:15:31 +0300 |
---|---|---|
committer | Tomi Leppänen <tomi.leppanen@jolla.com> | 2021-02-19 09:38:54 +0200 |
commit | 80b73e75d82ec618625c5278828bb5b9b32d3114 (patch) | |
tree | ba062f63d9c343a47898b089d20d28cf24ca9f44 /src/fcopy/main.c | |
parent | refresh capabilities (#3945) (diff) | |
download | firejail-80b73e75d82ec618625c5278828bb5b9b32d3114.tar.gz firejail-80b73e75d82ec618625c5278828bb5b9b32d3114.tar.zst firejail-80b73e75d82ec618625c5278828bb5b9b32d3114.zip |
Fix symlinks that go though /proc/self
When constructing sandbox fs, /etc/mtab which is symlink to
/proc/self/mounts gets resolved as /proc/PID/mounts. Where
PID is not the pid of the process that is going to get
executed in the firejail -> the result is broken/unaccessible
symlink from the application point of view.
Use /proc/self/xxx type symlink target if it resolves similarly
as the /proc/PID/xxx type would at the time of mapping.
Signed-off-by: Simo Piiroinen <simo.piiroinen@jolla.com>
Signed-off-by: Tomi Leppänen <tomi.leppanen@jolla.com>
Diffstat (limited to 'src/fcopy/main.c')
-rw-r--r-- | src/fcopy/main.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/src/fcopy/main.c b/src/fcopy/main.c index 01633be59..a41df52a1 100644 --- a/src/fcopy/main.c +++ b/src/fcopy/main.c | |||
@@ -172,6 +172,47 @@ static void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { | |||
172 | } | 172 | } |
173 | } | 173 | } |
174 | 174 | ||
175 | static char *proc_pid_to_self(const char *target) | ||
176 | { | ||
177 | char *use_target = 0; | ||
178 | char *proc_pid = 0; | ||
179 | |||
180 | if (!(use_target = canonicalize_file_name(target))) | ||
181 | goto done; | ||
182 | |||
183 | // target is under /proc/<PID>? | ||
184 | static const char proc[] = "/proc/"; | ||
185 | if (strncmp(use_target, proc, sizeof proc - 1)) | ||
186 | goto done; | ||
187 | |||
188 | int digit = use_target[sizeof proc - 1]; | ||
189 | if (digit < '1' || digit > '9') | ||
190 | goto done; | ||
191 | |||
192 | // check where /proc/self points to | ||
193 | static const char proc_self[] = "/proc/self"; | ||
194 | if (!(proc_pid = canonicalize_file_name(proc_self))) | ||
195 | goto done; | ||
196 | |||
197 | // redirect /proc/PID/xxx -> /proc/self/XXX | ||
198 | size_t pfix = strlen(proc_pid); | ||
199 | if (strncmp(use_target, proc_pid, pfix)) | ||
200 | goto done; | ||
201 | |||
202 | if (use_target[pfix] != 0 && use_target[pfix] != '/') | ||
203 | goto done; | ||
204 | |||
205 | char *tmp; | ||
206 | if (asprintf(&tmp, "%s%s", proc_self, use_target + pfix) != -1) { | ||
207 | if (arg_debug) | ||
208 | fprintf(stderr, "SYMLINK %s\n --> %s\n", use_target, tmp); | ||
209 | free(use_target), use_target = tmp; | ||
210 | } | ||
211 | |||
212 | done: | ||
213 | free(proc_pid); | ||
214 | return use_target; | ||
215 | } | ||
175 | 216 | ||
176 | void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { | 217 | void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, gid_t gid) { |
177 | (void) mode; | 218 | (void) mode; |
@@ -183,7 +224,7 @@ void copy_link(const char *target, const char *linkpath, mode_t mode, uid_t uid, | |||
183 | if (lstat(linkpath, &s) == 0) | 224 | if (lstat(linkpath, &s) == 0) |
184 | return; | 225 | return; |
185 | 226 | ||
186 | char *rp = realpath(target, NULL); | 227 | char *rp = proc_pid_to_self(target); |
187 | if (rp) { | 228 | if (rp) { |
188 | if (symlink(rp, linkpath) == -1) { | 229 | if (symlink(rp, linkpath) == -1) { |
189 | free(rp); | 230 | free(rp); |