48
48
//! * if I/O can be isolated to separate profiling events, and doesn't impact
49
49
//! execution in a more subtle way (see below), the deterministic parts of
50
50
//! the program can still be profiled with high accuracy
51
- //! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, thread scheduling)
51
+ //! * intentional uses of randomness may change execution paths, though for
52
+ //! cryptographic operations specifically, "constant time" implementations
53
+ //! are preferred / necessary (in order to limit an external observer's
54
+ //! ability to infer secrets), so they're not as much of a problem
55
+ //! * even otherwise-deterministic machine-local communication (to e.g. system
56
+ //! services or drivers) can behave unpredictably (especially under load)
57
+ //! * while we haven't observed this in the wild yet, it's possible for
58
+ //! file reads/writes to be split up into multiple smaller chunks
59
+ //! (and therefore take more userspace instructions to fully read/write)
60
+ //! * low-level non-determinism (e.g. ASLR, randomized `HashMap`s, timers)
52
61
//! * ASLR ("Address Space Layout Randomization"), may be provided by the OS for
53
62
//! security reasons, or accidentally caused through allocations that depend on
54
63
//! random data (even as low-entropy as e.g. the base 10 length of a process ID)
65
74
//! ASLR and ASLR-like effects, making the entire program more sensitive
66
75
//! * the default hasher is randomized, and while `rustc` doesn't use it,
67
76
//! proc macros can (and will), and it's harder to disable than Linux ASLR
68
- //! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
69
- //! has a 10 second "purge timer", which can introduce an ASLR-like effect,
70
- //! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
77
+ //! * most ways of measuring time will inherently never perfectly align with
78
+ //! exact points in the program's execution, making time behave like another
79
+ //! low-entropy source of randomness - this also means timers will elapse at
80
+ //! unpredictable points (which can further impact the rest of the execution)
81
+ //! * this includes the common thread scheduler technique of preempting the
82
+ //! currently executing thread with a periodic timer interrupt, so the exact
83
+ //! interleaving of multiple threads will likely not be reproducible without
84
+ //! special OS configuration, or tools that emulate a deterministic scheduler
85
+ //! * `jemalloc` (the allocator used by `rustc`, at least in official releases)
86
+ //! has a 10 second "purge timer", which can introduce an ASLR-like effect,
87
+ //! unless disabled with `MALLOC_CONF=dirty_decay_ms:0,muzzy_decay_ms:0`
71
88
//! * hardware flaws (whether in the design or implementation)
72
89
//! * hardware interrupts ("IRQs") and exceptions (like page faults) cause
73
90
//! overcounting (1 instruction per interrupt, possibly the `iret` from the
@@ -525,10 +542,10 @@ mod hw {
525
542
} else {
526
543
asm ! (
527
544
// Dummy `cpuid(0)` to serialize instruction execution.
528
- "xor eax, eax" ,
545
+ "xor % eax, % eax" , // Intel syntax: "xor eax, eax"
529
546
"cpuid" ,
530
547
531
- "mov ecx, {rdpmc_ecx:e}" ,
548
+ "mov {rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {rdpmc_ecx:e}"
532
549
"rdpmc" ,
533
550
rdpmc_ecx = in( reg) reg_idx,
534
551
out( "eax" ) lo,
@@ -539,6 +556,12 @@ mod hw {
539
556
out( "ecx" ) _,
540
557
541
558
options( nostack) ,
559
+
560
+ // HACK(eddyb) LLVM 9 and older do not support modifiers
561
+ // in Intel syntax inline asm; whenever Rust minimum LLVM
562
+ // version becomes LLVM 10, remove and replace above
563
+ // instructions with Intel syntax version (from comments).
564
+ options( att_syntax) ,
542
565
) ;
543
566
}
544
567
}
@@ -556,14 +579,14 @@ mod hw {
556
579
unsafe {
557
580
asm ! (
558
581
// Dummy `cpuid(0)` to serialize instruction execution.
559
- "xor eax, eax" ,
582
+ "xor % eax, % eax" , // Intel syntax: "xor eax, eax"
560
583
"cpuid" ,
561
584
562
- "mov ecx, {a_rdpmc_ecx:e}" ,
585
+ "mov {a_rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {a_rdpmc_ecx:e}"
563
586
"rdpmc" ,
564
- "mov {a_rdpmc_eax:e}, eax" ,
565
- "mov {a_rdpmc_edx:e}, edx" ,
566
- "mov ecx, {b_rdpmc_ecx:e}" ,
587
+ "mov %eax, {a_rdpmc_eax:e}" , // Intel syntax: "mov {a_rdpmc_eax:e}, eax"
588
+ "mov %edx, {a_rdpmc_edx:e}" , // Intel syntax: "mov {a_rdpmc_edx:e}, edx"
589
+ "mov {b_rdpmc_ecx:e}, % ecx" , // Intel syntax: "mov ecx, {b_rdpmc_ecx:e}"
567
590
"rdpmc" ,
568
591
a_rdpmc_ecx = in( reg) a_reg_idx,
569
592
a_rdpmc_eax = out( reg) a_lo,
@@ -577,6 +600,12 @@ mod hw {
577
600
out( "ecx" ) _,
578
601
579
602
options( nostack) ,
603
+
604
+ // HACK(eddyb) LLVM 9 and older do not support modifiers
605
+ // in Intel syntax inline asm; whenever Rust minimum LLVM
606
+ // version becomes LLVM 10, remove and replace above
607
+ // instructions with Intel syntax version (from comments).
608
+ options( att_syntax) ,
580
609
) ;
581
610
}
582
611
(
@@ -786,10 +815,17 @@ mod hw {
786
815
let mut _tmp: u64 = 0 ;
787
816
unsafe {
788
817
asm ! (
789
- "lock xadd qword ptr [{atomic}], {tmp}" ,
818
+ // Intel syntax: "lock xadd [{atomic}], {tmp}"
819
+ "lock xadd {tmp}, ({atomic})" ,
790
820
791
821
atomic = in( reg) & mut atomic,
792
822
tmp = inout( reg) _tmp,
823
+
824
+ // HACK(eddyb) LLVM 9 and older do not support modifiers
825
+ // in Intel syntax inline asm; whenever Rust minimum LLVM
826
+ // version becomes LLVM 10, remove and replace above
827
+ // instructions with Intel syntax version (from comments).
828
+ options( att_syntax) ,
793
829
) ;
794
830
}
795
831
0 commit comments