Skip to content

Commit e092d0b

Browse files
committed
Auto merge of rust-lang#99299 - Mark-Simulacrum:stable-next, r=Mark-Simulacrum
[stable] 1.62.1 release This bundles: * Windows: Fallback for overlapped I/O rust-lang#98950 * don't succeed evaluate_obligation query if new opaque types were registered rust-lang#98614 * Mitigate MMIO stale data vulnerability rust-lang#98126 * Return a FxIndexSet in is_late_bound query. rust-lang#99219 Also bumps the version number to 1.62.1 and includes a short release notes section for the release. r? `@Mark-Simulacrum`
2 parents a8314ef + 647922f commit e092d0b

File tree

36 files changed

+442
-212
lines changed

36 files changed

+442
-212
lines changed

RELEASES.md

+18
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
Version 1.62.1 (2022-07-19)
2+
==========================
3+
4+
Rust 1.62.1 addresses a few recent regressions in the compiler and standard
5+
library, and also mitigates a CPU vulnerability on Intel SGX.
6+
7+
* [The compiler fixed unsound function coercions involving `impl Trait` return types.][98608]
8+
* [The compiler fixed an incremental compilation bug with `async fn` lifetimes.][98890]
9+
* [Windows added a fallback for overlapped I/O in synchronous reads and writes.][98950]
10+
* [The `x86_64-fortanix-unknown-sgx` target added a mitigation for the
11+
MMIO stale data vulnerability][98126], advisory [INTEL-SA-00615].
12+
13+
[98608]: https://github.com/rust-lang/rust/issues/98608
14+
[98890]: https://github.com/rust-lang/rust/issues/98890
15+
[98950]: https://github.com/rust-lang/rust/pull/98950
16+
[98126]: https://github.com/rust-lang/rust/pull/98126
17+
[INTEL-SA-00615]: https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html
18+
119
Version 1.62.0 (2022-06-30)
220
==========================
321

compiler/rustc_infer/src/infer/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
929929
.region_constraints_added_in_snapshot(&snapshot.undo_snapshot)
930930
}
931931

932+
pub fn opaque_types_added_in_snapshot(&self, snapshot: &CombinedSnapshot<'a, 'tcx>) -> bool {
933+
self.inner.borrow().undo_log.opaque_types_in_snapshot(&snapshot.undo_snapshot)
934+
}
935+
932936
pub fn add_given(&self, sub: ty::Region<'tcx>, sup: ty::RegionVid) {
933937
self.inner.borrow_mut().unwrap_region_constraints().add_given(sub, sup);
934938
}

