openstudiocore/ruby/openstudio/sketchup_plugin/stdruby/fileutils.rb
def remove_entry_secure(path, force = false)
    unless fu_have_symlink?
      remove_entry path, force
      return
    end
    fullpath = File.expand_path(path)
    st = File.lstat(fullpath)
    unless st.directory?
      File.unlink fullpath
      return
    end
    # is a directory.
    parent_st = File.stat(File.dirname(fullpath))
    unless fu_world_writable?(parent_st)
      remove_entry path, force
      return
    end
    unless parent_st.sticky?
      raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
    end
    # freeze tree root
    euid = Process.euid
    File.open(fullpath + '/.') {|f|
      unless fu_stat_identical_entry?(st, f.stat)
        # symlink (TOC-to-TOU attack?)
        File.unlink fullpath
        return
      end
      f.chown euid, -1
      f.chmod 0700
    }
    # ---- tree root is frozen ----
    root = Entry_.new(path)
    root.preorder_traverse do |ent|
      if ent.directory?
        ent.chown euid, -1
        ent.chmod 0700
      end
    end
    root.postorder_traverse do |ent|
      begin
        ent.remove
      rescue
        raise unless force
      end
    end
  rescue
    raise unless force
  end
#
# 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 are not
# world writable.  Otherwise this method does not work.
# Only exception is temporary directory like /tmp and /var/tmp,
# whose permission is 1777.
#
# 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:
#
#   http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2005-0448
#   http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452
#
# For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
#

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.

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).

You must ensure that *ALL* parent directories are not
world writable.  Otherwise this method does not work.
Only exception is temporary directory like /tmp and /var/tmp,
whose permission is 1777.

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.



For fileutils.rb, this vulnerability is reported in [ruby-dev:26100].
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 . 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 ) . You must ensure that * ALL * parent directories are not world writable . Otherwise this method does not work . Only exception is temporary directory like / tmp and / var / tmp whose permission is 1777 . 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 . For fileutils . rb this vulnerability is reported in [ ruby - dev : 26100 ] .
def remove_entry_secure(path, force = false)
    unless fu_have_symlink?
      remove_entry path, force
      return
    end
    fullpath = File.expand_path(path)
    st = File.lstat(fullpath)
    unless st.directory?
      File.unlink fullpath
      return
    end
    parent_st = File.stat(File.dirname(fullpath))
    unless fu_world_writable?(parent_st)
      remove_entry path, force
      return
    end
    unless parent_st.sticky?
      raise ArgumentError, "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})"
    end
    euid = Process.euid
    File.open(fullpath + '/.') {|f|
      unless fu_stat_identical_entry?(st, f.stat)
        File.unlink fullpath
        return
      end
      f.chown euid, -1
      f.chmod 0700
    }
    root = Entry_.new(path)
    root.preorder_traverse do |ent|
      if ent.directory?
        ent.chown euid, -1
        ent.chmod 0700
      end
    end
    root.postorder_traverse do |ent|
      begin
        ent.remove
      rescue
        raise unless force
      end
    end
  rescue
    raise unless force
  end
def remove_entry_secure ( path , force = false ) unless fu_have_symlink? remove_entry path , force return end fullpath = File . expand_path ( path ) st = File . lstat ( fullpath ) unless st . directory? File . unlink fullpath return end parent_st = File . stat ( File . dirname ( fullpath ) ) unless fu_world_writable? ( parent_st ) remove_entry path , force return end unless parent_st . sticky? raise ArgumentError , "parent directory is world writable, FileUtils#remove_entry_secure does not work; abort: #{path.inspect} (parent directory mode #{'%o' % parent_st.mode})" end euid = Process . euid File . open ( fullpath + '/.' ) { | f | unless fu_stat_identical_entry? ( st , f . stat ) File . unlink fullpath return end f . chown euid , - 1 f . chmod 0700 } root = Entry_ . new ( path ) root . preorder_traverse do | ent | if ent . directory? ent . chown euid , - 1 ent . chmod 0700 end end root . postorder_traverse do | ent | begin ent . remove rescue raise unless force end end rescue raise unless force end
This method removes a file system entry +path+.
This method removes a file system entry + path + .
# is a directory.
 # freeze tree root
 # symlink (TOC-to-TOU attack?)
 # ---- tree root is frozen ----

path
force