cmd/initContainer: Try to handle config files that're absolute symlinks#460
Conversation
|
Build failed.
|
a0882a1 to
0289674
Compare
|
Build failed.
|
0289674 to
24c936a
Compare
|
I extended the comment in the function to clarify what it does, added a description of the |
|
Build failed.
|
24c936a to
ef34d58
Compare
|
Build failed.
|
b8660cc to
88a7ae5
Compare
|
@debarshiray when you have time, could you look at this?? 2c4405d and 88a7ae5 made this a bit larger change but I think it's necessary to include it to keep toolboxes work across system updates (or rebases on Silverblue/CoreOS). |
|
Build failed.
|
debarshiray
left a comment
There was a problem hiding this comment.
Thanks for working on this!
src/cmd/initContainer.go
Outdated
| // If the target is a link, follow the chain. If needed, repeat the process. | ||
| for isSymlink { | ||
| logrus.Debugf("Path %s is a symlink. Resolving.", target) | ||
| newTarget, err := os.Readlink(target) |
There was a problem hiding this comment.
Am I wrong in thinking that a lot of this can be simplified by using filepath.EvalSymlinks ?
For example, I have:
$ ls -l /etc/os-release
lrwxrwxrwx. 1 root root 21 Apr 28 14:50 /etc/os-release -> ../usr/lib/os-release
Invoking filepath.EvalSymlinks("/etc/os-release") gives me /usr/lib/os-release.
For the sake of sanity, I don't mind requiring that the redirectPath function accepts only absolute paths, because it's an internal function whose callers are under our control. If we go down this path, then I would check the inputs early on in the function and panic out (because it would be a programmer error) if the conditions aren't met.
There was a problem hiding this comment.
Ignoring the exact Go APIs that are used, I think that the redirectPath function should roughly do the following:
-
If
targetis not a symbolic link, then don't bother checking if it exists or not. Just linkcontainerPathtotarget. -
If
targetis a symbolic link, then check if it's resolving. If it's resolving, then linkcontainerPathtotarget. -
If
targetis a symbolic link and if it's not resolving, then either the link is absolute or relative. If it's absolute, then prepend/run/hostto the destination oftargetand linkcontainerPathto it, which may or not lead to a valid file. If it's relative, then linkcontainerPathtotargeteven though we know that it doesn't resolve. In both these cases, we are not trying to guarantee thatcontainerPathpoints to a valid file. We are merely doing the best we can to dig up the right destination, and giving up if we run out of guesses. -
It should not fail the entry-point process even if
targetdoesn't exist or resolve. We can log a debug message or such, but we shouldn't stop the container from starting up just because there's something wrong with a configuration file. In this case, a slightly broken container that starts is vastly better than one doesn't start at all. If nothing else, it makes it easier to debug.
At the end of the day, all sane operating systems should be using relative symbolic links on the host. Fedora does that, and this is exactly the reason why relative symlinks are nice. They work even if you change the root from / to /run/host.
What we are trying to fix, are those few cases where a human created an absolute symbolic link. We should do our best to handle the obvious and simple cases, but if a human has made a mistake, then it's their responsibility to fix that up.
src/cmd/initContainer.go
Outdated
| // If the target is a link, follow the chain. If needed, repeat the process. | ||
| for isSymlink { | ||
| logrus.Debugf("Path %s is a symlink. Resolving.", target) | ||
| newTarget, err := os.Readlink(target) |
There was a problem hiding this comment.
Ignoring the exact Go APIs that are used, I think that the redirectPath function should roughly do the following:
-
If
targetis not a symbolic link, then don't bother checking if it exists or not. Just linkcontainerPathtotarget. -
If
targetis a symbolic link, then check if it's resolving. If it's resolving, then linkcontainerPathtotarget. -
If
targetis a symbolic link and if it's not resolving, then either the link is absolute or relative. If it's absolute, then prepend/run/hostto the destination oftargetand linkcontainerPathto it, which may or not lead to a valid file. If it's relative, then linkcontainerPathtotargeteven though we know that it doesn't resolve. In both these cases, we are not trying to guarantee thatcontainerPathpoints to a valid file. We are merely doing the best we can to dig up the right destination, and giving up if we run out of guesses. -
It should not fail the entry-point process even if
targetdoesn't exist or resolve. We can log a debug message or such, but we shouldn't stop the container from starting up just because there's something wrong with a configuration file. In this case, a slightly broken container that starts is vastly better than one doesn't start at all. If nothing else, it makes it easier to debug.
At the end of the day, all sane operating systems should be using relative symbolic links on the host. Fedora does that, and this is exactly the reason why relative symlinks are nice. They work even if you change the root from / to /run/host.
What we are trying to fix, are those few cases where a human created an absolute symbolic link. We should do our best to handle the obvious and simple cases, but if a human has made a mistake, then it's their responsibility to fix that up.
|
Given that operating systems are expected to use relative symbolic links, it seems to me that updates aren't such a pressing problem. When someone updates from Fedora 32 to 33, then their Things can break if a user changes their
|
88a7ae5 to
4e0ba3c
Compare
|
Build failed.
|
4e0ba3c to
835fc3c
Compare
|
Build failed.
|
835fc3c to
dd2b3ec
Compare
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
ae0cfed to
d755b2a
Compare
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
d755b2a to
56e86e3
Compare
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
56e86e3 to
2e823c5
Compare
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
2e823c5 to
e97fd51
Compare
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
e97fd51 to
4c5906e
Compare
|
Build failed.
|
There has been a long-standing issue[0] when symlinking /etc/resolv.conf to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were proposed. Hardcode other paths, where the file could be, completely rely on tools like flatpak-session-helper that will track such files in a single directory, or update the symlinking function to follow symlinks and update the target path. [0] containers#187 The first solution is the easiest short-term but not very good long-term. The second solution is possibly the best long-term but there is a problem with using flatpak-session-helper. It cannot be used as root. That leaves the third option, follow symlinks and update the target path if the target is an invalid symlink. This commit takes the third approach to solve the issue. Now the target of the symlinking is first tested if it is a symlink. If it's not then the symlinking is done right away. If it's a symlink then it is resolved. When the target is valid, symlinking proceeds normally. If it it's not then symlinking still proceeds but in two different ways depending on target being an absolute or a relative symlink: - absolute - target is prepended with /run/host (the target may not be invalid) - relative - target is not changed (the target will be invalid) This commit tries to rely on well-made relative symlinks. Those behave correctly even when they are placed in a different prefix (in Toolbox's case under /run/host). Thanks Tudor Roman for raising concern about relative links. Based on: containers#380 containers#460
4c5906e to
2b78d78
Compare
Currently toolbox containers can get misconfigured if some configuration files on the host are absolute symbolic links to some other location. For example, when systemd-resolved is used to manage /etc/resolv.conf on the host, and if the file is an absolute link to /run/systemd/resolve/stub-resolv.conf, then /etc/resolv.conf ends up being invalid inside the container. This happens because the container's /etc/resolv.conf points to /run/host/etc/resolv.conf, which in turn points to /run/systemd/resolve/stub-resolv.conf, but that's absent from the container. This is, of course, not a problem with relative symbolic links. If the host had a relative link to ../run/systemd/resolve/stub-resolv.conf, then it would continue to work inside the container. One solution would have been to use flatpak-session-helper to maintain a copy of the host's /etc/resolv.conf in $XDG_RUNTIME_DIR/.flatpak-helper/monitor. However, that doesn't work when toolbox(1) is run as root. The other option is to prepend the destination of the absolute symbolic link with /run/host to make it resolve inside the container. It might not work with funky links, but it's enough for the common case where a an administrator changed the host's /etc/resolv.conf into a sane, but absolute, symbolic link. Properly configured hosts should anyway use relative symbolic links, because they don't need to be adjusted in such scenarios. That's also what Fedora and Ubuntu do, by default. Thanks to Tudor Roman for raising a concern about relative symbolic links. Based on Martin Pitt's work on the POSIX shell implementation: containers#380 containers#187
|
Build failed.
|
2b78d78 to
88a95b0
Compare
|
Build failed.
|
|
I took the liberty to address the above issues. Thanks for your work on this, @HarryMichal ! |
There has been a long-standing issue[0] when symlinking /etc/resolv.conf
to /run/host/etc/resolv.conf (host's resolv.conf). Many solutions were
proposed. Hardcode other paths, where the file could be, completely rely
on tools like flatpak-session-helper that will track such files in a
single directory, or update the symlinking function to follow symlinks
and update the target path.
The first solution is the easiest short-term but not very good
long-term. The second solution is possibly the best long-term but there
is a problem with using flatpak-session-helper. It cannot be used as
root. That leaves the third option, follow symlinks and update the
target path if the target is an invalid symlink.
This commit takes the third approach to solve the issue. Now the target
of the symlinking is first tested if it is a symlink. If it's not then
the symlinking is done right away. If it's a symlink then it is resolved.
When the target is valid, symlinking proceeds normally. If it it's not
then symlinking still proceeds but in two different ways depending on
target being an absolute or a relative symlink:
invalid)
This commit tries to rely on well-made relative symlinks. Those behave
correctly even when they are placed in a different prefix (in Toolbox's
case under /run/host).
Thanks Tudor Roman for raising concern about relative links.
Closes #187