[pve-devel] [RFC container] fix #2762: add recursive bindmount option

Oguz Bektas o.bektas at proxmox.com
Thu Jul 9 14:44:34 CEST 2020


allows to mount bindmounts recursively. useful for mounting ZFS datasets
in containers.

Signed-off-by: Oguz Bektas <o.bektas at proxmox.com>
---

@wobu is unsure about the security implications of this (bindmount +
symlink + recursion), so i'm sending this first version as RFC to get
reviewed.


 src/PVE/LXC.pm        | 14 ++++++++------
 src/PVE/LXC/Config.pm |  5 +++++
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index f3aca7a..aaf9594 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1452,10 +1452,11 @@ sub __bindmount_verify {
 
 # Perform the actual bind mounting:
 sub __bindmount_do {
-    my ($dir, $dest, $ro, @extra_opts) = @_;
-    PVE::Tools::run_command(['mount', '-o', 'bind', @extra_opts, $dir, $dest]);
+    my ($dir, $dest, $ro, $recursive_bind, @extra_opts) = @_;
+    my $bind_method = $recursive_bind ? 'rbind' : 'bind';
+    PVE::Tools::run_command(['mount', '-o', $bind_method, @extra_opts, $dir, $dest]);
     if ($ro) {
-	eval { PVE::Tools::run_command(['mount', '-o', 'bind,remount,ro', $dest]); };
+	eval { PVE::Tools::run_command(['mount', '-o', "$bind_method,remount,ro", $dest]); };
 	if (my $err = $@) {
 	    warn "bindmount error\n";
 	    # don't leave writable bind-mounts behind...
@@ -1466,11 +1467,11 @@ sub __bindmount_do {
 }
 
 sub bindmount {
-    my ($dir, $parentfd, $last_dir, $dest, $ro, @extra_opts) = @_;
+    my ($dir, $parentfd, $last_dir, $dest, $ro, $recursive_bind, @extra_opts) = @_;
 
     my $srcdh = __bindmount_prepare('/', $dir);
 
-    __bindmount_do($dir, $dest, $ro, @extra_opts);
+    __bindmount_do($dir, $dest, $ro, $recursive_bind, @extra_opts);
 
     if (!__bindmount_verify($srcdh, $parentfd, $last_dir, $ro)) {
 	PVE::Tools::run_command(['umount', $dest]);
@@ -1591,6 +1592,7 @@ sub __mountpoint_mount {
 
     my $optstring = join(',', @$optlist);
     my $readonly = $mountpoint->{ro};
+    my $recursive_bind = $mountpoint->{recursive};
 
     my @extra_opts;
     @extra_opts = ('-o', $optstring) if $optstring;
@@ -1676,7 +1678,7 @@ sub __mountpoint_mount {
 	return wantarray ? ($volid, 0, $devpath) : $volid;
     } elsif ($type eq 'bind') {
 	die "directory '$volid' does not exist\n" if ! -d $volid;
-	bindmount($volid, $parentfd, $last_dir//$rootdir, $mount_path, $readonly, @extra_opts) if $mount_path;
+	bindmount($volid, $parentfd, $last_dir//$rootdir, $mount_path, $readonly, $recursive_bind, @extra_opts) if $mount_path;
 	warn "cannot enable quota control for bind mounts\n" if $quota;
 	return wantarray ? ($volid, 0, undef) : $volid;
     }
diff --git a/src/PVE/LXC/Config.pm b/src/PVE/LXC/Config.pm
index edd587b..0b8c35d 100644
--- a/src/PVE/LXC/Config.pm
+++ b/src/PVE/LXC/Config.pm
@@ -766,6 +766,11 @@ my $mp_desc = {
 	verbose_description => "Path to the mount point as seen from inside the container.\n\n".
 			       "NOTE: Must not contain any symlinks for security reasons."
     },
+    recursive => {
+	type => 'boolean',
+	description => 'Mount recursively. Useful for mounting ZFS dataset trees.',
+	optional => 1
+    }
 };
 PVE::JSONSchema::register_format('pve-ct-mountpoint', $mp_desc);
 
-- 
2.20.1





More information about the pve-devel mailing list