Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.6.1 security issues #43

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 6 additions & 35 deletions libraries/chain/controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ struct controller_impl {
* are removed from this list if they are re-applied in other blocks. Producers
* can query this list when scheduling new transactions into blocks.
*/
map<digest_type, transaction_metadata_ptr> unapplied_transactions;
unapplied_transactions_type unapplied_transactions;

// async on thread_pool and return future
template<typename F>
Expand Down Expand Up @@ -2241,41 +2241,12 @@ const account_object& controller::get_account( account_name name )const
return my->db.get<account_object, by_name>(name);
} FC_CAPTURE_AND_RETHROW( (name) ) }

vector<transaction_metadata_ptr> controller::get_unapplied_transactions() const {
vector<transaction_metadata_ptr> result;
if ( my->read_mode == db_read_mode::SPECULATIVE ) {
result.reserve(my->unapplied_transactions.size());
for ( const auto& entry: my->unapplied_transactions ) {
result.emplace_back(entry.second);
}
} else {
EOS_ASSERT( my->unapplied_transactions.empty(), transaction_exception, "not empty unapplied_transactions in non-speculative mode" ); //should never happen
}
return result;
}

void controller::drop_unapplied_transaction(const transaction_metadata_ptr& trx) {
my->unapplied_transactions.erase(trx->signed_id);
}

void controller::drop_all_unapplied_transactions() {
my->unapplied_transactions.clear();
}

