diff options
author | David RodrÃguez <deivid.rodriguez@riseup.net> | 2021-10-06 18:17:37 +0200 |
---|---|---|
committer | git <svn-admin@ruby-lang.org> | 2021-10-10 23:12:47 +0900 |
commit | bbcf8f87ac50be423991ccbb2d83ac09ebecf46a (patch) | |
tree | ce9e1153cc80d6c0d5ef0282813f4f637d885d4b /lib/rubygems/package.rb | |
parent | a5289bfa71d85d7c3ab1ebf94237edecd847851b (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.rb | 33 |
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+ |