Use read_volatile for stack_check_guard.

Its whole point is that it will be aliased if the stack overflows, so it
doesn't make sense to use a reference. In fact the compiler might
optimise away the reads. Reading a pointer is still a bit dodgy, but
better.

Test: m vmbase_example_bin
Change-Id: I23e83d2b83d945d0fe66bcbd909cd5e04a609e12
diff --git a/vmbase/example/src/layout.rs b/vmbase/example/src/layout.rs
index 2e9d27a..63f3b76 100644
--- a/vmbase/example/src/layout.rs
+++ b/vmbase/example/src/layout.rs
@@ -19,7 +19,6 @@
 use core::ops::Range;
 use log::info;
 use vmbase::layout;
-use vmbase::STACK_CHK_GUARD;
 
 /// The first 1 GiB of memory are used for MMIO.
 pub const DEVICE_REGION: MemoryRegion = MemoryRegion::new(0, 0x40000000);
@@ -108,8 +107,3 @@
         *ptr
     }
 }
-
-/// Value of __stack_chk_guard.
-pub fn stack_chk_guard() -> u64 {
-    *STACK_CHK_GUARD
-}
diff --git a/vmbase/example/src/main.rs b/vmbase/example/src/main.rs
index b3b5732..021daa4 100644
--- a/vmbase/example/src/main.rs
+++ b/vmbase/example/src/main.rs
@@ -25,7 +25,7 @@
 
 use crate::layout::{
     bionic_tls, boot_stack_range, dtb_range, print_addresses, rodata_range, scratch_range,
-    stack_chk_guard, text_range, DEVICE_REGION,
+    text_range, DEVICE_REGION,
 };
 use crate::pci::{check_pci, get_bar_region};
 use aarch64_paging::{idmap::IdMap, paging::Attributes};
@@ -33,7 +33,7 @@
 use fdtpci::PciInfo;
 use libfdt::Fdt;
 use log::{debug, error, info, trace, warn, LevelFilter};
-use vmbase::{configure_heap, cstr, logger, main, memory::SIZE_64KB};
+use vmbase::{configure_heap, cstr, layout::stack_chk_guard, logger, main, memory::SIZE_64KB};
 
 static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
 static mut ZEROED_DATA: [u32; 10] = [0; 10];
diff --git a/vmbase/src/bionic.rs b/vmbase/src/bionic.rs
index 69da521..937105e 100644
--- a/vmbase/src/bionic.rs
+++ b/vmbase/src/bionic.rs
@@ -23,13 +23,9 @@
 
 use crate::console;
 use crate::eprintln;
-use crate::linker;
 
 const EOF: c_int = -1;
 
-/// Reference to __stack_chk_guard.
-pub static STACK_CHK_GUARD: &u64 = unsafe { &linker::__stack_chk_guard };
-
 #[no_mangle]
 extern "C" fn __stack_chk_fail() -> ! {
     panic!("stack guard check failed");
diff --git a/vmbase/src/layout/mod.rs b/vmbase/src/layout/mod.rs
index 21c113a..00d7f9a 100644
--- a/vmbase/src/layout/mod.rs
+++ b/vmbase/src/layout/mod.rs
@@ -17,6 +17,7 @@
 pub mod crosvm;
 
 use crate::console::BASE_ADDRESS;
+use crate::linker::__stack_chk_guard;
 use core::ops::Range;
 use core::ptr::addr_of;
 
@@ -97,3 +98,11 @@
 pub fn binary_end() -> usize {
     linker_addr!(bin_end)
 }
+
+/// Value of __stack_chk_guard.
+pub fn stack_chk_guard() -> u64 {
+    // SAFETY: __stack_chk_guard shouldn't have any mutable aliases unless the stack overflows. If
+    // it does, then there could be undefined behaviour all over the program, but we want to at
+    // least have a chance at catching it.
+    unsafe { addr_of!(__stack_chk_guard).read_volatile() }
+}
diff --git a/vmbase/src/lib.rs b/vmbase/src/lib.rs
index 88bad8b..7e47968 100644
--- a/vmbase/src/lib.rs
+++ b/vmbase/src/lib.rs
@@ -35,8 +35,6 @@
 pub mod util;
 pub mod virtio;
 
-pub use bionic::STACK_CHK_GUARD;
-
 use core::panic::PanicInfo;
 use power::reboot;