compiler/rustc_infer/src/infer/opaque_types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
9999
}
100100
let (a, b) = if a_is_expected { (a, b) } else { (b, a) };
101101
let process = |a: Ty<'tcx>, b: Ty<'tcx>| match *a.kind() {
102-
ty::Opaque(def_id, substs) => {
102+
ty::Opaque(def_id, substs) if def_id.is_local() => {
103103
let origin = if self.defining_use_anchor.is_some() {
104104
// Check that this is `impl Trait` type is
105105
// declared by `parent_def_id` -- i.e., one whose

compiler/rustc_infer/src/infer/undo_log.rs

+4
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,10 @@ impl<'tcx> InferCtxtUndoLogs<'tcx> {
185185
})
186186
}
187187

188+
pub(crate) fn opaque_types_in_snapshot(&self, s: &Snapshot<'tcx>) -> bool {
189+
self.logs[s.undo_len..].iter().any(|log| matches!(log, UndoLog::OpaqueTypes(..)))
190+
}
191+
188192
pub(crate) fn region_constraints(
189193
&self,
190194
) -> impl Iterator<Item = &'_ region_constraints::UndoLog<'tcx>> + Clone {

compiler/rustc_infer/src/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ impl<'tcx> ProjectionCache<'_, 'tcx> {
203203
Some(&ProjectionCacheEntry::NormalizedTy { ref ty, complete: _ }) => {
204204
info!("ProjectionCacheEntry::complete({:?}) - completing {:?}", key, ty);
205205
let mut ty = ty.clone();
206-
if result == EvaluationResult::EvaluatedToOk {
206+
if result.must_apply_considering_regions() {
207207
ty.obligations = vec![];
208208
}
209209
map.insert(key, ProjectionCacheEntry::NormalizedTy { ty, complete: Some(result) });

compiler/rustc_middle/src/arena.rs

+1
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ macro_rules! arena_types {
8585
[] attribute: rustc_ast::Attribute,
8686
[] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
8787
[] hir_id_set: rustc_hir::HirIdSet,
88+
[] late_bound_lifetimes: rustc_data_structures::fx::FxIndexSet<rustc_hir::def_id::LocalDefId>,
8889

8990
// Interned types
9091
[] tys: rustc_data_structures::intern::WithStableHash<rustc_middle::ty::TyS<'tcx>>,

compiler/rustc_middle/src/middle/resolve_lifetime.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::ty;
44

5-
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
5+
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
66
use rustc_hir::def_id::{DefId, LocalDefId};
77
use rustc_hir::ItemLocalId;
88
use rustc_macros::HashStable;
@@ -64,7 +64,7 @@ pub struct ResolveLifetimes {
6464
/// Set of lifetime def ids that are late-bound; a region can
6565
/// be late-bound if (a) it does NOT appear in a where-clause and
6666
/// (b) it DOES appear in the arguments.
67-
pub late_bound: FxHashMap<LocalDefId, FxHashSet<LocalDefId>>,
67+
pub late_bound: FxHashMap<LocalDefId, FxIndexSet<LocalDefId>>,
6868

6969
pub late_bound_vars: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Vec<ty::BoundVariableKind>>>,
7070
}

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ rustc_queries! {
15371537
Option<&'tcx FxHashMap<ItemLocalId, Region>> {
15381538
desc { "looking up a named region" }
15391539
}
1540-
query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
1540+
query is_late_bound_map(_: LocalDefId) -> Option<(LocalDefId, &'tcx FxIndexSet<LocalDefId>)> {
15411541
desc { "testing if a region is late bound" }
15421542
}
15431543
/// For a given item (like a struct), gets the default lifetimes to be used

compiler/rustc_middle/src/traits/select.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,10 @@ pub enum EvaluationResult {
176176
EvaluatedToOk,
177177
/// Evaluation successful, but there were unevaluated region obligations.
178178
EvaluatedToOkModuloRegions,
179+
/// Evaluation successful, but need to rerun because opaque types got
180+
/// hidden types assigned without it being known whether the opaque types
181+
/// are within their defining scope
182+
EvaluatedToOkModuloOpaqueTypes,
179183
/// Evaluation is known to be ambiguous -- it *might* hold for some
180184
/// assignment of inference variables, but it might not.
181185
///
@@ -252,9 +256,11 @@ impl EvaluationResult {
252256

253257
pub fn may_apply(self) -> bool {
254258
match self {
255-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
256-
true
257-
}
259+
EvaluatedToOkModuloOpaqueTypes
260+
| EvaluatedToOk
261+
| EvaluatedToOkModuloRegions
262+
| EvaluatedToAmbig
263+
| EvaluatedToUnknown => true,
258264

259265
EvaluatedToErr | EvaluatedToRecur => false,
260266
}
@@ -264,7 +270,11 @@ impl EvaluationResult {
264270
match self {
265271
EvaluatedToUnknown | EvaluatedToRecur => true,
266272

267-
EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
273+
EvaluatedToOkModuloOpaqueTypes
274+
| EvaluatedToOk
275+
| EvaluatedToOkModuloRegions
276+
| EvaluatedToAmbig
277+
| EvaluatedToErr => false,
268278
}
269279
}
270280
}

compiler/rustc_middle/src/ty/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ impl<'tcx> InstantiatedPredicates<'tcx> {
10651065
Lift
10661066
)]
10671067
pub struct OpaqueTypeKey<'tcx> {
1068+
// FIXME(oli-obk): make this a LocalDefId
10681069
pub def_id: DefId,
10691070
pub substs: SubstsRef<'tcx>,
10701071
}

compiler/rustc_middle/src/ty/query.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use crate::ty::{self, AdtSizedConstraint, CrateInherentImpls, ParamEnvAnd, Ty, T
3636
use rustc_ast as ast;
3737
use rustc_ast::expand::allocator::AllocatorKind;
3838
use rustc_attr as attr;
39-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
39+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
4040
use rustc_data_structures::steal::Steal;
4141
use rustc_data_structures::svh::Svh;
4242
use rustc_data_structures::sync::Lrc;

compiler/rustc_resolve/src/late/lifetimes.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot};
1010
use rustc_ast::walk_list;
11-
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
11+
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
1212
use rustc_errors::{struct_span_err, Applicability, Diagnostic};
1313
use rustc_hir as hir;
1414
use rustc_hir::def::{DefKind, Res};
@@ -482,6 +482,11 @@ fn convert_named_region_map(tcx: TyCtxt<'_>, named_region_map: NamedRegionMap) -
482482
let def_id = tcx.hir().local_def_id(hir_id);
483483
map.insert(def_id);
484484
}
485+
for (_, late_bound) in &mut rl.late_bound {
486+
late_bound.sort_by(|&a, &b| {
487+
tcx.def_path_hash(a.to_def_id()).cmp(&tcx.def_path_hash(b.to_def_id()))
488+
});
489+
}
485490
for (hir_id, v) in named_region_map.late_bound_vars {
486491
let map = rl.late_bound_vars.entry(hir_id.owner).or_default();
487492
map.insert(hir_id.local_id, v);
@@ -540,7 +545,7 @@ fn item_for(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> LocalDefId {
540545
fn is_late_bound_map<'tcx>(
541546
tcx: TyCtxt<'tcx>,
542547
def_id: LocalDefId,
543-
) -> Option<(LocalDefId, &'tcx FxHashSet<LocalDefId>)> {
548+
) -> Option<(LocalDefId, &'tcx FxIndexSet<LocalDefId>)> {
544549
match tcx.def_kind(def_id) {
545550
DefKind::AnonConst | DefKind::InlineConst => {
546551
let mut def_id = tcx.local_parent(def_id);

compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs

+1
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
761761
Ok(
762762
EvaluationResult::EvaluatedToOk
763763
| EvaluationResult::EvaluatedToOkModuloRegions
764+
| EvaluationResult::EvaluatedToOkModuloOpaqueTypes
764765
| EvaluationResult::EvaluatedToAmbig,
765766
) => {}
766767
_ => return false,

compiler/rustc_trait_selection/src/traits/select/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
388388
Err(_) => return Ok(EvaluatedToErr),
389389
}
390390

391+
if self.infcx.opaque_types_added_in_snapshot(snapshot) {
392+
return Ok(result.max(EvaluatedToOkModuloOpaqueTypes));
393+
}
394+
391395
match self.infcx.region_constraints_added_in_snapshot(snapshot) {
392396
None => Ok(result),
393397
Some(_) => Ok(result.max(EvaluatedToOkModuloRegions)),

compiler/rustc_type_ir/src/lib.rs

-8
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,6 @@ bitflags! {
6161
| TypeFlags::HAS_CT_INFER.bits
6262
| TypeFlags::HAS_TY_PLACEHOLDER.bits
6363
| TypeFlags::HAS_CT_PLACEHOLDER.bits
64-
// The `evaluate_obligation` query does not return further
65-
// obligations. If it evaluates an obligation with an opaque
66-
// type, that opaque type may get compared to another type,
67-
// constraining it. We would lose this information.
68-
// FIXME: differentiate between crate-local opaque types
69-
// and opaque types from other crates, as only opaque types
70-
// from the local crate can possibly be a local name
71-
| TypeFlags::HAS_TY_OPAQUE.bits
7264
// We consider 'freshened' types and constants
7365
// to depend on a particular fn.
7466
// The freshening process throws away information,

library/std/src/sys/sgx/abi/usercalls/alloc.rs

+110-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
#![allow(unused)]
22

3+
use crate::arch::asm;
34
use crate::cell::UnsafeCell;
5+
use crate::cmp;
6+
use crate::convert::TryInto;
47
use crate::mem;
58
use crate::ops::{CoerceUnsized, Deref, DerefMut, Index, IndexMut};
69
use crate::ptr::{self, NonNull};
710
use crate::slice;
811
use crate::slice::SliceIndex;
912

10-
use super::super::mem::is_user_range;
13+
use super::super::mem::{is_enclave_range, is_user_range};
1114
use fortanix_sgx_abi::*;
1215

1316
/// A type that can be safely read from or written to userspace.
@@ -210,7 +213,9 @@ where
210213
unsafe {
211214
// Mustn't call alloc with size 0.
212215
let ptr = if size > 0 {
213-
rtunwrap!(Ok, super::alloc(size, T::align_of())) as _
216+
// `copy_to_userspace` is more efficient when data is 8-byte aligned
217+
let alignment = cmp::max(T::align_of(), 8);
218+
rtunwrap!(Ok, super::alloc(size, alignment)) as _
214219
} else {
215220
T::align_of() as _ // dangling pointer ok for size 0
216221
};
@@ -225,13 +230,9 @@ where
225230
/// Copies `val` into freshly allocated space in user memory.
226231
pub fn new_from_enclave(val: &T) -> Self {
227232
unsafe {
228-
let ret = Self::new_uninit_bytes(mem::size_of_val(val));
229-
ptr::copy(
230-
val as *const T as *const u8,
231-
ret.0.as_ptr() as *mut u8,
232-
mem::size_of_val(val),
233-
);
234-
ret
233+
let mut user = Self::new_uninit_bytes(mem::size_of_val(val));
234+
user.copy_from_enclave(val);
235+
user
235236
}
236237
}
237238

@@ -304,6 +305,105 @@ where
304305
}
305306
}
306307

308+
/// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
309+
///
310+
/// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
311+
/// - preceded by the VERW instruction and followed by the MFENCE; LFENCE instruction sequence
312+
/// - or are in multiples of 8 bytes, aligned to an 8-byte boundary
313+
///
314+
/// # Panics
315+
/// This function panics if:
316+
///
317+
/// * The `src` pointer is null
318+
/// * The `dst` pointer is null
319+
/// * The `src` memory range is not in enclave memory
320+
/// * The `dst` memory range is not in user memory
321+
///
322+
/// # References
323+
/// - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00615.html
324+
/// - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/processor-mmio-stale-data-vulnerabilities.html#inpage-nav-3-2-2
325+
pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
326+
unsafe fn copy_bytewise_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
327+
unsafe {
328+
let mut seg_sel: u16 = 0;
329+
for off in 0..len {
330+
asm!("
331+
mov %ds, ({seg_sel})
332+
verw ({seg_sel})
333+
movb {val}, ({dst})
334+
mfence
335+
lfence
336+
",
337+
val = in(reg_byte) *src.offset(off as isize),
338+
dst = in(reg) dst.offset(off as isize),
339+
seg_sel = in(reg) &mut seg_sel,
340+
options(nostack, att_syntax)
341+
);
342+
}
343+
}
344+
}
345+
346+
unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
347+
unsafe {
348+
asm!(
349+
"rep movsq (%rsi), (%rdi)",
350+
inout("rcx") len / 8 => _,
351+
inout("rdi") dst => _,
352+
inout("rsi") src => _,
353+
options(att_syntax, nostack, preserves_flags)
354+
);
355+
}
356+
}
357+
assert!(!src.is_null());
358+
assert!(!dst.is_null());
359+
assert!(is_enclave_range(src, len));
360+
assert!(is_user_range(dst, len));
361+
assert!(len < isize::MAX as usize);
362+
assert!(!(src as usize).overflowing_add(len).1);
363+
assert!(!(dst as usize).overflowing_add(len).1);
364+
365+
if len < 8 {
366+
// Can't align on 8 byte boundary: copy safely byte per byte
367+
unsafe {
368+
copy_bytewise_to_userspace(src, dst, len);
369+
}
370+
} else if len % 8 == 0 && dst as usize % 8 == 0 {
371+
// Copying 8-byte aligned quadwords: copy quad word per quad word
372+
unsafe {
373+
copy_aligned_quadwords_to_userspace(src, dst, len);
374+
}
375+
} else {
376+
// Split copies into three parts:
377+
// +--------+
378+
// | small0 | Chunk smaller than 8 bytes
379+
// +--------+
380+
// | big | Chunk 8-byte aligned, and size a multiple of 8 bytes
381+
// +--------+
382+
// | small1 | Chunk smaller than 8 bytes
383+
// +--------+
384+
385+
unsafe {
386+
// Copy small0
387+
let small0_size = (8 - dst as usize % 8) as u8;
388+
let small0_src = src;
389+
let small0_dst = dst;
390+
copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _);
391+
392+
// Copy big
393+
let small1_size = ((len - small0_size as usize) % 8) as u8;
394+
let big_size = len - small0_size as usize - small1_size as usize;
395+
let big_src = src.offset(small0_size as _);
396+
let big_dst = dst.offset(small0_size as _);
397+
copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size);
398+
399+
// Copy small1
400+
let small1_src = src.offset(big_size as isize + small0_size as isize);
401+
let small1_dst = dst.offset(big_size as isize + small0_size as isize);
402+
copy_bytewise_to_userspace(small1_src, small1_dst, small1_size as _);
403+
}
404+
}
405+
}
406+
307407
#[unstable(feature = "sgx_platform", issue = "56975")]
308408
impl<T: ?Sized> UserRef<T>
309409
where
@@ -352,7 +452,7 @@ where
352452
pub fn copy_from_enclave(&mut self, val: &T) {
353453
unsafe {
354454
assert_eq!(mem::size_of_val(val), mem::size_of_val(&*self.0.get()));
355-
ptr::copy(
455+
copy_to_userspace(
356456
val as *const T as *const u8,
357457
self.0.get() as *mut T as *mut u8,
358458
mem::size_of_val(val),

library/std/src/sys/sgx/abi/usercalls/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use crate::time::{Duration, Instant};
66
pub(crate) mod alloc;
77
#[macro_use]
88
pub(crate) mod raw;
9+
#[cfg(test)]
10+
mod tests;
911

1012
use self::raw::*;
1113

0 commit comments

Comments
 (0)