Skip to content

Commit 226156f

Browse files
committed
Auto merge of #808 - RalfJung:extra-fn, r=RalfJung
use Dlsym support to implement getentropy (and better thread spawn error) This is the Miri side of rust-lang/rust#62245. Fixes #789
2 parents cb09fab + fbf3f5e commit 226156f

File tree

10 files changed

+186
-124
lines changed

10 files changed

+186
-124
lines changed

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
481068a707679257e2a738b40987246e0420e787
1+
b820c761744db080ff7a4ba3ac88d259065cb836

src/eval.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc::mir;
1111

1212
use crate::{
1313
InterpResult, InterpError, InterpCx, StackPopCleanup, struct_error,
14-
Scalar, Tag, Pointer,
14+
Scalar, Tag, Pointer, FnVal,
1515
MemoryExtra, MiriMemoryKind, Evaluator, TlsEvalContextExt,
1616
};
1717

@@ -93,7 +93,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
9393
let mut args = ecx.frame().body.args_iter();
9494

9595
// First argument: pointer to `main()`.
96-
let main_ptr = ecx.memory_mut().create_fn_alloc(main_instance);
96+
let main_ptr = ecx.memory_mut().create_fn_alloc(FnVal::Instance(main_instance));
9797
let dest = ecx.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
9898
ecx.write_scalar(Scalar::Ptr(main_ptr), dest)?;
9999

src/helpers.rs

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use std::mem;
22

3-
use rustc::ty::{self, layout::{self, Size}};
3+
use rustc::ty::{self, layout::{self, Size, Align}};
44
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
55

6+
use rand::RngCore;
7+
68
use crate::*;
79

810
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
@@ -65,6 +67,40 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6567
})
6668
}
6769

70+
/// Generate some random bytes, and write them to `dest`.
71+
fn gen_random(
72+
&mut self,
73+
len: usize,
74+
ptr: Scalar<Tag>,
75+
) -> InterpResult<'tcx> {
76+
let this = self.eval_context_mut();
77+
78+
let ptr = match this.memory().check_ptr_access(ptr, Size::from_bytes(len as u64), Align::from_bytes(1).unwrap())? {
79+
Some(ptr) => ptr,
80+
None => return Ok(()), // zero-sized access
81+
};
82+
83+
let data = match &mut this.memory_mut().extra.rng {
84+
Some(rng) => {
85+
let mut rng = rng.borrow_mut();
86+
let mut data = vec![0; len];
87+
rng.fill_bytes(&mut data);
88+
data
89+
}
90+
None => {
91+
return err!(Unimplemented(
92+
"miri does not support gathering system entropy in deterministic mode!
93+
Use '-Zmiri-seed=<seed>' to enable random number generation.
94+
WARNING: Miri does *not* generate cryptographically secure entropy -
95+
do not use Miri to run any program that needs secure random number generation".to_owned(),
96+
));
97+
}
98+
};
99+
let tcx = &{this.tcx.tcx};
100+
this.memory_mut().get_mut(ptr.alloc_id)?
101+
.write_bytes(tcx, ptr, &data)
102+
}
103+
68104
/// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
69105
/// will be true if this is frozen, false if this is in an `UnsafeCell`.
70106
fn visit_freeze_sensitive(

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,14 @@ pub use crate::shims::{EvalContextExt as ShimsEvalContextExt};
3131
pub use crate::shims::foreign_items::EvalContextExt as ForeignItemsEvalContextExt;
3232
pub use crate::shims::intrinsics::EvalContextExt as IntrinsicsEvalContextExt;
3333
pub use crate::shims::tls::{EvalContextExt as TlsEvalContextExt, TlsData};
34+
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as DlsymEvalContextExt};
3435
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
3536
pub use crate::range_map::RangeMap;
3637
pub use crate::helpers::{EvalContextExt as HelpersEvalContextExt};
3738
pub use crate::mono_hash_map::MonoHashMap;
3839
pub use crate::stacked_borrows::{EvalContextExt as StackedBorEvalContextExt, Tag, Permission, Stack, Stacks, Item};
3940
pub use crate::machine::{
40-
PAGE_SIZE, STACK_ADDR, NUM_CPUS,
41+
PAGE_SIZE, STACK_ADDR, STACK_SIZE, NUM_CPUS,
4142
MemoryExtra, AllocExtra, MiriMemoryKind, Evaluator, MiriEvalContext, MiriEvalContextExt,
4243
};
4344
pub use crate::eval::{eval_main, create_ecx, MiriConfig};

