| # Prevent nsenter(1) from following basename symlinks. This can allow an |
| # attacker with a symlink primitive to trick a privileged process into executing |
| # in a different namespace. |
| # Unfortunately this solution only protects against basename symlinks, not |
| # against symlinks in other path components. A more comprehensive solution |
| # exists and will be sent upstream. |
| # See b/226186172 for details. |
| |
| diff --git a/sys-utils/nsenter.c b/sys-utils/nsenter.c |
| index 4432cd367..c520bf204 100644 |
| --- a/sys-utils/nsenter.c |
| +++ b/sys-utils/nsenter.c |
| @@ -112,11 +112,16 @@ static int wd_fd = -1; |
| static void open_target_fd(int *fd, const char *type, const char *path) |
| { |
| char pathbuf[PATH_MAX]; |
| + int flags = O_NOFOLLOW; |
| |
| if (!path && namespace_target_pid) { |
| snprintf(pathbuf, sizeof(pathbuf), "/proc/%u/%s", |
| namespace_target_pid, type); |
| path = pathbuf; |
| + /* Clear O_NOFOLLOW when opening a path in /proc, because |
| + * /proc/<pid>/ns/<type> is a symlink. |
| + */ |
| + flags = 0; |
| } |
| if (!path) |
| errx(EXIT_FAILURE, |
| @@ -126,9 +131,13 @@ static void open_target_fd(int *fd, const char *type, const char *path) |
| if (*fd >= 0) |
| close(*fd); |
| |
| - *fd = open(path, O_RDONLY); |
| - if (*fd < 0) |
| + *fd = open(path, O_RDONLY | flags); |
| + if (*fd < 0) { |
| + if (errno == ELOOP) |
| + errx(EXIT_FAILURE, _("refusing to follow symlink at %s"), path); |
| + |
| err(EXIT_FAILURE, _("cannot open %s"), path); |
| + } |
| } |
| |
| static void open_namespace_fd(int nstype, const char *path) |