Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Sanitize AppendVec's file_size#7373

Merged
ryoqun merged 11 commits into
solana-labs:masterfrom
ryoqun:sanitize-append-vec-offset
Jan 6, 2020
Merged

Sanitize AppendVec's file_size#7373
ryoqun merged 11 commits into
solana-labs:masterfrom
ryoqun:sanitize-append-vec-offset

Conversation

@ryoqun
Copy link
Copy Markdown
Contributor

@ryoqun ryoqun commented Dec 9, 2019

Problem

Creation and restoration of AppendVec is not secure with regard to size of mmap.
Currently, validators can easily be panic!-ed just by putting empty (0-sized) appendvec file or very large sparse appendvec file. The former is forbidden by the specs of mmap and the later will cause panics depending on system configuration/load.

Summary of Changes

  • cap the maximum mmaped appendvec size to 16GiB. This effectively limits the maximum account data size to roughly 8GiB (half of 16GB according to current AppendVec capacity reservation policy) with plenty of margin to the hotly debated limit on the individual account sizes (ref: put limit on account data length #7320).
  • minor runtime behavior change and code cleanup along wide the above.

Part of #7167

Comment thread runtime/src/append_vec.rs
};
}

const MAXIMUM_APPEND_VEC_FILE_SIZE: usize = 16 * 1024 * 1024 * 1024; // 16 GiB
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be much lower considering it seems AccountsDB never increases its .file_size from DEFAULT_FILE_SIZE.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't increase, it may allocate a larger one than default if the store account is larger than the default file size.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for confirmation, then maybe we could lower to be close in relation to #7320.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now, I think this is fine as it is now because we can assume the running system will have at least 16GB RAM as per the doc and we can be relieved we'll never be tripped by the limit at that high number depending on current AccountDB's behavior and its possible future changes.

Or, could this be lower, say, a half?: 8GB