vector<transaction_id_type> controller::get_scheduled_transactions() const {
const auto& idx = db().get_index<generated_transaction_multi_index,by_delay>();

vector<transaction_id_type> result;

static const size_t max_reserve = 64;
result.reserve(std::min(idx.size(), max_reserve));

auto itr = idx.begin();
while( itr != idx.end() && itr->delay_until <= pending_block_time() ) {
result.emplace_back(itr->trx_id);
++itr;
unapplied_transactions_type& controller::get_unapplied_transactions() {
if ( my->read_mode != db_read_mode::SPECULATIVE ) {
EOS_ASSERT( my->unapplied_transactions.empty(), transaction_exception,
"not empty unapplied_transactions in non-speculative mode" ); //should never happen
}
return result;
return my->unapplied_transactions;
}

bool controller::sender_avoids_whitelist_blacklist_enforcement( account_name sender )const {
Expand Down
18 changes: 3 additions & 15 deletions libraries/chain/include/eosio/chain/controller.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace eosio { namespace chain {
class account_object;
using resource_limits::resource_limits_manager;
using apply_handler = std::function<void(apply_context&)>;
using unapplied_transactions_type = map<transaction_id_type, transaction_metadata_ptr>;

class fork_database;

Expand Down Expand Up @@ -124,22 +125,9 @@ namespace eosio { namespace chain {
* The caller is responsible for calling drop_unapplied_transaction on a failing transaction that
* they never intend to retry
*
* @return vector of transactions which have been unapplied
* @return map of transactions which have been unapplied
*/
vector<transaction_metadata_ptr> get_unapplied_transactions() const;
void drop_unapplied_transaction(const transaction_metadata_ptr& trx);
void drop_all_unapplied_transactions();

/**
* These transaction IDs represent transactions available in the head chain state as scheduled
* or otherwise generated transactions.
*
* calling push_scheduled_transaction with these IDs will remove the associated transaction from
* the chain state IFF it succeeds or objectively fails
*
* @return
*/
vector<transaction_id_type> get_scheduled_transactions() const;
unapplied_transactions_type& get_unapplied_transactions();

/**
*
Expand Down
11 changes: 7 additions & 4 deletions libraries/chain/include/eosio/chain/wasm_eosio_injection.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ namespace eosio { namespace chain { namespace wasm_injections {

};

struct call_depth_check {
struct call_depth_check_and_insert_checktime {
static constexpr bool kills = true;
static constexpr bool post = false;
static int32_t global_idx;
Expand All @@ -290,6 +290,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
injector_utils::add_import<ResultType::none>(*(arg.module), "call_depth_assert", assert_idx);

wasm_ops::op_types<>::call_t call_assert;
wasm_ops::op_types<>::call_t call_checktime;
wasm_ops::op_types<>::get_global_t get_global_inst;
wasm_ops::op_types<>::set_global_t set_global_inst;

Expand All @@ -301,6 +302,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
wasm_ops::op_types<>::else__t else_inst;

call_assert.field = assert_idx;
call_checktime.field = checktime_injection::chktm_idx;
get_global_inst.field = global_idx;
set_global_inst.field = global_idx;
const_inst.field = -1;
Expand Down Expand Up @@ -334,6 +336,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
INSERT_INJECTED(const_inst);
INSERT_INJECTED(add_inst);
INSERT_INJECTED(set_global_inst);
INSERT_INJECTED(call_checktime);

#undef INSERT_INJECTED
}
Expand Down Expand Up @@ -679,8 +682,8 @@ namespace eosio { namespace chain { namespace wasm_injections {
};

struct pre_op_injectors : wasm_ops::op_types<pass_injector> {
using call_t = wasm_ops::call <call_depth_check>;
using call_indirect_t = wasm_ops::call_indirect <call_depth_check>;
using call_t = wasm_ops::call <call_depth_check_and_insert_checktime>;
using call_indirect_t = wasm_ops::call_indirect <call_depth_check_and_insert_checktime>;

// float binops
using f32_add_t = wasm_ops::f32_add <f32_binop_injector<wasm_ops::f32_add_code>>;
Expand Down Expand Up @@ -785,7 +788,7 @@ namespace eosio { namespace chain { namespace wasm_injections {
// initialize static fields of injectors
injector_utils::init( mod );
checktime_injection::init();
call_depth_check::init();
call_depth_check_and_insert_checktime::init();
}

void inject() {
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/wasm_eosio_injection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ void max_memory_injection_visitor::inject( Module& m ) {
}
void max_memory_injection_visitor::initializer() {}

int32_t call_depth_check::global_idx = -1;
int32_t call_depth_check_and_insert_checktime::global_idx = -1;
uint32_t instruction_counter::icnt = 0;
uint32_t instruction_counter::tcnt = 0;
uint32_t instruction_counter::bcnt = 0;
Expand Down
11 changes: 11 additions & 0 deletions libraries/testing/include/eosio/testing/tester.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ namespace eosio { namespace testing {
void produce_min_num_of_blocks_to_spend_time_wo_inactive_prod(const fc::microseconds target_elapsed_time = fc::microseconds());
signed_block_ptr push_block(signed_block_ptr b);

/**
* These transaction IDs represent transactions available in the head chain state as scheduled
* or otherwise generated transactions.
*
* calling push_scheduled_transaction with these IDs will remove the associated transaction from
* the chain state IFF it succeeds or objectively fails
*
* @return
*/
vector<transaction_id_type> get_scheduled_transactions() const;

transaction_trace_ptr push_transaction( packed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US );
transaction_trace_ptr push_transaction( signed_transaction& trx, fc::time_point deadline = fc::time_point::maximum(), uint32_t billed_cpu_time_us = DEFAULT_BILLED_CPU_TIME_US );
action_result push_action(action&& cert_act, uint64_t authorizer); // TODO/QUESTION: Is this needed?
Expand Down
21 changes: 17 additions & 4 deletions libraries/testing/tester.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <eosio/testing/tester.hpp>
#include <eosio/chain/wast_to_wasm.hpp>
#include <eosio/chain/eosio_contract.hpp>
#include <eosio/chain/generated_transaction_object.hpp>

#include <eosio.bios/eosio.bios.wast.hpp>
#include <eosio.bios/eosio.bios.abi.hpp>
Expand Down Expand Up @@ -163,16 +164,16 @@ namespace eosio { namespace testing {
}

if( !skip_pending_trxs ) {
auto unapplied_trxs = control->get_unapplied_transactions();
for (const auto& trx : unapplied_trxs ) {
auto trace = control->push_transaction(trx, fc::time_point::maximum());
unapplied_transactions_type unapplied_trxs = control->get_unapplied_transactions(); // make copy of map
for (const auto& entry : unapplied_trxs ) {
auto trace = control->push_transaction(entry.second, fc::time_point::maximum());
if(trace->except) {
trace->except->dynamic_rethrow_exception();
}
}

vector<transaction_id_type> scheduled_trxs;
while( (scheduled_trxs = control->get_scheduled_transactions() ).size() > 0 ) {
while( (scheduled_trxs = get_scheduled_transactions() ).size() > 0 ) {
for (const auto& trx : scheduled_trxs ) {
auto trace = control->push_scheduled_transaction(trx, fc::time_point::maximum());
if(trace->except) {
Expand Down Expand Up @@ -237,6 +238,18 @@ namespace eosio { namespace testing {
}
}

vector<transaction_id_type> base_tester::get_scheduled_transactions() const {
const auto& idx = control->db().get_index<generated_transaction_multi_index,by_delay>();

vector<transaction_id_type> result;

auto itr = idx.begin();
while( itr != idx.end() && itr->delay_until <= control->pending_block_time() ) {
result.emplace_back(itr->trx_id);
++itr;
}
return result;
}

void base_tester::produce_blocks_until_end_of_round() {
uint64_t blocks_per_round;
Expand Down
Loading