Pull in hardened BPF virtual machine (#9931)

This commit is contained in:
Jack May
2020-05-08 12:37:04 -07:00
parent 01c490d354
commit 92562b4349
8 changed files with 451 additions and 808 deletions

537
Cargo.lock generated

File diff suppressed because it is too large Load Diff

345
programs/bpf/Cargo.lock generated
View File

@ -9,30 +9,6 @@ dependencies = [
"memchr",
]
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.8",
]
[[package]]
name = "ar"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "579681b3fecd1e9d6b5ce6969e05f9feb913f296eddaf595be1166a5ca597bc4"
dependencies = [
"byteorder 1.3.4",
]
[[package]]
name = "arrayref"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
[[package]]
name = "ascii"
version = "0.7.1"
@ -101,34 +77,12 @@ dependencies = [
"serde",
]
[[package]]
name = "bit-vec"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f"
[[package]]
name = "bit-vec"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f59bbe95d4e52a6398ec21238d31577f2b28a9d86807f06ca59d191d8440d0bb"
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block-buffer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab"
dependencies = [
"arrayref",
"byte-tools 0.2.0",
]
[[package]]
name = "block-buffer"
version = "0.7.3"
@ -136,7 +90,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools 0.3.1",
"byte-tools",
"byteorder 1.3.4",
"generic-array 0.12.3",
]
@ -147,16 +101,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools 0.3.1",
]
[[package]]
name = "bloom"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d00ac8e5056d6d65376a3c1aa5c7c34850d6949ace17f0266953a254eb3d6fe8"
dependencies = [
"bit-vec 0.4.4",
"byte-tools",
]
[[package]]
@ -181,12 +126,6 @@ dependencies = [
"serde",
]
[[package]]
name = "byte-tools"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
[[package]]
name = "byte-tools"
version = "0.3.1"
@ -245,26 +184,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
dependencies = [
"num-integer",
"num-traits 0.2.11",
"num-traits",
"serde",
"time",
]
[[package]]
name = "clap"
version = "2.33.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "clear_on_drop"
version = "0.2.3"
@ -283,17 +207,6 @@ dependencies = [
"bitflags",
]
[[package]]
name = "colored"
version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
dependencies = [
"atty",
"lazy_static",
"winapi 0.3.8",
]
[[package]]
name = "combine"
version = "2.5.2"
@ -393,21 +306,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26778518a7f6cffa1d25a44b602b62b979bd88adb9e99ffec546998cf3404839"
dependencies = [
"byteorder 1.3.4",
"digest 0.8.1",
"digest",
"rand_core",
"subtle 2.2.2",
"zeroize",
]
[[package]]
name = "digest"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90"
dependencies = [
"generic-array 0.9.0",
]
[[package]]
name = "digest"
version = "0.8.1"
@ -433,7 +337,7 @@ dependencies = [
"curve25519-dalek",
"rand",
"serde",
"sha2 0.8.1",
"sha2",
]
[[package]]
@ -451,33 +355,6 @@ dependencies = [
"byteorder 0.5.3",
]
[[package]]
name = "elfkit"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02f182eda16a7360c80a2f8638d0726e9d5478173058f1505c42536ca666ecd2"
dependencies = [
"ar",
"bit-vec 0.5.1",
"bitflags",
"bloom",
"byteorder 1.3.4",
"clap",
"colored",
"enum-primitive-derive",
"env_logger 0.5.13",
"fnv",
"glob",
"indexmap",
"itertools 0.7.11",
"log",
"num-traits 0.2.11",
"pretty_env_logger",
"rayon",
"sha2 0.7.1",
"tempfile",
]
[[package]]
name = "encoding_rs"
version = "0.8.22"
@ -487,30 +364,6 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "enum-primitive-derive"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2b90e520ec62c1864c8c78d637acbfe8baf5f63240f2fb8165b8325c07812dd"
dependencies = [
"num-traits 0.1.43",
"quote 0.3.15",
"syn 0.11.11",
]
[[package]]
name = "env_logger"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "env_logger"
version = "0.7.1"
@ -654,15 +507,6 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d"
dependencies = [
"typenum",
]
[[package]]
name = "generic-array"
version = "0.12.3"
@ -704,10 +548,15 @@ dependencies = [
]
[[package]]
name = "glob"
version = "0.2.11"
name = "goblin"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb"
checksum = "ddd5e3132801a1ac34ac53b97acde50c4685414dd2f291b9ea52afa6f07468c8"
dependencies = [
"log",
"plain",
"scroll",
]
[[package]]
name = "h2"
@ -759,7 +608,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695"
dependencies = [
"crypto-mac",
"digest 0.8.1",
"digest",
]
[[package]]
@ -869,15 +718,6 @@ dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d47946d458e94a1b7bcabbf6521ea7c037062c81f534615abcad76e84d4970d"
dependencies = [
"either",
]
[[package]]
name = "itertools"
version = "0.9.0"
@ -1131,16 +971,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
dependencies = [
"autocfg",
"num-traits 0.2.11",
]
[[package]]
name = "num-traits"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
dependencies = [
"num-traits 0.2.11",
"num-traits",
]
[[package]]
@ -1270,24 +1101,18 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
[[package]]
name = "ppv-lite86"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
[[package]]
name = "pretty_env_logger"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed8d1e63042e889b85228620629b51c011d380eed2c7e0015f8a644def280c28"
dependencies = [
"ansi_term",
"chrono",
"env_logger 0.5.13",
"log",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.15"
@ -1324,12 +1149,6 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quote"
version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
[[package]]
name = "quote"
version = "0.6.13"
@ -1569,6 +1388,26 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "scroll"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abb2332cb595d33f7edd5700f4cbf94892e680c7f0ae56adab58a35190b66cb1"
dependencies = [
"scroll_derive",
]
[[package]]
name = "scroll_derive"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8584eea9b9ff42825b46faf46a8c24d2cff13ec152fa2a50df788b87c07ee28"
dependencies = [
"proc-macro2 1.0.12",
"quote 1.0.4",
"syn 1.0.19",
]
[[package]]
name = "sct"
version = "0.6.0"
@ -1669,26 +1508,14 @@ dependencies = [
"url",
]
[[package]]
name = "sha2"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9eb6be24e4c23a84d7184280d2722f7f2731fcdd4a9d886efbfe4413e4847ea0"
dependencies = [
"block-buffer 0.3.3",
"byte-tools 0.2.0",
"digest 0.7.6",
"fake-simd",
]
[[package]]
name = "sha2"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27044adfd2e1f077f649f59deb9490d3941d674002f7d062870a60ebe9bd47a0"
dependencies = [
"block-buffer 0.7.3",
"digest 0.8.1",
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
@ -1723,7 +1550,7 @@ dependencies = [
"libc",
"log",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"solana-logger",
"solana-sdk",
"solana_rbpf",
@ -1792,7 +1619,7 @@ name = "solana-bpf-rust-error-handling"
version = "1.1.11"
dependencies = [
"num-derive 0.2.5",
"num-traits 0.2.11",
"num-traits",
"solana-sdk",
"solana-sdk-bpf-test",
"thiserror",
@ -1911,7 +1738,7 @@ dependencies = [
name = "solana-logger"
version = "1.1.11"
dependencies = [
"env_logger 0.7.1",
"env_logger",
"lazy_static",
"log",
]
@ -1931,7 +1758,7 @@ dependencies = [
name = "solana-metrics"
version = "1.1.11"
dependencies = [
"env_logger 0.7.1",
"env_logger",
"gethostname",
"lazy_static",
"log",
@ -1956,14 +1783,14 @@ dependencies = [
"byteorder 1.3.4",
"fnv",
"fs_extra",
"itertools 0.9.0",
"itertools",
"lazy_static",
"libc",
"libloading",
"log",
"memmap",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"num_cpus",
"rand",
"rayon",
@ -1997,11 +1824,11 @@ dependencies = [
"generic-array 0.13.2",
"hex",
"hmac",
"itertools 0.9.0",
"itertools",
"log",
"memmap",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"pbkdf2",
"rand",
"rand_chacha",
@ -2009,7 +1836,7 @@ dependencies = [
"serde_bytes",
"serde_derive",
"serde_json",
"sha2 0.8.1",
"sha2",
"solana-crate-features",
"solana-logger",
"solana-sdk-macro",
@ -2037,7 +1864,7 @@ dependencies = [
"bincode",
"log",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"serde",
"serde_derive",
"solana-config-program",
@ -2054,7 +1881,7 @@ dependencies = [
"bincode",
"log",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"rand",
"serde",
"serde_derive",
@ -2069,7 +1896,7 @@ dependencies = [
"bincode",
"log",
"num-derive 0.3.0",
"num-traits 0.2.11",
"num-traits",
"serde",
"serde_derive",
"solana-metrics",
@ -2079,17 +1906,18 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.1.26"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d6bee545321a2fed2f9a24066bf7bf08f9b814fd48865b7c629ee40f33f3207"
checksum = "e7baa2550500e75413f031f239fe0c4da2d477ae1b1ff7cb671eba483f963d91"
dependencies = [
"byteorder 1.3.4",
"combine",
"elfkit",
"goblin",
"hash32",
"libc",
"log",
"num-traits 0.2.11",
"rand",
"scroll",
"thiserror",
"time",
]
@ -2100,12 +1928,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "subtle"
version = "1.0.0"
@ -2118,17 +1940,6 @@ version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c65d530b10ccaeac294f349038a597e435b18fb456aadd0840a623f83b9e941"
[[package]]
name = "syn"
version = "0.11.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
dependencies = [
"quote 0.3.15",
"synom",
"unicode-xid 0.0.4",
]
[[package]]
name = "syn"
version = "0.15.44"
@ -2151,15 +1962,6 @@ dependencies = [
"unicode-xid 0.2.0",
]
[[package]]
name = "synom"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
dependencies = [
"unicode-xid 0.0.4",
]
[[package]]
name = "synstructure"
version = "0.12.3"
@ -2195,15 +1997,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.16"
@ -2514,18 +2307,6 @@ dependencies = [
"smallvec 1.4.0",
]
[[package]]
name = "unicode-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479"
[[package]]
name = "unicode-xid"
version = "0.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc"
[[package]]
name = "unicode-xid"
version = "0.1.0"
@ -2555,12 +2336,6 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.1"

View File

@ -26,7 +26,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "1.1.11" }
solana-logger = { path = "../../logger", version = "1.1.11" }
solana-runtime = { path = "../../runtime", version = "1.1.11" }
solana-sdk = { path = "../../sdk", version = "1.1.11" }
solana_rbpf = "=0.1.26"
solana_rbpf = "=0.1.27"
[[bench]]
name = "bpf_loader"

View File

@ -92,7 +92,7 @@ mod bpf {
.native_instruction_processors
.push(solana_bpf_loader_program!());
let bank = Arc::new(Bank::new(&genesis_config));
// Create bank with specific slot, used by solana_bpf_rust_sysvar test
// Create bank with a specific slot, used by solana_bpf_rust_sysvar test
let bank =
Bank::new_from_parent(&bank, &Pubkey::default(), DEFAULT_SLOTS_PER_EPOCH + 1);
let bank_client = BankClient::new(bank);

View File

@ -17,9 +17,12 @@ num-derive = { version = "0.3" }
num-traits = { version = "0.2" }
solana-logger = { path = "../../logger", version = "1.1.11" }
solana-sdk = { path = "../../sdk", version = "1.1.11" }
solana_rbpf = "=0.1.26"
solana_rbpf = "=0.1.27"
thiserror = "1.0"
[dev-dependencies]
rand = "0.7.3"
[lib]
crate-type = ["lib", "cdylib"]
name = "solana_bpf_loader_program"

View File

@ -25,7 +25,7 @@ impl BPFAllocator {
impl Alloc for BPFAllocator {
fn alloc(&mut self, layout: Layout) -> Result<u64, AllocErr> {
if self.pos + layout.size() as u64 <= self.len {
if self.pos.saturating_add(layout.size() as u64) <= self.len {
let addr = self.start + self.pos;
self.pos += layout.size() as u64;
Ok(addr)

View File

@ -2,36 +2,56 @@ use crate::BPFError;
use solana_rbpf::ebpf;
use thiserror::Error;
/// Error definitions
#[derive(Debug, Error)]
pub enum VerifierError {
/// ProgramLengthNotMultiple
#[error("program length must be a multiple of {} octets", ebpf::INSN_SIZE)]
ProgramLengthNotMultiple,
/// ProgramTooLarge
#[error("program too big, max {}, is {}", ebpf::PROG_MAX_INSNS, .0)]
ProgramTooLarge(usize),
/// NoProgram
#[error("no program set, call prog_set() to load one")]
NoProgram,
#[error("division by 0 (insn #{0})")]
DivisionByZero(usize),
/// UnsupportedLEBEArgument
#[error("unsupported argument for LE/BE (insn #{0})")]
UnsupportedLEBEArgument(usize),
/// LDDWCannotBeLast
#[error("LD_DW instruction cannot be last in program")]
LDDWCannotBeLast,
/// IncompleteLDDW
#[error("incomplete LD_DW instruction (insn #{0})")]
IncompleteLDDW(usize),
/// InfiniteLoop
#[error("infinite loop (insn #{0})")]
InfiniteLoop(usize),
/// JumpOutOfCode
#[error("jump out of code to #{0} (insn #{1})")]
JumpOutOfCode(usize, usize),
/// JumpToMiddleOfLDDW
#[error("jump to middle of LD_DW at #{0} (insn #{1})")]
JumpToMiddleOfLDDW(usize, usize),
/// InvalidSourceRegister
#[error("invalid source register (insn #{0})")]
InvalidSourceRegister(usize),
/// CannotWriteR10
#[error("cannot write into register r10 (insn #{0})")]
CannotWriteR10(usize),
/// InvalidDestinationRegister
#[error("invalid destination register (insn #{0})")]
InvalidDestinationRegister(usize),
/// UnknownOpCode
#[error("unknown eBPF opcode {0:#2x} (insn #{1:?})")]
UnknownOpCode(u8, usize),
/// Shift with overflow
#[error("Shift with overflow at instruction {0}")]
ShiftWithOverflow(usize),
/// Invalid register specified
#[error("Invalid register specified at instruction {0}")]
InvalidRegister(usize),
}
fn check_prog_len(prog: &[u8]) -> Result<(), BPFError> {
@ -102,6 +122,23 @@ fn check_registers(insn: &ebpf::Insn, store: bool, insn_ptr: usize) -> Result<()
}
}
/// Check that the imm is a valid shift operand
fn check_imm_shift(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
if insn.imm < 0 || insn.imm as u64 >= 64 {
return Err(VerifierError::ShiftWithOverflow(insn_ptr));
}
Ok(())
}
/// Check that the imm is a valid register number
fn check_imm_register(insn: &ebpf::Insn, insn_ptr: usize) -> Result<(), VerifierError> {
if insn.imm < 0 || insn.imm > 10 {
return Err(VerifierError::InvalidRegister(insn_ptr));
}
Ok(())
}
#[rustfmt::skip]
pub fn check(prog: &[u8]) -> Result<(), BPFError> {
check_prog_len(prog)?;
@ -111,189 +148,126 @@ pub fn check(prog: &[u8]) -> Result<(), BPFError> {
let mut store = false;
match insn.opc {
// BPF_LD class
ebpf::LD_ABS_B => {}
ebpf::LD_ABS_H => {}
ebpf::LD_ABS_W => {}
ebpf::LD_ABS_DW => {}
ebpf::LD_IND_B => {}
ebpf::LD_IND_H => {}
ebpf::LD_IND_W => {}
ebpf::LD_IND_DW => {}
ebpf::LD_DW_IMM => {
// BPF_LD class
ebpf::LD_ABS_B => {},
ebpf::LD_ABS_H => {},
ebpf::LD_ABS_W => {},
ebpf::LD_ABS_DW => {},
ebpf::LD_IND_B => {},
ebpf::LD_IND_H => {},
ebpf::LD_IND_W => {},
ebpf::LD_IND_DW => {},
ebpf::LD_DW_IMM => {
store = true;
check_load_dw(prog, insn_ptr)?;
insn_ptr += 1;
}
},
// BPF_LDX class
ebpf::LD_B_REG => {}
ebpf::LD_H_REG => {}
ebpf::LD_W_REG => {}
ebpf::LD_DW_REG => {}
ebpf::LD_B_REG => {},
ebpf::LD_H_REG => {},
ebpf::LD_W_REG => {},
ebpf::LD_DW_REG => {},
// BPF_ST class
ebpf::ST_B_IMM => store = true,
ebpf::ST_H_IMM => store = true,
ebpf::ST_W_IMM => store = true,
ebpf::ST_DW_IMM => store = true,
ebpf::ST_B_IMM => store = true,
ebpf::ST_H_IMM => store = true,
ebpf::ST_W_IMM => store = true,
ebpf::ST_DW_IMM => store = true,
// BPF_STX class
ebpf::ST_B_REG => store = true,
ebpf::ST_H_REG => store = true,
ebpf::ST_W_REG => store = true,
ebpf::ST_DW_REG => store = true,
ebpf::ST_W_XADD => {
unimplemented!();
}
ebpf::ST_DW_XADD => {
unimplemented!();
}
ebpf::ST_B_REG => store = true,
ebpf::ST_H_REG => store = true,
ebpf::ST_W_REG => store = true,
ebpf::ST_DW_REG => store = true,
// BPF_ALU class
ebpf::ADD32_IMM => {}
ebpf::ADD32_REG => {}
ebpf::SUB32_IMM => {}
ebpf::SUB32_REG => {}
ebpf::MUL32_IMM => {}
ebpf::MUL32_REG => {}
ebpf::DIV32_IMM => {
check_imm_nonzero(&insn, insn_ptr)?;
}
ebpf::DIV32_REG => {}
ebpf::OR32_IMM => {}
ebpf::OR32_REG => {}
ebpf::AND32_IMM => {}
ebpf::AND32_REG => {}
ebpf::LSH32_IMM => {}
ebpf::LSH32_REG => {}
ebpf::RSH32_IMM => {}
ebpf::RSH32_REG => {}
ebpf::NEG32 => {}
ebpf::MOD32_IMM => {
check_imm_nonzero(&insn, insn_ptr)?;
}
ebpf::MOD32_REG => {}
ebpf::XOR32_IMM => {}
ebpf::XOR32_REG => {}
ebpf::MOV32_IMM => {}
ebpf::MOV32_REG => {}
ebpf::ARSH32_IMM => {}
ebpf::ARSH32_REG => {}
ebpf::LE => {
check_imm_endian(&insn, insn_ptr)?;
}
ebpf::BE => {
check_imm_endian(&insn, insn_ptr)?;
}
ebpf::ADD32_IMM => {},
ebpf::ADD32_REG => {},
ebpf::SUB32_IMM => {},
ebpf::SUB32_REG => {},
ebpf::MUL32_IMM => {},
ebpf::MUL32_REG => {},
ebpf::DIV32_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::DIV32_REG => {},
ebpf::OR32_IMM => {},
ebpf::OR32_REG => {},
ebpf::AND32_IMM => {},
ebpf::AND32_REG => {},
ebpf::LSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::LSH32_REG => {},
ebpf::RSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::RSH32_REG => {},
ebpf::NEG32 => {},
ebpf::MOD32_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MOD32_REG => {},
ebpf::XOR32_IMM => {},
ebpf::XOR32_REG => {},
ebpf::MOV32_IMM => {},
ebpf::MOV32_REG => {},
ebpf::ARSH32_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::ARSH32_REG => {},
ebpf::LE => { check_imm_endian(&insn, insn_ptr)?; },
ebpf::BE => { check_imm_endian(&insn, insn_ptr)?; },
// BPF_ALU64 class
ebpf::ADD64_IMM => {}
ebpf::ADD64_REG => {}
ebpf::SUB64_IMM => {}
ebpf::SUB64_REG => {}
ebpf::MUL64_IMM => {
check_imm_nonzero(&insn, insn_ptr)?;
}
ebpf::MUL64_REG => {}
ebpf::DIV64_IMM => {
check_imm_nonzero(&insn, insn_ptr)?;
}
ebpf::DIV64_REG => {}
ebpf::OR64_IMM => {}
ebpf::OR64_REG => {}
ebpf::AND64_IMM => {}
ebpf::AND64_REG => {}
ebpf::LSH64_IMM => {}
ebpf::LSH64_REG => {}
ebpf::RSH64_IMM => {}
ebpf::RSH64_REG => {}
ebpf::NEG64 => {}
ebpf::MOD64_IMM => {}
ebpf::MOD64_REG => {}
ebpf::XOR64_IMM => {}
ebpf::XOR64_REG => {}
ebpf::MOV64_IMM => {}
ebpf::MOV64_REG => {}
ebpf::ARSH64_IMM => {}
ebpf::ARSH64_REG => {}
ebpf::ADD64_IMM => {},
ebpf::ADD64_REG => {},
ebpf::SUB64_IMM => {},
ebpf::SUB64_REG => {},
ebpf::MUL64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MUL64_REG => {},
ebpf::DIV64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::DIV64_REG => {},
ebpf::OR64_IMM => {},
ebpf::OR64_REG => {},
ebpf::AND64_IMM => {},
ebpf::AND64_REG => {},
ebpf::LSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::LSH64_REG => {},
ebpf::RSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::RSH64_REG => {},
ebpf::NEG64 => {},
ebpf::MOD64_IMM => { check_imm_nonzero(&insn, insn_ptr)?; },
ebpf::MOD64_REG => {},
ebpf::XOR64_IMM => {},
ebpf::XOR64_REG => {},
ebpf::MOV64_IMM => {},
ebpf::MOV64_REG => {},
ebpf::ARSH64_IMM => { check_imm_shift(&insn, insn_ptr)?; },
ebpf::ARSH64_REG => {},
// BPF_JMP class
ebpf::JA => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JEQ_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JEQ_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JGT_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JGT_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JGE_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JGE_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JLT_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JLT_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JLE_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JLE_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSET_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSET_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JNE_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JNE_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSGT_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSGT_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSGE_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSGE_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSLT_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSLT_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSLE_IMM => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::JSLE_REG => {
check_jmp_offset(prog, insn_ptr)?;
}
ebpf::CALL_IMM => {}
ebpf::CALL_REG => {}
ebpf::EXIT => {}
ebpf::JA => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JEQ_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JEQ_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JGT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JGT_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JGE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JGE_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JLT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JLT_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JLE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JLE_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSET_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSET_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JNE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JNE_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSGT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSGT_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSGE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSGE_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSLT_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSLT_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSLE_IMM => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::JSLE_REG => { check_jmp_offset(prog, insn_ptr)?; },
ebpf::CALL_IMM => {},
ebpf::CALL_REG => { check_imm_register(&insn, insn_ptr)?; },
ebpf::EXIT => {},
_ => {
_ => {
return Err(VerifierError::UnknownOpCode(insn.opc, insn_ptr).into());
}
}

View File

@ -250,8 +250,9 @@ pub fn process_instruction(
#[cfg(test)]
mod tests {
use super::*;
use rand::Rng;
use solana_sdk::{account::Account, rent::Rent};
use std::{fs::File, io::Read};
use std::{fs::File, io::Read, ops::Range};
#[test]
#[should_panic(expected = "ExceededMaxInstructions(10)")]
@ -416,4 +417,61 @@ mod tests {
process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![])
);
}
/// fuzzing utility function
fn fuzz<F>(
bytes: &[u8],
outer_iters: usize,
inner_iters: usize,
offset: Range<usize>,
value: Range<u8>,
work: F,
) where
F: Fn(&mut [u8]),
{
let mut rng = rand::thread_rng();
for _ in 0..outer_iters {
let mut mangled_bytes = bytes.to_vec();
for _ in 0..inner_iters {
let offset = rng.gen_range(offset.start, offset.end);
let value = rng.gen_range(value.start, value.end);
mangled_bytes[offset] = value;
work(&mut mangled_bytes);
}
}
}
#[test]
#[ignore]
fn test_fuzz() {
let program_id = Pubkey::new_rand();
let program_key = Pubkey::new_rand();
// Create program account
let mut file = File::open("test_elfs/noop.so").expect("file open failed");
let mut elf = Vec::new();
file.read_to_end(&mut elf).unwrap();
info!("mangle the whole file");
fuzz(
&elf,
1_000_000_000,
100,
0..elf.len(),
0..255,
|bytes: &mut [u8]| {
let program_account = Account::new_ref(1, 0, &program_id);
program_account.borrow_mut().data = bytes.to_vec();
program_account.borrow_mut().executable = true;
let parameter_account = Account::new_ref(1, 0, &program_id);
let keyed_accounts = vec![
KeyedAccount::new(&program_key, false, &program_account),
KeyedAccount::new(&program_key, false, &parameter_account),
];
let _result = process_instruction(&bpf_loader::id(), &keyed_accounts, &vec![]);
},
);
}
}