зеркало из https://github.com/github/ruby.git
[ruby/fileutils] [DOC] Enhanced RDoc for FileUtils (https://github.com/ruby/fileutils/pull/78)
Treats: ::rm ::rm_f ::rm_r ::rm_rf ::remove_entry_secure https://github.com/ruby/fileutils/commit/ce2a438d75
This commit is contained in:
Родитель
f2f8c0b39b
Коммит
b737998d25
204
lib/fileutils.rb
204
lib/fileutils.rb
|
@ -101,6 +101,57 @@ end
|
|||
# files/directories. This equates to passing the <tt>:noop</tt> and
|
||||
# <tt>:verbose</tt> flags to methods in FileUtils.
|
||||
#
|
||||
# == Avoiding the TOCTTOU Vulnerability
|
||||
#
|
||||
# For certain methods that recursively remove entries,
|
||||
# there is a potential vulnerability called the
|
||||
# {Time-of-check to time-of-use}[https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use],
|
||||
# or TOCTTOU, vulnerability that can exist when:
|
||||
#
|
||||
# - An ancestor directory of the entry at the target path is world writable;
|
||||
# such directories include <tt>/tmp</tt>.
|
||||
# - The directory tree at the target path includes:
|
||||
#
|
||||
# - A world-writable descendant directory.
|
||||
# - A symbolic link.
|
||||
#
|
||||
# To avoid that vulnerability, you can use this method to remove entries:
|
||||
#
|
||||
# - FileUtils.remove_entry_secure: removes recursively
|
||||
# if the target path points to a directory.
|
||||
#
|
||||
# Also available are these methods,
|
||||
# each of which calls \FileUtils.remove_entry_secure:
|
||||
#
|
||||
# - FileUtils.rm_r with keyword argument <tt>secure: true</tt>.
|
||||
# - FileUtils.rm_rf with keyword argument <tt>secure: true</tt>.
|
||||
#
|
||||
# Finally, this method for moving entries calls \FileUtils.remove_entry_secure
|
||||
# if the source and destination are on different devices
|
||||
# (which means that the "move" is really a copy and remove):
|
||||
#
|
||||
# - FileUtils.mv with keyword argument <tt>secure: true</tt>.
|
||||
#
|
||||
# \Method \FileUtils.remove_entry_secure removes securely
|
||||
# by applying a special pre-process:
|
||||
#
|
||||
# - If the target path points to a directory, this method uses
|
||||
# {chown(2)}[https://man7.org/linux/man-pages/man2/chown.2.html]
|
||||
# and {chmod(2)}[https://man7.org/linux/man-pages/man2/chmod.2.html]
|
||||
# in removing directories.
|
||||
# - The owner of the target directory should be either the current process
|
||||
# or the super user (root).
|
||||
#
|
||||
# WARNING: You must ensure that *ALL* parent directories cannot be
|
||||
# moved by other untrusted users. For example, parent directories
|
||||
# should not be owned by untrusted users, and should not be world
|
||||
# writable except when the sticky bit is set.
|
||||
#
|
||||
# For details of this security vulnerability, see Perl cases:
|
||||
#
|
||||
# - {CVE-2005-0448}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448].
|
||||
# - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452].
|
||||
#
|
||||
module FileUtils
|
||||
VERSION = "1.6.0"
|
||||
|
||||
|
@ -197,7 +248,7 @@ module FileUtils
|
|||
#
|
||||
# Creates directories at the paths in the given +list+
|
||||
# (an array of strings or a single string);
|
||||
# returns +list+.
|
||||
# returns +list+ if it is an array, <tt>[list]</tt> otherwise.
|
||||
#
|
||||
# With no keyword arguments, creates a directory at each +path+ in +list+
|
||||
# by calling: <tt>Dir.mkdir(path, mode)</tt>;
|
||||
|
@ -239,7 +290,7 @@ module FileUtils
|
|||
# Creates directories at the paths in the given +list+
|
||||
# (an array of strings or a single string),
|
||||
# also creating ancestor directories as needed;
|
||||
# returns +list+.
|
||||
# returns +list+ if it is an array, <tt>[list]</tt> otherwise.
|
||||
#
|
||||
# With no keyword arguments, creates a directory at each +path+ in +list+,
|
||||
# along with any needed ancestor directories,
|
||||
|
@ -311,7 +362,7 @@ module FileUtils
|
|||
#
|
||||
# Removes directories at the paths in the given +list+
|
||||
# (an array of strings or a single string);
|
||||
# returns +list+.
|
||||
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
||||
#
|
||||
# With no keyword arguments, removes the directory at each +path+ in +list+,
|
||||
# by calling: <tt>Dir.rmdir(path)</tt>;
|
||||
|
@ -865,6 +916,10 @@ module FileUtils
|
|||
# If +src+ and +dest+ are on different devices,
|
||||
# first copies, then removes +src+.
|
||||
#
|
||||
# May cause a local vulnerability if not called with keyword argument
|
||||
# <tt>secure: true</tt>;
|
||||
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
||||
#
|
||||
# If +src+ is the path to a single file or directory and +dest+ does not exist,
|
||||
# moves +src+ to +dest+:
|
||||
#
|
||||
|
@ -898,13 +953,14 @@ module FileUtils
|
|||
# | `-- src.txt
|
||||
# `-- src1.txt
|
||||
#
|
||||
# - <tt>force: true</tt> - attempts to force the move;
|
||||
# if the move includes removing +src+
|
||||
# Keyword arguments:
|
||||
#
|
||||
# - <tt>force: true</tt> - if the move includes removing +src+
|
||||
# (that is, if +src+ and +dest+ are on different devices),
|
||||
# ignores raised exceptions of StandardError and its descendants.
|
||||
# - <tt>noop: true</tt> - does not move files.
|
||||
# - <tt>secure: true</tt> - removes +src+ securely
|
||||
# by calling FileUtils.remove_entry_secure.
|
||||
# - <tt>secure: true</tt> - removes +src+ securely;
|
||||
# see details at FileUtils.remove_entry_secure.
|
||||
# - <tt>verbose: true</tt> - prints an equivalent command:
|
||||
#
|
||||
# FileUtils.mv('src0', 'dest0', noop: true, verbose: true)
|
||||
|
@ -949,13 +1005,29 @@ module FileUtils
|
|||
alias move mv
|
||||
module_function :move
|
||||
|
||||
# Removes entries at the paths in the given +list+
|
||||
# (an array of strings or a single string);
|
||||
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
||||
#
|
||||
# Remove file(s) specified in +list+. This method cannot remove directories.
|
||||
# All StandardErrors are ignored when the :force option is set.
|
||||
# With no keyword arguments, removes files at the paths given in +list+:
|
||||
#
|
||||
# FileUtils.rm %w( junk.txt dust.txt )
|
||||
# FileUtils.rm Dir.glob('*.so')
|
||||
# FileUtils.rm 'NotExistFile', force: true # never raises exception
|
||||
# FileUtils.touch(['src0.txt', 'src0.dat'])
|
||||
# FileUtils.rm(['src0.dat', 'src0.txt']) # => ["src0.dat", "src0.txt"]
|
||||
#
|
||||
# Keyword arguments:
|
||||
#
|
||||
# - <tt>force: true</tt> - ignores raised exceptions of StandardError
|
||||
# and its descendants.
|
||||
# - <tt>noop: true</tt> - does not remove files; returns +nil+.
|
||||
# - <tt>verbose: true</tt> - prints an equivalent command:
|
||||
#
|
||||
# FileUtils.rm(['src0.dat', 'src0.txt'], noop: true, verbose: true)
|
||||
#
|
||||
# Output:
|
||||
#
|
||||
# rm src0.dat src0.txt
|
||||
#
|
||||
# FileUtils.remove is an alias for FileUtils.rm.
|
||||
#
|
||||
def rm(list, force: nil, noop: nil, verbose: nil)
|
||||
list = fu_list(list)
|
||||
|
@ -971,10 +1043,13 @@ module FileUtils
|
|||
alias remove rm
|
||||
module_function :remove
|
||||
|
||||
# Equivalent to:
|
||||
#
|
||||
# Equivalent to
|
||||
# FileUtils.rm(list, force: true, **kwargs)
|
||||
#
|
||||
# FileUtils.rm(list, force: true)
|
||||
# See FileUtils.rm for keyword arguments.
|
||||
#
|
||||
# FileUtils.safe_unlink is an alias for FileUtils.rm_f.
|
||||
#
|
||||
def rm_f(list, noop: nil, verbose: nil)
|
||||
rm list, force: true, noop: noop, verbose: verbose
|
||||
|
@ -984,24 +1059,50 @@ module FileUtils
|
|||
alias safe_unlink rm_f
|
||||
module_function :safe_unlink
|
||||
|
||||
# Removes entries at the paths in the given +list+
|
||||
# (an array of strings or a single string);
|
||||
# returns +list+, if it is an array, <tt>[list]</tt> otherwise.
|
||||
#
|
||||
# remove files +list+[0] +list+[1]... If +list+[n] is a directory,
|
||||
# removes its all contents recursively. This method ignores
|
||||
# StandardError when :force option is set.
|
||||
# May cause a local vulnerability if not called with keyword argument
|
||||
# <tt>secure: true</tt>;
|
||||
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
||||
#
|
||||
# FileUtils.rm_r Dir.glob('/tmp/*')
|
||||
# FileUtils.rm_r 'some_dir', force: true
|
||||
# For each file path, removes the file at that path:
|
||||
#
|
||||
# WARNING: This method causes local vulnerability
|
||||
# if one of parent directories or removing directory tree are world
|
||||
# writable (including /tmp, whose permission is 1777), and the current
|
||||
# process has strong privilege such as Unix super user (root), and the
|
||||
# system has symbolic link. For secure removing, read the documentation
|
||||
# of remove_entry_secure carefully, and set :secure option to true.
|
||||
# Default is <tt>secure: false</tt>.
|
||||
# FileUtils.touch(['src0.txt', 'src0.dat'])
|
||||
# FileUtils.rm_r(['src0.dat', 'src0.txt'])
|
||||
# File.exist?('src0.txt') # => false
|
||||
# File.exist?('src0.dat') # => false
|
||||
#
|
||||
# NOTE: This method calls remove_entry_secure if :secure option is set.
|
||||
# See also remove_entry_secure.
|
||||
# For each directory path, recursively removes files and directories:
|
||||
#
|
||||
# system('tree --charset=ascii src1')
|
||||
# src1
|
||||
# |-- dir0
|
||||
# | |-- src0.txt
|
||||
# | `-- src1.txt
|
||||
# `-- dir1
|
||||
# |-- src2.txt
|
||||
# `-- src3.txt
|
||||
# FileUtils.rm_r('src1')
|
||||
# File.exist?('src1') # => false
|
||||
#
|
||||
# Keyword arguments:
|
||||
#
|
||||
# - <tt>force: true</tt> - ignores raised exceptions of StandardError
|
||||
# and its descendants.
|
||||
# - <tt>noop: true</tt> - does not remove entries; returns +nil+.
|
||||
# - <tt>secure: true</tt> - removes +src+ securely;
|
||||
# see details at FileUtils.remove_entry_secure.
|
||||
# - <tt>verbose: true</tt> - prints an equivalent command:
|
||||
#
|
||||
# FileUtils.rm_r(['src0.dat', 'src0.txt'], noop: true, verbose: true)
|
||||
# FileUtils.rm_r('src1', noop: true, verbose: true)
|
||||
#
|
||||
# Output:
|
||||
#
|
||||
# rm -r src0.dat src0.txt
|
||||
# rm -r src1
|
||||
#
|
||||
def rm_r(list, force: nil, noop: nil, verbose: nil, secure: nil)
|
||||
list = fu_list(list)
|
||||
|
@ -1017,13 +1118,17 @@ module FileUtils
|
|||
end
|
||||
module_function :rm_r
|
||||
|
||||
# Equivalent to:
|
||||
#
|
||||
# Equivalent to
|
||||
# FileUtils.rm_r(list, force: true, **kwargs)
|
||||
#
|
||||
# FileUtils.rm_r(list, force: true)
|
||||
# May cause a local vulnerability if not called with keyword argument
|
||||
# <tt>secure: true</tt>;
|
||||
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
||||
#
|
||||
# WARNING: This method causes local vulnerability.
|
||||
# Read the documentation of rm_r first.
|
||||
# See FileUtils.rm_r for keyword arguments.
|
||||
#
|
||||
# FileUtils.rmtree is an alias for FileUtils.rm_rf.
|
||||
#
|
||||
def rm_rf(list, noop: nil, verbose: nil, secure: nil)
|
||||
rm_r list, force: true, noop: noop, verbose: verbose, secure: secure
|
||||
|
@ -1033,37 +1138,12 @@ module FileUtils
|
|||
alias rmtree rm_rf
|
||||
module_function :rmtree
|
||||
|
||||
# Securely removes the entry given by +path+,
|
||||
# which should be the entry for a regular file, a symbolic link,
|
||||
# or a directory.
|
||||
#
|
||||
# This method removes a file system entry +path+. +path+ shall be a
|
||||
# regular file, a directory, or something. If +path+ is a directory,
|
||||
# remove it recursively. This method is required to avoid TOCTTOU
|
||||
# (time-of-check-to-time-of-use) local security vulnerability of rm_r.
|
||||
# #rm_r causes security hole when:
|
||||
#
|
||||
# * Parent directory is world writable (including /tmp).
|
||||
# * Removing directory tree includes world writable directory.
|
||||
# * The system has symbolic link.
|
||||
#
|
||||
# To avoid this security hole, this method applies special preprocess.
|
||||
# If +path+ is a directory, this method chown(2) and chmod(2) all
|
||||
# removing directories. This requires the current process is the
|
||||
# owner of the removing whole directory tree, or is the super user (root).
|
||||
#
|
||||
# WARNING: You must ensure that *ALL* parent directories cannot be
|
||||
# moved by other untrusted users. For example, parent directories
|
||||
# should not be owned by untrusted users, and should not be world
|
||||
# writable except when the sticky bit set.
|
||||
#
|
||||
# WARNING: Only the owner of the removing directory tree, or Unix super
|
||||
# user (root) should invoke this method. Otherwise this method does not
|
||||
# work.
|
||||
#
|
||||
# For details of this security vulnerability, see Perl's case:
|
||||
#
|
||||
# * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
|
||||
# * https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
|
||||
#
|
||||
# For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
|
||||
# Avoids a local vulnerability that can exist in certain circumstances;
|
||||
# see {Avoiding the TOCTTOU Vulnerability}[rdoc-ref:FileUtils@Avoiding+the+TOCTTOU+Vulnerability].
|
||||
#
|
||||
def remove_entry_secure(path, force = false)
|
||||
unless fu_have_symlink?
|
||||
|
|
Загрузка…
Ссылка в новой задаче