src/machine.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ use rand::rngs::StdRng;
1111
use syntax::attr;
1212
use syntax::symbol::sym;
1313
use rustc::hir::def_id::DefId;
14-
use rustc::ty::{self, layout::{Size, LayoutOf}, query::TyCtxtAt};
14+
use rustc::ty::{self, layout::{Size, LayoutOf}, TyCtxt};
1515
use rustc::mir;
1616

1717
use crate::*;
1818

1919
// Some global facts about the emulated machine.
2020
pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture
21-
pub const STACK_ADDR: u64 = 16*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
21+
pub const STACK_ADDR: u64 = 32*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
22+
pub const STACK_SIZE: u64 = 16*PAGE_SIZE; // whatever
2223
pub const NUM_CPUS: u64 = 1;
2324

2425
/// Extra memory kinds
@@ -135,6 +136,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
135136
type MemoryExtra = MemoryExtra;
136137
type AllocExtra = AllocExtra;
137138
type PointerTag = Tag;
139+
type ExtraFnVal = Dlsym;
138140

139141
type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
140142

@@ -145,7 +147,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
145147
ecx.memory().extra.validate
146148
}
147149

148-
/// Returns `Ok()` when the function was handled; fail otherwise.
149150
#[inline(always)]
150151
fn find_fn(
151152
ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -157,6 +158,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
157158
ecx.find_fn(instance, args, dest, ret)
158159
}
159160

161+
#[inline(always)]
162+
fn call_extra_fn(
163+
ecx: &mut InterpCx<'mir, 'tcx, Self>,
164+
fn_val: Dlsym,
165+
args: &[OpTy<'tcx, Tag>],
166+
dest: Option<PlaceTy<'tcx, Tag>>,
167+
ret: Option<mir::BasicBlock>,
168+
) -> InterpResult<'tcx> {
169+
ecx.call_dlsym(fn_val, args, dest, ret)
170+
}
171+
160172
#[inline(always)]
161173
fn call_intrinsic(
162174
ecx: &mut rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>,
@@ -220,8 +232,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
220232
}
221233

