From da6298481ea4dfe7d894f42fa105cda015ebe5ce Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Mon, 7 Sep 2015 13:40:57 +0200 Subject: [PATCH] get rid of most of the loop-devices code -) loop devices are now attached in mountpoint_mount, and immediately detached in order to set the auto-clear flag Keeping track of loop-devices is otherweise next to impossible and a security concern. We mount the filesystems for the container. We do not support full loop device access for containers for a simple reason: once a container detached a loop device, the startup of another container might reuse it, exposing its devices to the first container, generating unwatned cross container access permissions. Loop devices are also set to auto-clear, so that we do not need to worry about detaching them when stopping the container. --- src/PVE/LXC.pm | 134 +++++++------------------------------- src/PVE/LXC/Create.pm | 7 +- src/PVE/VZDump/LXC.pm | 21 +----- src/lxc-pve-mount-hook | 5 +- src/lxc-pve-prestart-hook | 1 - 5 files changed, 29 insertions(+), 139 deletions(-) diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm index 7b91906..216c3cf 100644 --- a/src/PVE/LXC.pm +++ b/src/PVE/LXC.pm @@ -1286,9 +1286,6 @@ sub vm_stop_cleanup { if (!$keepActive) { my $vollist = get_vm_volumes($conf); - my $loopdevlist = get_vm_volumes($conf, 'rootfs'); - - detach_loops($storage_cfg, $loopdevlist); PVE::Storage::deactivate_volumes($storage_cfg, $vollist); } }; @@ -1821,21 +1818,6 @@ sub foreach_mountpoint_reverse { foreach_mountpoint_full($conf, 1, $func); } -sub loopdevices_list { - - my $loopdev = {}; - my $parser = sub { - my $line = shift; - if ($line =~ m/^(\/dev\/loop\d+)\s+\d\s+\d\s+\d\s+\d\s(\S+)$/) { - $loopdev->{$1} = $2; - } - }; - - PVE::Tools::run_command(['losetup'], outfunc => $parser); - - return $loopdev; -} - sub blockdevices_list { my $bdevs = {}; @@ -1849,14 +1831,6 @@ sub blockdevices_list { return $bdevs; } -sub find_loopdev { - my ($loopdevs, $path) = @_; - - foreach my $dev (keys %$loopdevs){ - return $dev if $loopdevs->{$dev} eq $path; - } -} - sub check_ct_modify_config_perm { my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_; @@ -1881,62 +1855,8 @@ sub check_ct_modify_config_perm { return 1; } -sub attach_loops { - my ($storage_cfg, $vollist, $snapname) = @_; - - my $loopdevs = {}; - - foreach my $volid (@$vollist) { - - my ($storage, $volname) = PVE::Storage::parse_volume_id($volid); - my $scfg = PVE::Storage::storage_config($storage_cfg, $storage); - - my ($vtype, undef, undef, undef, undef, $isBase, $format) = - PVE::Storage::parse_volname($storage_cfg, $volid); - - if ($format eq 'raw' && $scfg->{path}) { - my $path = PVE::Storage::path($storage_cfg, $volid, $snapname); - my $loopdev; - - my $parser = sub { - my $line = shift; - $loopdev = $line if $line =~m|^/dev/loop\d+$|; - $loopdevs->{$loopdev} = $path; - }; - - PVE::Tools::run_command(['losetup', '--find', '--show', $path], outfunc => $parser); - } - } - - return $loopdevs; -} - -sub detach_loops { - my ($storage_cfg, $vollist, $snapname) = @_; - - my $loopdevs = loopdevices_list(); - - foreach my $volid (@$vollist) { - - my ($storage, $volname) = PVE::Storage::parse_volume_id($volid); - my $scfg = PVE::Storage::storage_config($storage_cfg, $storage); - - my ($vtype, undef, undef, undef, undef, $isBase, $format) = - PVE::Storage::parse_volname($storage_cfg, $volid); - - if ($format eq 'raw' && $scfg->{path}) { - my $path = PVE::Storage::path($storage_cfg, $volid, $snapname); - foreach my $dev (keys %$loopdevs){ - PVE::Tools::run_command(['losetup', '-d', $dev]) if $loopdevs->{$dev} eq $path; - } - } - } -} - sub umount_all { - my ($vmid, $storage_cfg, $conf, $noerr, $loopdevs) = @_; - - $loopdevs ||= loopdevices_list(); + my ($vmid, $storage_cfg, $conf, $noerr) = @_; my $rootdir = "/var/lib/lxc/$vmid/rootfs"; my $volid_list = get_vm_volumes($conf); @@ -1965,8 +1885,6 @@ sub umount_all { } } }); - - PVE::LXC::detach_loops($storage_cfg, $volid_list); } sub mount_all { @@ -1977,10 +1895,7 @@ sub mount_all { my $volid_list = get_vm_volumes($conf); PVE::Storage::activate_volumes($storage_cfg, $volid_list); - my $loopdevs; eval { - $loopdevs = attach_loops($storage_cfg, $volid_list); - foreach_mountpoint($conf, sub { my ($ms, $mountpoint) = @_; @@ -1996,7 +1911,7 @@ sub mount_all { die "unable to mount base volume - internal error" if $isBase; File::Path::make_path "$rootdir/$mount" if $mkdirs; - mountpoint_mount($mountpoint, $rootdir, $storage_cfg, $loopdevs); + mountpoint_mount($mountpoint, $rootdir, $storage_cfg); }); }; if (my $err = $@) { @@ -2004,19 +1919,19 @@ sub mount_all { umount_all($vmid, $storage_cfg, $conf, 1); } - return wantarray ? ($rootdir, $loopdevs) : $rootdir; + return $rootdir; } sub mountpoint_mount_path { - my ($mountpoint, $storage_cfg, $loopdevs, $snapname) = @_; + my ($mountpoint, $storage_cfg, $snapname) = @_; - return mountpoint_mount($mountpoint, undef, $storage_cfg, $loopdevs, $snapname); + return mountpoint_mount($mountpoint, undef, $storage_cfg, $snapname); } # use $rootdir = undef to just return the corresponding mount path sub mountpoint_mount { - my ($mountpoint, $rootdir, $storage_cfg, $loopdevs, $snapname) = @_; + my ($mountpoint, $rootdir, $storage_cfg, $snapname) = @_; my $volid = $mountpoint->{volume}; my $mount = $mountpoint->{mp}; @@ -2040,42 +1955,37 @@ sub mountpoint_mount { my $scfg = PVE::Storage::storage_config($storage_cfg, $storage); my $path = PVE::Storage::path($storage_cfg, $volid, $snapname); + return $path if !$mount_path; my ($vtype, undef, undef, undef, undef, $isBase, $format) = PVE::Storage::parse_volname($storage_cfg, $volid); if ($format eq 'subvol') { - - if ($mount_path) { - if ($snapname) { - if ($scfg->{type} eq 'zfspool') { - my $path_arg = $path; - $path_arg =~ s!^/+!!; - PVE::Tools::run_command(['mount', '-o', 'ro', '-t', 'zfs', $path_arg, $mount_path]); - } else { - die "cannot mount subvol snapshots for storage type '$scfg->{type}'\n"; - } + if ($snapname) { + if ($scfg->{type} eq 'zfspool') { + my $path_arg = $path; + $path_arg =~ s!^/+!!; + PVE::Tools::run_command(['mount', '-o', 'ro', '-t', 'zfs', $path_arg, $mount_path]); } else { - PVE::Tools::run_command(['mount', '-o', 'bind', $path, $mount_path]); - } + die "cannot mount subvol snapshots for storage type '$scfg->{type}'\n"; + } + } else { + PVE::Tools::run_command(['mount', '-o', 'bind', $path, $mount_path]); } return $path; - } elsif ($format eq 'raw') { - + my @extra_opts; if ($scfg->{path}) { - $path = find_loopdev($loopdevs, $path) if $loopdevs; + push @extra_opts, '-o', 'loop'; } elsif ($scfg->{type} eq 'drbd' || $scfg->{type} eq 'rbd') { # do nothing } else { die "unsupported storage type '$scfg->{type}'\n"; } - if ($mount_path) { - if ($isBase || defined($snapname)) { - PVE::Tools::run_command(['mount', '-o', 'ro', $path, $mount_path]); - } else { - PVE::Tools::run_command(['mount', $path, $mount_path]); - } + if ($isBase || defined($snapname)) { + PVE::Tools::run_command(['mount', '-o', "ro", @extra_opts, $path, $mount_path]); + } else { + PVE::Tools::run_command(['mount', @extra_opts, $path, $mount_path]); } return $path; } else { diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm index 9a63083..463af0b 100644 --- a/src/PVE/LXC/Create.pm +++ b/src/PVE/LXC/Create.pm @@ -205,16 +205,15 @@ sub create_rootfs { PVE::LXC::create_config($vmid, $conf); } - my $loopdevs; eval { - my ($rootdir, $loopdevs) = PVE::LXC::mount_all($vmid, $storage_cfg, $conf); + my $rootdir = PVE::LXC::mount_all($vmid, $storage_cfg, $conf); restore_and_configure($vmid, $archive, $rootdir, $conf, $password, $restore); }; if (my $err = $@) { warn $err; - PVE::LXC::umount_all($vmid, $storage_cfg, $conf, 1, $loopdevs); + PVE::LXC::umount_all($vmid, $storage_cfg, $conf, 1); } else { - PVE::LXC::umount_all($vmid, $storage_cfg, $conf, 0, $loopdevs); + PVE::LXC::umount_all($vmid, $storage_cfg, $conf, 0); } PVE::Storage::deactivate_volumes($storage_cfg, PVE::LXC::get_vm_volumes($conf)); diff --git a/src/PVE/VZDump/LXC.pm b/src/PVE/VZDump/LXC.pm index b99cd62..77cd9cf 100644 --- a/src/PVE/VZDump/LXC.pm +++ b/src/PVE/VZDump/LXC.pm @@ -130,10 +130,8 @@ sub prepare { &$check_mountpoint_empty($mountpoint); my $volid_list = [$diskinfo->{volid}]; - $task->{cleanup}->{detach_loops} = $volid_list; - my $loopdevs = PVE::LXC::attach_loops($self->{storecfg}, $volid_list); my $mp = { volume => $diskinfo->{volid}, mp => "/" }; - PVE::LXC::mountpoint_mount($mp, $mountpoint, $self->{storecfg}, $loopdevs); + PVE::LXC::mountpoint_mount($mp, $mountpoint, $self->{storecfg}); $diskinfo->{dir} = $diskinfo->{mountpoint} = $mountpoint; $task->{snapdir} = $diskinfo->{dir}; } elsif ($mode eq 'suspend') { @@ -177,13 +175,10 @@ sub snapshot { # my $volid_list = PVE::LXC::get_vm_volumes($snapconf); my $volid_list = [$diskinfo->{volid}]; - $task->{cleanup}->{detach_loops} = $volid_list; - my $loopdevs = PVE::LXC::attach_loops($self->{storecfg}, $volid_list, 'vzdump'); - my $mountpoint = $default_mount_point; my $mp = { volume => $diskinfo->{volid}, mp => "/" }; - PVE::LXC::mountpoint_mount($mp, $mountpoint, $self->{storecfg}, $loopdevs, 'vzdump'); + PVE::LXC::mountpoint_mount($mp, $mountpoint, $self->{storecfg}, 'vzdump'); $diskinfo->{dir} = $diskinfo->{mountpoint} = $mountpoint; $task->{snapdir} = $diskinfo->{dir}; @@ -293,18 +288,6 @@ sub cleanup { PVE::Tools::run_command(['umount', '-l', '-d', $mountpoint]); }; - if (my $volid_list = $task->{cleanup}->{detach_vzdump_snapshot_loops}) { - PVE::LXC::detach_loops($self->{storecfg}, $volid_list, 'vzdump'); - } - - if (my $volid_list = $task->{cleanup}->{detach_loops}) { - if ($task->{cleanup}->{remove_snapshot}) { - PVE::LXC::detach_loops($self->{storecfg}, $volid_list, 'vzdump'); - } else { - PVE::LXC::detach_loops($self->{storecfg}, $volid_list); - } - } - if ($task->{cleanup}->{remove_snapshot}) { $self->loginfo("remove vzdump snapshot"); PVE::LXC::snapshot_delete($vmid, 'vzdump', 0); diff --git a/src/lxc-pve-mount-hook b/src/lxc-pve-mount-hook index c4bccae..b7d84ed 100755 --- a/src/lxc-pve-mount-hook +++ b/src/lxc-pve-mount-hook @@ -89,13 +89,12 @@ __PACKAGE__->register_method ({ my $storage_cfg = PVE::Storage::Plugin->parse_config($fn, $raw); my $bdevs = PVE::LXC::blockdevices_list(); - my $loopdevs = PVE::LXC::loopdevices_list(); my $setup_mountpoint = sub { my ($ms, $mountpoint) = @_; return if $ms eq 'rootfs'; - PVE::LXC::mountpoint_mount($mountpoint, $rootdir, $storage_cfg, $loopdevs); + PVE::LXC::mountpoint_mount($mountpoint, $rootdir, $storage_cfg); }; my $setup_cgroup_device = sub { @@ -104,7 +103,7 @@ __PACKAGE__->register_method ({ my $volid = $mountpoint->{volume}; return if !$volid || $volid =~ m|^/dev/.+|; - my $path = PVE::LXC::mountpoint_mount_path($mountpoint, $storage_cfg, $loopdevs); + my $path = PVE::LXC::mountpoint_mount_path($mountpoint, $storage_cfg); if (-l $path) { $path = readlink($path); diff --git a/src/lxc-pve-prestart-hook b/src/lxc-pve-prestart-hook index 04caff3..d2691eb 100755 --- a/src/lxc-pve-prestart-hook +++ b/src/lxc-pve-prestart-hook @@ -85,7 +85,6 @@ __PACKAGE__->register_method ({ my $loopdevlist = PVE::LXC::get_vm_volumes($conf, 'rootfs'); PVE::Storage::activate_volumes($storage_cfg, $vollist); - PVE::LXC::attach_loops($storage_cfg, $loopdevlist); return undef; }}); -- 2.39.5