Skip to content

Commit 85dd212

Browse files
committed
Merge branch 'bug/wrong-file_changed-argument' into rapid7
[Closes rapid7#965]
2 parents 04668c7 + 4a1087d commit 85dd212

File tree

15 files changed

+2106
-34
lines changed

15 files changed

+2106
-34
lines changed

lib/fastlib.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,12 +182,14 @@ def self.fastlib_filter_encode(lib, buff)
182182
end
183183

184184

185+
# This method provides a way to create a FASTLIB archive programatically.
185186
#
186-
# This method provides a way to create a FASTLIB archive programatically,
187-
# the key arguments are the name of the destination archive, the base
188-
# directory that should be excluded from the archived path, and finally
189-
# the list of specific files and directories to include in the archive.
190-
#
187+
# @param [String] lib the output path for the archive
188+
# @param [String] flag a string containing the hex values for the flags ({FLAG_COMPRESS} and {FLAG_ENCRYPT}).
189+
# @param [String] bdir the path to the base directory which will be stripped from all paths included in the archive
190+
# @param [Array<String>] dirs list of directories/files to pack into the archive. All dirs should be under bdir so
191+
# that the paths are stripped correctly.
192+
# @return [void]
191193
def self.dump(lib, flag, bdir, *dirs)
192194
head = ""
193195
data = ""

lib/msf/core/module_manager/loading.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ module Msf::ModuleManager::Loading
2626
def file_changed?(path)
2727
changed = false
2828

29-
module_details = self.module_info_by_path[path]
29+
module_info = self.module_info_by_path[path]
3030

3131
# if uncached then it counts as changed
3232
# Payloads can't be cached due to stage/stager matching
33-
if module_details.nil? or module_details[:mtype] == Msf::MODULE_PAYLOAD
33+
if module_info.nil? or module_info[:type] == Msf::MODULE_PAYLOAD
3434
changed = true
3535
else
3636
begin
@@ -39,7 +39,7 @@ def file_changed?(path)
3939
# if the file does not exist now, that's a change
4040
changed = true
4141
else
42-
cached_modification_time = module_details[:mtime].to_i
42+
cached_modification_time = module_info[:modification_time].to_i
4343

4444
# if the file's modification time's different from the cache, then it's changed
4545
if current_modification_time != cached_modification_time

lib/msf/core/modules/loader/archive.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def each_module_reference_name(path)
4141
type = entry.split('/', 2)[0]
4242
type = type.singularize
4343

44-
unless module_manager.enablement_by_type[type]
44+
unless module_manager.type_enabled?(type)
4545
next
4646
end
4747

lib/msf/core/modules/loader/base.rb

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#
44
require 'msf/core/modules/loader'
55
require 'msf/core/modules/namespace'
6+
require 'msf/core/modules/version_compatibility_error'
67

78
# Responsible for loading modules for {Msf::ModuleManager}.
89
#
@@ -77,7 +78,6 @@ def loadable?(path)
7778
raise ::NotImplementedError
7879
end
7980

80-
8181
# Loads a module from the supplied path and module_reference_name.
8282
#
8383
# @param [String] parent_path The path under which the module exists. This is not necessarily the same path as passed
@@ -104,14 +104,18 @@ def load_module(parent_path, type, module_reference_name, options={})
104104
force = options[:force] || false
105105
reload = options[:reload] || false
106106

107-
unless force or module_manager.file_changed?(parent_path)
108-
dlog("Cached module from #{parent_path} has not changed.", 'core', LEV_2)
107+
module_path = self.module_path(parent_path, type, module_reference_name)
108+
file_changed = module_manager.file_changed?(module_path)
109+
110+
unless force or file_changed
111+
dlog("Cached module from #{module_path} has not changed.", 'core', LEV_2)
109112

110113
return false
111114
end
112115

116+
reload ||= force || file_changed
117+
113118
metasploit_class = nil
114-
module_path = self.module_path(parent_path, type, module_reference_name)
115119

116120
loaded = namespace_module_transaction(type + "/" + module_reference_name, :reload => reload) { |namespace_module|
117121
# set the parent_path so that the module can be reloaded with #load_module
@@ -121,7 +125,7 @@ def load_module(parent_path, type, module_reference_name, options={})
121125

122126
begin
123127
namespace_module.module_eval_with_lexical_scope(module_content, module_path)
124-
# handle interrupts as pass-throughs unlike other Exceptions
128+
# handle interrupts as pass-throughs unlike other Exceptions so users can bail with Ctrl+C
125129
rescue ::Interrupt
126130
raise
127131
rescue ::Exception => error
@@ -191,6 +195,11 @@ def load_module(parent_path, type, module_reference_name, options={})
191195
# not trigger an ambiguous name warning, which would cause the reloaded module to not be stored in the
192196
# ModuleManager.
193197
module_manager.delete(module_reference_name)
198+
199+
# Delete the original copy of the module in the type-specific module set stores the reloaded module and doesn't
200+
# trigger an ambiguous name warning
201+
module_set = module_manager.module_set(type)
202+
module_set.delete(module_reference_name)
194203
end
195204

196205
# Do some processing on the loaded module to get it into the right associations
@@ -290,7 +299,6 @@ def reload_module(original_metasploit_class_or_instance)
290299

291300
dlog("Reloading module #{module_reference_name}...", 'core')
292301

293-
294302
if load_module(parent_path, type, module_reference_name, :force => true, :reload => true)
295303
# Create a new instance of the module
296304
reloaded_module_instance = module_manager.create(module_reference_name)
@@ -486,20 +494,18 @@ def namespace_module_transaction(uniq_module_reference_name, options={}, &block)
486494
elog("Reloading namespace_module #{previous_namespace_module} when :reload => false")
487495
end
488496

497+
relative_name = namespace_module_names.last
498+
489499
if previous_namespace_module
490500
parent_module = previous_namespace_module.parent
491-
relative_name = namespace_module_names.last
492-
493-
# remove_const is private, so invoke in instance context
494-
parent_module.instance_eval do
495-
remove_const relative_name
496-
end
497-
else
498-
parent_module = nil
499-
relative_name = namespace_module_names.last
501+
# remove_const is private, so use send to bypass
502+
parent_module.send(:remove_const, relative_name)
500503
end
501504

502505
namespace_module = create_namespace_module(namespace_module_names)
506+
# Get the parent module from the created module so that restore_namespace_module can remove namespace_module's
507+
# constant if needed.
508+
parent_module = namespace_module.parent
503509

504510
begin
505511
loaded = block.call(namespace_module)
@@ -534,19 +540,29 @@ def read_module_content(parent_path, type, module_reference_name)
534540
#
535541
# @param [Module] parent_module The .parent of namespace_module before it was removed from the constant tree.
536542
# @param [String] relative_name The name of the constant under parent_module where namespace_module was attached.
537-
# @param [Module] namespace_module The previous namespace module containing the old module content.
543+
# @param [Module, nil] namespace_module The previous namespace module containing the old module content. If `nil`,
544+
# then the relative_name constant is removed from parent_module, but nothing is set as the new constant.
538545
# @return [void]
539546
def restore_namespace_module(parent_module, relative_name, namespace_module)
540-
if parent_module and namespace_module
541-
# the const may have been redefined by {#create_namespace_module}, in which case that new namespace_module needs
542-
# to be removed so the original can replace it.
543-
if parent_module.const_defined? relative_name
544-
parent_module.instance_eval do
545-
remove_const relative_name
546-
end
547+
if parent_module
548+
# If there is a current module with relative_name
549+
if parent_module.const_defined?(relative_name)
550+
# if the current value isn't the value to be restored.
551+
if parent_module.const_get(relative_name) != namespace_module
552+
# remove_const is private, so use send to bypass
553+
parent_module.send(:remove_const, relative_name)
554+
555+
# if there was a previous module, not set it to the name
556+
if namespace_module
557+
parent_module.const_set(relative_name, namespace_module)
558+
end
559+
end
560+
else
561+
# if there was a previous module, but there isn't a current module, then restore the previous module
562+
if namespace_module
563+
parent_module.const_set(relative_name, namespace_module)
564+
end
547565
end
548-
549-
parent_module.const_set(relative_name, namespace_module)
550566
end
551567
end
552568

0 commit comments

Comments
 (0)