222234
fn find_foreign_static(
235+
tcx: TyCtxt<'tcx>,
223236
def_id: DefId,
224-
tcx: TyCtxtAt<'tcx>,
225237
) -> InterpResult<'tcx, Cow<'tcx, Allocation>> {
226238
let attrs = tcx.get_attrs(def_id);
227239
let link_name = match attr::first_attr_value_str_by_name(&attrs, sym::link_name) {
@@ -251,20 +263,20 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
251263
}
252264

253265
fn tag_allocation<'b>(
266+
memory_extra: &MemoryExtra,
254267
id: AllocId,
255268
alloc: Cow<'b, Allocation>,
256269
kind: Option<MemoryKind<Self::MemoryKinds>>,
257-
memory: &Memory<'mir, 'tcx, Self>,
258270
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
259271
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
260272
let alloc = alloc.into_owned();
261-
let (stacks, base_tag) = if !memory.extra.validate {
273+
let (stacks, base_tag) = if !memory_extra.validate {
262274
(None, Tag::Untagged)
263275
} else {
264276
let (stacks, base_tag) = Stacks::new_allocation(
265277
id,
266278
Size::from_bytes(alloc.bytes.len() as u64),
267-
Rc::clone(&memory.extra.stacked_borrows),
279+
Rc::clone(&memory_extra.stacked_borrows),
268280
kind,
269281
);
270282
(Some(stacks), base_tag)
@@ -273,18 +285,18 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
273285
assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
274286
// Now we can rely on the inner pointers being static, too.
275287
}
276-
let mut memory_extra = memory.extra.stacked_borrows.borrow_mut();
288+
let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
277289
let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
278290
bytes: alloc.bytes,
279291
relocations: Relocations::from_presorted(
280292
alloc.relocations.iter()
281293
// The allocations in the relocations (pointers stored *inside* this allocation)
282294
// all get the base pointer tag.
283295
.map(|&(offset, ((), alloc))| {
284-
let tag = if !memory.extra.validate {
296+
let tag = if !memory_extra.validate {
285297
Tag::Untagged
286298
} else {
287-
memory_extra.static_base_ptr(alloc)
299+
stacked_borrows.static_base_ptr(alloc)
288300
};
289301
(offset, (tag, alloc))
290302
})
@@ -302,13 +314,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
302314

303315
#[inline(always)]
304316
fn tag_static_base_pointer(
317+
memory_extra: &MemoryExtra,
305318
id: AllocId,
306-
memory: &Memory<'mir, 'tcx, Self>,
307319
) -> Self::PointerTag {
308-
if !memory.extra.validate {
320+
if !memory_extra.validate {
309321
Tag::Untagged
310322
} else {
311-
memory.extra.stacked_borrows.borrow_mut().static_base_ptr(id)
323+
memory_extra.stacked_borrows.borrow_mut().static_base_ptr(id)
312324
}
313325
}
314326

@@ -342,8 +354,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
342354
}
343355

344356
fn int_to_ptr(
345-
int: u64,
346357
memory: &Memory<'mir, 'tcx, Self>,
358+
int: u64,
347359
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
348360
if int == 0 {
349361
err!(InvalidNullPointerUsage)
@@ -355,8 +367,8 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
355367
}
356368

357369
fn ptr_to_int(
358-
ptr: Pointer<Self::PointerTag>,
359370
memory: &Memory<'mir, 'tcx, Self>,
371+
ptr: Pointer<Self::PointerTag>,
360372
) -> InterpResult<'tcx, u64> {
361373
if memory.extra.rng.is_none() {
362374
err!(ReadPointerAsBytes)

src/shims/dlsym.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use rustc::mir;
2+
3+
use crate::*;
4+
5+
#[derive(Debug, Copy, Clone)]
6+
pub enum Dlsym {
7+
GetEntropy,
8+
}
9+
10+
impl Dlsym {
11+
// Returns an error for unsupported symbols, and None if this symbol
12+
// should become a NULL pointer (pretend it does not exist).
13+
pub fn from_str(name: &str) -> InterpResult<'static, Option<Dlsym>> {
14+
use self::Dlsym::*;
15+
Ok(match name {
16+
"getentropy" => Some(GetEntropy),
17+
"__pthread_get_minstack" => None,
18+
_ =>
19+
return err!(Unimplemented(format!(
20+
"Unsupported dlsym: {}", name
21+
))),
22+
})
23+
}
24+
}
25+
26+
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
27+
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
28+
fn call_dlsym(
29+
&mut self,
30+
dlsym: Dlsym,
31+
args: &[OpTy<'tcx, Tag>],
32+
dest: Option<PlaceTy<'tcx, Tag>>,
33+
ret: Option<mir::BasicBlock>,
34+
) -> InterpResult<'tcx> {
35+
use self::Dlsym::*;
36+
37+
let this = self.eval_context_mut();
38+
39+
let dest = dest.expect("we don't support any diverging dlsym");
40+
let ret = ret.expect("dest is `Some` but ret is `None`");
41+
42+
match dlsym {
43+
GetEntropy => {
44+
let ptr = this.read_scalar(args[0])?.not_undef()?;
45+
let len = this.read_scalar(args[1])?.to_usize(this)?;
46+
this.gen_random(len as usize, ptr)?;
47+
this.write_null(dest)?;
48+
}
49+
}
50+
51+
this.goto_block(Some(ret))?;
52+
this.dump_place(*dest);
53+
Ok(())
54+
}
55+
}

0 commit comments

Comments
 (0)