diff --git a/docs/README.md b/docs/README.md index 7ca3921502..76caef1ada 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,6 +13,7 @@ $ npm install This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. +(You might have to run build.sh first if you run into failures) ``` $ npm run start diff --git a/docs/src/developing/programming-model/accounts.md b/docs/src/developing/programming-model/accounts.md index 6abc7ce04b..daedd5d42d 100644 --- a/docs/src/developing/programming-model/accounts.md +++ b/docs/src/developing/programming-model/accounts.md @@ -84,6 +84,39 @@ _assign_ account ownership, meaning changing owner to different program id. If an account is not owned by a program, the program is only permitted to read its data and credit the account. +## Verifying validity of unmodified, reference-only accounts + +For security purposes, it is recommended that programs check the validity of any +account it reads but does not modify. + +The security model enforces that an account's data can only be modified by the +account's `Owner` program. Doing so allows the program to trust that the data +passed to them via accounts they own will be in a known and valid state. The +runtime enforces this by rejecting any transaction containing a program that +attempts to write to an account it does not own. But, there are also cases +where a program may merely read an account they think they own and assume the +data has only been written by themselves and thus is valid. But anyone can +issues instructions to a program, and the runtime does not know that those +accounts are expected to be owned by the program. Therefore a malicious user +could create accounts with arbitrary data and then pass these accounts to the +program in the place of a valid account. The arbitrary data could be crafted in +a way that leads to unexpected or harmful program behavior. + +To check an account's validity, the program should either check the account's +address against a known value or check that the account is indeed owned +correctly (usually owned by the program itself). + +One example is when programs read a sysvar. Unless the program checks the +address or owner, it's impossible to be sure whether it's a real and valid +sysvar merely by successful deserialization. Accordingly, the Solana SDK [checks +the sysvar's validity during +deserialization](https://github.com/solana-labs/solana/blob/a95675a7ce1651f7b59443eb146b356bc4b3f374/sdk/program/src/sysvar/mod.rs#L65). + +If the program always modifies the account in question, the address/owner check +isn't required because modifying an unowned (could be the malicious account with +the wrong owner) will be rejected by the runtime, and the containing transaction +will be thrown out. + ## Rent Keeping accounts alive on Solana incurs a storage cost called _rent_ because the diff --git a/docs/src/developing/programming-model/transactions.md b/docs/src/developing/programming-model/transactions.md index cf5eb8ad7c..ce376ddaa5 100644 --- a/docs/src/developing/programming-model/transactions.md +++ b/docs/src/developing/programming-model/transactions.md @@ -171,6 +171,26 @@ that this method only supports fixed sized types. Token utilizes the trait to encode/decode instruction data for both token instructions as well as token account states. +### Multiple instructions in a single transaction + +A transaction can contain instructions in any order. This means a malicious +user could craft transactions that may pose instructions in an order that the +program has not been protected against. Programs should be hardened to properly +and safely handle any possible instruction sequence. + +One not so obvious example is account deinitialization. Some programs may +attempt to deinitialize an account by setting its lamports to zero, with the +assumption that the runtime will delete the account. This assumption may be +valid between transactions, but it is not between instructions or cross-program +invocations. To harden against this, the program should also explicitly zero out the +account's data. + +An example of where this could be a problem is if a token program, upon +transferring the token out of an account, sets the account's lamports to zero, +assuming it will be deleted by the runtime. If the program does zero out the +account's data, a malicious user could trail this instruction with another that +transfers the tokens a second time. + ## Signatures Each transaction explicitly lists all account public keys referenced by the