89bd5b4791
[#50179803] [SeeRM #7967] [SeeRM #7870] Because metasploit-framework runs migrations with the same process and with the same connection as it later accesses the database, the column information can become cached prematurely and be incorrect by the end of the migrations. Fix the bad cache by automatically resetting the column information for all model classes after the migrations have run.
58 lines
1.7 KiB
Ruby
58 lines
1.7 KiB
Ruby
module Msf
|
|
class DBManager
|
|
module Migration
|
|
# Migrate database to latest schema version.
|
|
#
|
|
# @param verbose [Boolean] see ActiveRecord::Migration.verbose
|
|
# @return [Array<ActiveRecord::MigrationProxy] List of migrations that
|
|
# ran.
|
|
#
|
|
# @see ActiveRecord::Migrator.migrate
|
|
def migrate(verbose=false)
|
|
ran = []
|
|
ActiveRecord::Migration.verbose = verbose
|
|
|
|
ActiveRecord::Base.connection_pool.with_connection do
|
|
begin
|
|
ran = ActiveRecord::Migrator.migrate(
|
|
ActiveRecord::Migrator.migrations_paths
|
|
)
|
|
# ActiveRecord::Migrator#migrate rescues all errors and re-raises them
|
|
# as StandardError
|
|
rescue StandardError => error
|
|
self.error = error
|
|
elog("DB.migrate threw an exception: #{error}")
|
|
dlog("Call stack:\n#{error.backtrace.join "\n"}")
|
|
end
|
|
end
|
|
|
|
# Since the connections that existed before the migrations ran could
|
|
# have outdated column information, reset column information for all
|
|
# ActiveRecord::Base descendents to prevent missing method errors for
|
|
# column methods for columns created in migrations after the column
|
|
# information was cached.
|
|
reset_column_information
|
|
|
|
return ran
|
|
end
|
|
|
|
# Flag to indicate database migration has completed
|
|
#
|
|
# @return [Boolean]
|
|
attr_accessor :migrated
|
|
|
|
private
|
|
|
|
# Resets the column information for all descendants of ActiveRecord::Base
|
|
# since some of the migrations may have cached column information that
|
|
# has been updated by later migrations.
|
|
#
|
|
# @return [void]
|
|
def reset_column_information
|
|
ActiveRecord::Base.descendants.each do |descendant|
|
|
descendant.reset_column_information
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end |