summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorKJ Tsanaktsidis <kj@kjtsanaktsidis.id.au>2024-08-08 21:24:13 +1000
committerKJ Tsanaktsidis <kj@kjtsanaktsidis.id.au>2024-08-23 09:34:41 +1000
commit8800127d80fb1063a186ced65af445e79a518924 (patch)
treea708756994a29730cd7c63e187586bb2be4ffc60 /test
parent165635049a2f5af83efe2bd64b08e7b59e925e18 (diff)
Skip some tests which don't work under permissionless containers
When running as UID 0 but without CAP_DAC_OVERRIDE (for example, in a docker container running with --uid 0 but --cap-drop=all), these tests won't work because of hard-coded assumptions about what uid 0 can and can't do.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/11402
Diffstat (limited to 'test')
-rw-r--r--test/fileutils/test_fileutils.rb16
-rw-r--r--test/ruby/test_file_exhaustive.rb19
2 files changed, 31 insertions, 4 deletions
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index 481f913d0c..d2096a04cc 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -93,12 +93,24 @@ class TestFileUtils < Test::Unit::TestCase
@@no_broken_symlink
end
+ def has_capsh?
+ !!system('capsh', '--print', out: File::NULL, err: File::NULL)
+ end
+
+ def has_root_file_capabilities?
+ !!system(
+ 'capsh', '--has-p=CAP_DAC_OVERRIDE', '--has-p=CAP_CHOWN', '--has-p=CAP_FOWNER',
+ out: File::NULL, err: File::NULL
+ )
+ end
+
def root_in_posix?
if /cygwin/ =~ RUBY_PLATFORM
# FIXME: privilege if groups include root user?
return Process.groups.include?(0)
- end
- if Process.respond_to?('uid')
+ elsif has_capsh?
+ return has_root_file_capabilities?
+ elsif Process.respond_to?('uid')
return Process.uid == 0
else
return false
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index de09811946..f3068cb189 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -186,6 +186,12 @@ class TestFileExhaustive < Test::Unit::TestCase
@blockdev
end
+ def root_without_capabilities?
+ return false unless Process.uid == 0
+ return false unless system('command', '-v', 'capsh', out: File::NULL)
+ !system('capsh', '--has-p=CAP_DAC_OVERRIDE', out: File::NULL, err: File::NULL)
+ end
+
def test_path
[regular_file, utf8_file].each do |file|
assert_equal(file, File.open(file) {|f| f.path})
@@ -1538,8 +1544,17 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(stat.size?, File.size?(f), f)
assert_bool_equal(stat.socket?, File.socket?(f), f)
assert_bool_equal(stat.setuid?, File.setuid?(f), f)
- assert_bool_equal(stat.writable?, File.writable?(f), f)
- assert_bool_equal(stat.writable_real?, File.writable_real?(f), f)
+ # It's possible in Linux to be uid 0, but not to have the CAP_DAC_OVERRIDE
+ # capability that allows skipping file permissions checks (e.g. some kinds
+ # of "rootless" container setups). In these cases, stat.writable? will be
+ # true (because it always returns true if Process.uid == 0), but
+ # File.writeable? will be false (because it actually asks the kernel to do
+ # an access check).
+ # Skip these two assertions in that case.
+ unless root_without_capabilities?
+ assert_bool_equal(stat.writable?, File.writable?(f), f)
+ assert_bool_equal(stat.writable_real?, File.writable_real?(f), f)
+ end
assert_bool_equal(stat.executable?, File.executable?(f), f)
assert_bool_equal(stat.executable_real?, File.executable_real?(f), f)
assert_bool_equal(stat.zero?, File.zero?(f), f)