nx_g22_adversary.nx source
↩ module page · 55 lines · 2667 B
1// nx_g22_adversary.nx -- G22 bias-via-cmov FLAG-RIDE adversary (T9 class).
2// Crafts the exact hazard the testq protects against: the textually-previous
3// ALU result is POSITIVE (SF=0) while the DIVIDEND is negative and NON-EXACT,
4// so a stale-flag ride (negctl X86_NEGCTL_G22_RIDE_ALWAYS=1) skips the bias
5// and truncation-toward-zero silently becomes floor: -101/4 = -25, floor -26.
6// Self-checking: exit 0 = all correct; a nonzero exit names the failing case.
7// The shipped ride gate never fires here (the previous ALU produced t, NOT the
8// dividend), so the testq is emitted and this stays GREEN; RIDE_ALWAYS -> RED.
9// license_tier: ORIGINAL No hw writes (Rule 26).
10import "nx_syscalls_x86_64.nx"
11const K_MAGIC_1000000000: i64 = 1000000000
12const K_MAGIC_9223372036854775807: i64 = 9223372036854775807
13const K_MAGIC_4611686018427387904: i64 = 4611686018427387904
14
15// t = p + q is a POSITIVE ALU result right before the div; x is negative.
16// t feeds the result through an UNFOLDABLE runtime div (t/1e9 == 0 for the
17// test inputs) so no algebraic identity can DCE the ADD and de-tooth the
18// adversary; that div sits AFTER the probed one, so adjacency is untouched.
19func g22_stale_pos(x: i64, p: i64, q: i64) -> i64 {
20 let t: i64 = p + q
21 let z: i64 = x / 4
22 return z + t / K_MAGIC_1000000000
23}
24
25// Mirror case: previous ALU result NEGATIVE (SF=1), dividend POSITIVE and
26// non-exact -- a stale ride would ADD the bias where none belongs: 101/4 = 25,
27// biased (101+3)>>2 = 26.
28func g22_stale_neg(x: i64, p: i64, q: i64) -> i64 {
29 let t: i64 = p - q
30 let z: i64 = x / 4
31 return z + t / K_MAGIC_1000000000
32}
33
34// Ride-ELIGIBLE shape (prev ALU produced the dividend itself): the shipped
35// gate rides here, and the flags are per the dividend by construction --
36// correct with or without the testq. Guards the gate's positive direction.
37func g22_ride_ok(p: i64, q: i64) -> i64 {
38 let x: i64 = p - q
39 return x / 8
40}
41
42func main() -> i64 {
43 // stale-positive-flags, negative dividend: -101/4 MUST be -25 (trunc).
44 if g22_stale_pos(0 - 101, 40, 60) != (0 - 25) { return 1 }
45 // stale-negative-flags, positive dividend: 101/4 MUST be 25.
46 if g22_stale_neg(101, 40, 100) != 25 { return 2 }
47 // INT_MIN edge through the cmov form: INT_MIN/2 = -2^62 exactly.
48 let im: i64 = 0 - K_MAGIC_9223372036854775807 - 1
49 if (im / 2) != (0 - K_MAGIC_4611686018427387904) { return 3 }
50 // ride-eligible: (40-141)/8 = -101/8 = -12 (trunc), flags per dividend.
51 if g22_ride_ok(40, 141) != (0 - 12) { return 4 }
52 // ride-eligible positive: (141-40)/8 = 101/8 = 12.
53 if g22_ride_ok(141, 40) != 12 { return 5 }
54 return 0
55}