summaryrefslogtreecommitdiff
path: root/lib/rubygems/package.rb
diff options
context:
space:
mode:
authorDavid Rodríguez <deivid.rodriguez@riseup.net>2021-10-06 18:17:37 +0200
committergit <svn-admin@ruby-lang.org>2021-10-10 23:12:47 +0900
commitbbcf8f87ac50be423991ccbb2d83ac09ebecf46a (patch)
treece9e1153cc80d6c0d5ef0282813f4f637d885d4b /lib/rubygems/package.rb
parenta5289bfa71d85d7c3ab1ebf94237edecd847851b (diff)
[ruby/rubygems] Check safety of packaged symlinks
If we explicitly disallow the creation of symlinks that point to files outside of the destination directory, we can avoid any other safety checks while creating directories, because we can be sure they will always fall under the destination directory as well. https://github.com/rubygems/rubygems/commit/555692b8de
Diffstat (limited to 'lib/rubygems/package.rb')
-rw-r--r--lib/rubygems/package.rb33
1 files changed, 16 insertions, 17 deletions
diff --git a/lib/rubygems/package.rb b/lib/rubygems/package.rb
index 7f843f4e0a..0ca272e099 100644
--- a/lib/rubygems/package.rb
+++ b/lib/rubygems/package.rb
@@ -71,6 +71,13 @@ class Gem::Package
end
end
+ class SymlinkError < Error
+ def initialize(name, destination, destination_dir)
+ super "installing symlink '%s' pointing to parent path %s of %s is not allowed" %
+ [name, destination, destination_dir]
+ end
+ end
+
class NonSeekableIO < Error; end
class TooLongFileName < Error; end
@@ -407,6 +414,14 @@ EOM
destination = install_location entry.full_name, destination_dir
+ if entry.symlink?
+ link_target = entry.header.linkname
+ real_destination = link_target.start_with?("/") ? link_target : File.expand_path(link_target, File.dirname(destination))
+
+ raise Gem::Package::SymlinkError.new(entry.full_name, real_destination, destination_dir) unless
+ normalize_path(real_destination).start_with? normalize_path(destination_dir + '/')
+ end
+
FileUtils.rm_rf destination
mkdir_options = {}
@@ -419,7 +434,7 @@ EOM
end
unless directories.include?(mkdir)
- mkdir_p_safe mkdir, mkdir_options, destination_dir, entry.full_name
+ FileUtils.mkdir_p mkdir, **mkdir_options
directories << mkdir
end
@@ -495,22 +510,6 @@ EOM
end
end
- def mkdir_p_safe(mkdir, mkdir_options, destination_dir, file_name)
- destination_dir = File.realpath(File.expand_path(destination_dir))
- parts = mkdir.split(File::SEPARATOR)
- parts.reduce do |path, basename|
- path = File.realpath(path) unless path == ""
- path = File.expand_path(path + File::SEPARATOR + basename)
- lstat = File.lstat path rescue nil
- if !lstat || !lstat.directory?
- unless normalize_path(path).start_with? normalize_path(destination_dir) and (FileUtils.mkdir path, **mkdir_options rescue false)
- raise Gem::Package::PathError.new(file_name, destination_dir)
- end
- end
- path
- end
- end
-
##
# Loads a Gem::Specification from the TarEntry +entry+