From: Wolfgang Bumiller Date: Fri, 3 Jun 2016 07:54:04 +0000 (+0200) Subject: fix and improve bindmount tests X-Git-Url: https://git.proxmox.com/?p=pve-container.git;a=commitdiff_plain;h=6c25d5bb05dc0cd29baeb59deaa5eaf22188f0eb fix and improve bindmount tests fixed leftover mounts after running the tests added another testcase: inject symlink before mount() and restore before verify() --- diff --git a/src/test/bindmount_test.pl b/src/test/bindmount_test.pl index a6052db..83152e9 100755 --- a/src/test/bindmount_test.pl +++ b/src/test/bindmount_test.pl @@ -20,23 +20,29 @@ my $a = "/tmpshare/a"; my $ab = "/tmpshare/a/b"; my $abc = "/tmpshare/a/b/c"; my $sym = "/tmpshare/sym"; +my $tmp = "/tmpshare/tmp"; my $secret = "/secret"; -END { +END { cleanup(); }; +sub cleanup { my $ignore_error; File::Path::rmtree("$pwd/$rootdir", {error => \$ignore_error}); File::Path::rmtree("$pwd/$sharedir", {error => \$ignore_error}); File::Path::rmtree("$pwd/$secret", {error => \$ignore_error}); -}; +} + +sub setup { + # Create all the test paths... + PVE::LXC::walk_tree_nofollow('.', $rootdir, 1); + PVE::LXC::walk_tree_nofollow($rootdir, $destdir, 1); + PVE::LXC::walk_tree_nofollow('.', $abc, 1); + PVE::LXC::walk_tree_nofollow('.', $secret, 1); + # Create one evil symlink + symlink('a/b', "$pwd/$sym") or die "failed to prepare test folders: $!\n"; +} -# Create all the test paths... -PVE::LXC::walk_tree_nofollow('.', $rootdir, 1); -PVE::LXC::walk_tree_nofollow($rootdir, $destdir, 1); -PVE::LXC::walk_tree_nofollow('.', $abc, 1); -PVE::LXC::walk_tree_nofollow('.', $secret, 1); -# Create one evil symlink -symlink('a/b', "$pwd/$sym") or die "failed to prepare test folders: $!\n"; +setup(); # Test walk_tree_nofollow: eval { PVE::LXC::walk_tree_nofollow('.', $rootdir, 0) }; @@ -47,7 +53,7 @@ die "unexpected test error: '$@'\n" if $@ ne "symlink encountered at: .$sym\n"; # Bindmount testing: sub bindmount { - my ($from, $rootdir, $destdir, $inject, $ro, $inject_write) = @_; + my ($from, $rootdir, $destdir, $inject, $ro, $inject_write, $restore) = @_; my ($mpath, $mpfd, $parentfd, $last); ($rootdir, $mpath, $mpfd, $parentfd, $last) = @@ -56,21 +62,36 @@ sub bindmount { my $srcdh = PVE::LXC::__bindmount_prepare('.', $from); if ($inject) { - File::Path::rmtree(".$inject"); - symlink("$pwd/$secret", ".$inject") - or die "failed to create symlink\n"; - PVE::LXC::walk_tree_nofollow('.', $from, 1); + if ($restore) { + rename(".$inject", ".$tmp") + or die "failed to move directory: $!\n"; + } else { + File::Path::rmtree(".$inject"); + } + symlink("$pwd/$secret", ".$inject") + or die "failed to create symlink\n"; + File::Path::mkpath(".$from"); } - PVE::LXC::__bindmount_do(".$from", $mpath, $inject_write ? 0 : $ro); - - my $res = PVE::LXC::__bindmount_verify($srcdh, $parentfd, $last, $ro); - + eval { + PVE::LXC::__bindmount_do(".$from", $mpath, $inject_write ? 0 : $ro); + + if ($restore) { + unlink(".$inject") or die "failed to restore path: $!\n"; + rename(".$tmp", ".$inject") or die "failed to restore path: $!\n"; + } + + PVE::LXC::__bindmount_verify($srcdh, $parentfd, $last, $ro) + or die "bindmount verification failed\n"; + }; + my $err = $@; system('umount', $mpath); + die $err if $err; } bindmount($a, $rootdir, $destdir, undef, 0, 0); eval { bindmount($sym, $rootdir, $destdir, undef, 0, 0) }; die "illegal symlink bindmount went through\n" if !$@; +die "unexpected test error: $@\n" if $@ ne "symlink encountered at: .$sym\n"; bindmount($abc, $rootdir, $destdir, undef, 0, 0); # Race test: Assume someone exchanged 2 equivalent bind mounts between and # after the bindmount_do()'s mount and remount calls. @@ -86,4 +107,11 @@ die "unexpected test error: $@\n" if $@ ne "failed to mark bind mount read only\ # __bindmount_do(). eval { bindmount($abc, $rootdir, $destdir, $ab, 0, 0) }; die "injected symlink bindmount went through\n" if !$@; -die "unexpected test error: $@\n" if $@ ne "symlink encountered at: .$ab\n"; +die "unexpected test error: $@\n" if $@ ne "bindmount verification failed\n"; +# Restore setup: +cleanup(); +setup(); +# Race test 2: As above but also reset the symlink back after __bindmount_do() +eval { bindmount($abc, $rootdir, $destdir, $ab, 0, 0, 1) }; +die "injected symlink bindmount went through\n" if !$@; +die "unexpected test error: $@\n" if $@ ne "bindmount verification failed\n";