From ef7eccad5b4e25237baeb2a50ce184f6cc0fc8ea Mon Sep 17 00:00:00 2001 From: benaryorg Date: Fri, 4 Jun 2021 12:34:52 +0000 Subject: [PATCH] fix #648 by ignoring EINVAL on-remount of proc When using --mount-proc=/some/path then unshare fails if the path provided is not already mounted due to the mount(2) call to change the propagation of the mount. In such a case mount(2) returns EINVAL, which however is used for a variety of other errors. If this error is ignored mistakenly the effects however should be negligible since: 1. the mount of proc afterwards happens regardless, errors of which are not ignored 2. the propagation change of root uses MS_REC, which should already change the propagation of all mounts recursively Furthermore /proc is not touched if --mount-proc specifies a different mount point. This should not cause too much unexpected behaviour due to point 2 from above in any case. Specifying --mount-proc with a different path also means that unshare(3) is not instructed to touch /proc, thus /proc not being touched should not be unexpected. As a side note, if unshare is called with /proc as an (implicit) parameter to --mount-proc then /proc is a stacked mount, meaning if /proc is unmounted within the namespace the host /proc will be visible again, thus not touching /proc with a different parameter does not constitute more information leakage than the alternative, quite contrary it may even be the desired behaviour. Signed-off-by: benaryorg --- sys-utils/unshare.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/sys-utils/unshare.c b/sys-utils/unshare.c index 39e2895afd..8e61221da8 100644 --- a/sys-utils/unshare.c +++ b/sys-utils/unshare.c @@ -650,8 +650,18 @@ int main(int argc, char *argv[]) err(EXIT_FAILURE, _("cannot chdir to '%s'"), newdir); if (procmnt) { - if (!newroot && mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL) != 0) - err(EXIT_FAILURE, _("cannot change %s filesystem propagation"), procmnt); + /* When not changing root and using the default propagation flags + then the recursive propagation change of root will + automatically change that of an existing proc mount. */ + if (!newroot && propagation != (MS_PRIVATE|MS_REC)) { + int rc = mount("none", procmnt, NULL, MS_PRIVATE|MS_REC, NULL); + + /* Custom procmnt means that proc is very likely not mounted, causing EINVAL. + Ignoring the error in this specific instance is considered safe. */ + if(rc != 0 && errno != EINVAL) + err(EXIT_FAILURE, _("cannot change %s filesystem propagation"), procmnt); + } + if (mount("proc", procmnt, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) != 0) err(EXIT_FAILURE, _("mount %s failed"), procmnt); } -- 2.47.3