Comment thread runtime/src/append_vec.rs Outdated
Comment thread runtime/src/append_vec.rs
let mut rd = Cursor::new(&data[..]);
let current_len: usize = deserialize_from(&mut rd).map_err(Error::custom)?;
let map = MmapMut::map_anon(1).map_err(|e| Error::custom(e.to_string()))?;
Ok(AppendVec {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved this logic to newly created fn new_empty_map. I can't live with this code. ;)

Comment thread runtime/src/append_vec.rs
map,
append_offset: Mutex::new(current_len),
current_len: AtomicUsize::new(current_len),
file_size: current_len as u64,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: I changed this behavior because this looked just a wrong thing. New code started to initialize this correctly with actual file size.

Or is this intentional to make appencvecs read-only?

Comment thread runtime/src/append_vec.rs
}

#[test]
#[should_panic(expected = "too small file size 0 for AppendVec")]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know those should_panics are rather ugly. I'll brush up once this PR's direction is affirmed.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other uses are fixed by now. Only this will remain as this is testing a panic from ::new().

Comment thread runtime/src/append_vec.rs
fn sanitize_mmap_size(size: usize) -> io::Result<()> {
if size == 0 {
Err(std::io::Error::new(
std::io::ErrorKind::Other,
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know these Errors are not welcomed as explicitly mentioned by #6446.

@ryoqun ryoqun changed the title [wip] Sanitize append vec offset [wip] Sanitize AppendVec's file_size Dec 9, 2019
Comment thread runtime/src/append_vec.rs

#[allow(clippy::mutex_atomic)]
pub fn set_file<P: AsRef<Path>>(&mut self, path: P) -> io::Result<()> {
self.path = path.as_ref().to_path_buf();
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only update self.path in an atomic way if everything went successful here.

Comment thread runtime/src/append_vec.rs

let map = unsafe { MmapMut::map_mut(&data)? };

self.file_size = file_size;
Copy link
Copy Markdown
Contributor Author

@ryoqun ryoqun Dec 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update file_size correctly, will be used later PRs to check the sum of contained accounts doesn't exceed this and moreover exactly matches to the current_len.

Copy link
Copy Markdown
Contributor Author

@ryoqun ryoqun Dec 19, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update file_size correctly, will be used later PRs to check the sum of contained acconts doesn't exceed this and moreover exactly matches to the current_len.

As promised by 2 weeks ago's myself, this is done by this and this.

@codecov
Copy link
Copy Markdown

codecov Bot commented Dec 9, 2019

Codecov Report

Merging #7373 into master will decrease coverage by 9.8%.
The diff coverage is 64.4%.

@@           Coverage Diff            @@
##           master   #7373     +/-   ##
========================================
- Coverage    68.7%   58.9%   -9.9%     
========================================
  Files         244     244             
  Lines       56028   64972   +8944     
========================================
- Hits        38530   38309    -221     
- Misses      17498   26663   +9165

Comment thread runtime/src/append_vec.rs Outdated
}
}

AppendVec::sanitize_mmap_size(size).unwrap();
Copy link
Copy Markdown
Contributor Author

@ryoqun ryoqun Dec 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, unwrap()ing here just because considering this is under the supertubes milestone and there isn't enough time to do large refactoring (would mean Bank.store() starts to fail). There are many other security issues to be fixed for snapshot for the milesone.

I'm pretty sure this code (=AppendVec::new) isn't touched by the snapshot deserialization code path at all.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move this above if create {

@ryoqun
Copy link
Copy Markdown
Contributor Author

ryoqun commented Dec 9, 2019

@sakridge @mvines Could you take a look? Of course, you can do in your spare time possibly after the ongoing super fun time has passed. :)

Comment thread runtime/src/append_vec.rs

#[allow(clippy::mutex_atomic)]
pub fn new_empty_map(current_len: usize) -> Self {
let map = MmapMut::map_anon(1).expect("failed to map the data file");
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error handling is made more critical rather undesirably from Err to just move the code here. But combined with this consideration, this can be tolerated to avoid large refactoring. :) And this mmap will almost never fail.

Comment thread runtime/src/append_vec.rs Outdated
let file_size = std::fs::metadata(&path)?.len();
assert!(current_len <= file_size as usize);

AppendVec::sanitize_mmap_size(file_size as usize)?;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice the ?; Now we're correctly propagating this error up to the snapshot deserializing code.

Comment thread runtime/src/append_vec.rs Outdated
@sakridge
Copy link
Copy Markdown
Contributor

sakridge commented Dec 9, 2019

Overall it looks pretty good to me.

Comment thread runtime/src/append_vec.rs Outdated
@ryoqun
Copy link
Copy Markdown
Contributor Author

ryoqun commented Dec 12, 2019

@mvines pinging for your first impression of this PR. Especially this introduces another fixed/constant cluster-wide-common hard limit in the snapshot area :)

@stale
Copy link
Copy Markdown

stale Bot commented Dec 19, 2019

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale Bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 19, 2019
@stale stale Bot removed the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 19, 2019
@ryoqun ryoqun changed the title [wip] Sanitize AppendVec's file_size Sanitize AppendVec's file_size Dec 19, 2019
@ryoqun ryoqun marked this pull request as ready for review December 19, 2019 10:30
@ryoqun
Copy link
Copy Markdown
Contributor Author

ryoqun commented Dec 19, 2019

Another round of brush up and I think this PR isn't draft anymore with good confidence. :)

@sakridge @mvines Could you review this again for being merged?

@ryoqun ryoqun requested review from mvines and sakridge December 19, 2019 10:32
Comment thread runtime/src/append_vec.rs
@stale
Copy link
Copy Markdown

stale Bot commented Dec 31, 2019

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.

@stale stale Bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 31, 2019
@ryoqun ryoqun removed the stale [bot only] Added to stale content; results in auto-close after a week. label Jan 6, 2020
Copy link
Copy Markdown
Contributor

@sakridge sakridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@ryoqun ryoqun merged commit 58e6d4a into solana-labs:master Jan 6, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants