Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Merge pull request #6482 from EOSIO/release/1.5.x
Browse files Browse the repository at this point in the history
Release 1.5.1
  • Loading branch information
b1bart authored Dec 13, 2018
2 parents ea08cfd + 147cdb9 commit d4ffb4e
Show file tree
Hide file tree
Showing 8 changed files with 166 additions and 95 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ set( CXX_STANDARD_REQUIRED ON)

set(VERSION_MAJOR 1)
set(VERSION_MINOR 5)
set(VERSION_PATCH 0)
set(VERSION_PATCH 1)

if(VERSION_SUFFIX)
set(VERSION_FULL "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_SUFFIX}")
Expand Down
4 changes: 2 additions & 2 deletions Docker/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ cd eos/Docker
docker build . -t eosio/eos
```

The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the v1.5.0 tag, you could do the following:
The above will build off the most recent commit to the master branch by default. If you would like to target a specific branch/tag, you may use a build argument. For example, if you wished to generate a docker image based off of the v1.5.1 tag, you could do the following:

```bash
docker build -t eosio/eos:v1.5.0 --build-arg branch=v1.5.0 .
docker build -t eosio/eos:v1.5.1 --build-arg branch=v1.5.1 .
```

By default, the symbol in eosio.system is set to SYS. You can override this using the symbol argument while building the docker image.
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,31 +39,31 @@ $ brew remove eosio
```
#### Ubuntu 18.04 Debian Package Install
```sh
$ wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio_1.5.0-1-ubuntu-18.04_amd64.deb
$ sudo apt install ./eosio_1.5.0-1-ubuntu-18.04_amd64.deb
$ wget https://github.com/eosio/eos/releases/download/v1.5.1/eosio_1.5.1-1-ubuntu-18.04_amd64.deb
$ sudo apt install ./eosio_1.5.1-1-ubuntu-18.04_amd64.deb
```
#### Ubuntu 16.04 Debian Package Install
```sh
$ wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio_1.5.0-1-ubuntu-16.04_amd64.deb
$ sudo apt install ./eosio_1.5.0-1-ubuntu-16.04_amd64.deb
$ wget https://github.com/eosio/eos/releases/download/v1.5.1/eosio_1.5.1-1-ubuntu-16.04_amd64.deb
$ sudo apt install ./eosio_1.5.1-1-ubuntu-16.04_amd64.deb
```
#### Debian Package Uninstall
```sh
$ sudo apt remove eosio
```
#### Centos RPM Package Install
```sh
$ wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio-1.5.0-1.el7.x86_64.rpm
$ sudo yum install ./eosio-1.5.0-1.el7.x86_64.rpm
$ wget https://github.com/eosio/eos/releases/download/v1.5.1/eosio-1.5.1-1.el7.x86_64.rpm
$ sudo yum install ./eosio-1.5.1-1.el7.x86_64.rpm
```
#### Centos RPM Package Uninstall
```sh
$ sudo yum remove eosio.cdt
```
#### Fedora RPM Package Install
```sh
$ wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio-1.5.0-1.fc27.x86_64.rpm
$ sudo yum install ./eosio-1.5.0-1.fc27.x86_64.rpm
$ wget https://github.com/eosio/eos/releases/download/v1.5.1/eosio-1.5.1-1.fc27.x86_64.rpm
$ sudo yum install ./eosio-1.5.1-1.fc27.x86_64.rpm
```
#### Fedora RPM Package Uninstall
```sh
Expand Down
108 changes: 85 additions & 23 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ void apply_context::execute_inline( action&& a ) {
bool enforce_actor_whitelist_blacklist = trx_context.enforce_whiteblacklist && control.is_producing_block();
flat_set<account_name> actors;

bool disallow_send_to_self_bypass = false; // eventually set to whether the appropriate protocol feature has been activated
bool send_to_self = (a.account == receiver);
bool inherit_parent_authorizations = (!disallow_send_to_self_bypass && send_to_self && (receiver == act.account) && control.is_producing_block());

flat_set<permission_level> inherited_authorizations;
if( inherit_parent_authorizations ) {
inherited_authorizations.reserve( a.authorization.size() );
}

for( const auto& auth : a.authorization ) {
auto* actor = control.db().find<account_object, by_name>(auth.actor);
EOS_ASSERT( actor != nullptr, action_validate_exception,
Expand All @@ -217,26 +226,49 @@ void apply_context::execute_inline( action&& a ) {
("permission", auth) );
if( enforce_actor_whitelist_blacklist )
actors.insert( auth.actor );

if( inherit_parent_authorizations && std::find(act.authorization.begin(), act.authorization.end(), auth) != act.authorization.end() ) {
inherited_authorizations.insert( auth );
}
}

if( enforce_actor_whitelist_blacklist ) {
control.check_actor_list( actors );
}

// No need to check authorization if: replaying irreversible blocks; contract is privileged; or, contract is calling itself.
if( !control.skip_auth_check() && !privileged && a.account != receiver ) {
control.get_authorization_manager()
.check_authorization( {a},
{},
{{receiver, config::eosio_code_name}},
control.pending_block_time() - trx_context.published,
std::bind(&transaction_context::checktime, &this->trx_context),
false
);

//QUESTION: Is it smart to allow a deferred transaction that has been delayed for some time to get away
// with sending an inline action that requires a delay even though the decision to send that inline
// action was made at the moment the deferred transaction was executed with potentially no forewarning?
// No need to check authorization if replaying irreversible blocks or contract is privileged
if( !control.skip_auth_check() && !privileged ) {
try {
control.get_authorization_manager()
.check_authorization( {a},
{},
{{receiver, config::eosio_code_name}},
control.pending_block_time() - trx_context.published,
std::bind(&transaction_context::checktime, &this->trx_context),
false,
inherited_authorizations
);

//QUESTION: Is it smart to allow a deferred transaction that has been delayed for some time to get away
// with sending an inline action that requires a delay even though the decision to send that inline
// action was made at the moment the deferred transaction was executed with potentially no forewarning?
} catch( const fc::exception& e ) {
if( disallow_send_to_self_bypass || !send_to_self ) {
throw;
} else if( control.is_producing_block() ) {
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with inline action sent to self"));
for (const auto& log: e.get_log()) {
new_exception.append_log(log);
}
throw new_exception;
}
} catch( ... ) {
if( disallow_send_to_self_bypass || !send_to_self ) {
throw;
} else if( control.is_producing_block() ) {
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating inline action sent to self");
}
}
}

_inline_actions.emplace_back( move(a) );
Expand Down Expand Up @@ -276,16 +308,30 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
require_authorization(payer); /// uses payer's storage
}

// if a contract is deferring only actions to itself then there is no need
// to check permissions, it could have done everything anyway.
bool check_auth = false;
for( const auto& act : trx.actions ) {
if( act.account != receiver ) {
check_auth = true;
break;
// Originally this code bypassed authorization checks if a contract was deferring only actions to itself.
// The idea was that the code could already do whatever the deferred transaction could do, so there was no point in checking authorizations.
// But this is not true. The original implementation didn't validate the authorizations on the actions which allowed for privilege escalation.
// It would make it possible to bill RAM to some unrelated account.
// Furthermore, even if the authorizations were forced to be a subset of the current action's authorizations, it would still violate the expectations
// of the signers of the original transaction, because the deferred transaction would allow billing more CPU and network bandwidth than the maximum limit
// specified on the original transaction.
// So, the deferred transaction must always go through the authorization checking if it is not sent by a privileged contract.
// However, the old logic must still be considered because it cannot objectively change until a consensus protocol upgrade.

bool disallow_send_to_self_bypass = false; // eventually set to whether the appropriate protocol feature has been activated

auto is_sending_only_to_self = [&trx]( const account_name& self ) {
bool send_to_self = true;
for( const auto& act : trx.actions ) {
if( act.account != self ) {
send_to_self = false;
break;
}
}
}
if( check_auth ) {
return send_to_self;
};

try {
control.get_authorization_manager()
.check_authorization( trx.actions,
{},
Expand All @@ -294,6 +340,22 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
std::bind(&transaction_context::checktime, &this->trx_context),
false
);
} catch( const fc::exception& e ) {
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
throw;
} else if( control.is_producing_block() ) {
subjective_block_production_exception new_exception(FC_LOG_MESSAGE( error, "Authorization failure with sent deferred transaction consisting only of actions to self"));
for (const auto& log: e.get_log()) {
new_exception.append_log(log);
}
throw new_exception;
}
} catch( ... ) {
if( disallow_send_to_self_bypass || !is_sending_only_to_self(receiver) ) {
throw;
} else if( control.is_producing_block() ) {
EOS_THROW(subjective_block_production_exception, "Unexpected exception occurred validating sent deferred transaction consisting only of actions to self");
}
}
}

Expand Down
11 changes: 7 additions & 4 deletions libraries/chain/authorization_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,8 @@ namespace eosio { namespace chain {
const flat_set<permission_level>& provided_permissions,
fc::microseconds provided_delay,
const std::function<void()>& _checktime,
bool allow_unused_keys
bool allow_unused_keys,
const flat_set<permission_level>& satisfied_authorizations
)const
{
const auto& checktime = ( static_cast<bool>(_checktime) ? _checktime : _noop_checktime );
Expand Down Expand Up @@ -488,9 +489,11 @@ namespace eosio { namespace chain {
}
}

auto res = permissions_to_satisfy.emplace( declared_auth, delay );
if( !res.second && res.first->second > delay) { // if the declared_auth was already in the map and with a higher delay
res.first->second = delay;
if( satisfied_authorizations.find( declared_auth ) == satisfied_authorizations.end() ) {
auto res = permissions_to_satisfy.emplace( declared_auth, delay );
if( !res.second && res.first->second > delay) { // if the declared_auth was already in the map and with a higher delay
res.first->second = delay;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ namespace eosio { namespace chain {
const flat_set<permission_level>& provided_permissions = flat_set<permission_level>(),
fc::microseconds provided_delay = fc::microseconds(0),
const std::function<void()>& checktime = std::function<void()>(),
bool allow_unused_keys = false
bool allow_unused_keys = false,
const flat_set<permission_level>& satisfied_authorizations = flat_set<permission_level>()
)const;


Expand Down
Loading

0 comments on commit d4ffb4e

Please sign in to comment.