From 6f51881d4681a0db1e5f4668b5d233d4c6982c73 Mon Sep 17 00:00:00 2001 From: Panu Matilainen Date: Thu, 1 Aug 2024 13:54:25 +0300 Subject: [PATCH] Disable private mounts in chroot'ed operation in the unshare plugin mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) inside a chroot fails with EINVAL if the "/" inside the chroot is not an actual mount point on the system - as it often isn't. For now, just disable that functionality on chroot operation. Related: #3187 --- docs/man/rpm-plugin-unshare.8.md | 5 +++++ plugins/unshare.c | 21 ++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/docs/man/rpm-plugin-unshare.8.md b/docs/man/rpm-plugin-unshare.8.md index d8a4222426..33073b872d 100644 --- a/docs/man/rpm-plugin-unshare.8.md +++ b/docs/man/rpm-plugin-unshare.8.md @@ -27,6 +27,11 @@ This plugin implements the following configurables: execution. Typical examples would be `/tmp` to protect against insecure temporary file usage inside scriptlets, and `/home` to prevent scriptlets from accessing user home directories. + When path unsharing is enabled, any mounts made from scriptlets + are also private to the scriptlet (and vice versa, mount changes + on the host are not visible to the scriptlet). + + Private mounts in chroot-operations is unimplemented. `%__transaction_unshare_nonet` diff --git a/plugins/unshare.c b/plugins/unshare.c index bb02201e4a..50f60fad2f 100644 --- a/plugins/unshare.c +++ b/plugins/unshare.c @@ -19,8 +19,18 @@ static rpmRC unshare_init(rpmPlugin plugin, rpmts ts) { char *paths = rpmExpand("%{?__transaction_unshare_paths}", NULL); private_mounts = argvSplitString(paths, ":", ARGV_SKIPEMPTY); - if (private_mounts) - unshare_flags |= CLONE_NEWNS; + if (private_mounts) { + /* + * Changing mount propagation from inside a chroot fails if the root + * is not also a mount point, disable for now. + */ + if (strcmp(rpmtsRootDir(ts), "/")) { + rpmlog(RPMLOG_WARNING, + "private mounts in chroot not implemented\n"); + } else { + unshare_flags |= CLONE_NEWNS; + } + } free(paths); if (rpmExpandNumeric("%{?__transaction_unshare_nonet}")) @@ -47,9 +57,10 @@ static rpmRC unshare_scriptlet_fork_post(rpmPlugin plugin, goto exit; } - if (private_mounts) { - if (mount("/", "/", NULL, MS_REC | MS_PRIVATE, NULL) == -1) { - rpmlog(RPMLOG_ERR, _("failed to mount private %s: %s\n"), + if (unshare_flags & CLONE_NEWNS) { + if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL) == -1) { + rpmlog(RPMLOG_ERR, + _("failed to change mount propagation %s: %s\n"), "/", strerror(errno)); goto exit; }