Skip to content

Commit 7242fdc

Browse files
authored
Add a rustix::runtime:::random() function. (#953)
This function returns the value of `AT_RANDOM`, for use by origin for initializing the stack-smashing protection canary.
1 parent d906002 commit 7242fdc

File tree

4 files changed

+56
-2
lines changed

4 files changed

+56
-2
lines changed

src/backend/linux_raw/param/auxv.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use linux_raw_sys::general::{
2525
};
2626
#[cfg(feature = "runtime")]
2727
use linux_raw_sys::general::{
28-
AT_EGID, AT_ENTRY, AT_EUID, AT_GID, AT_PHDR, AT_PHENT, AT_PHNUM, AT_SECURE, AT_UID,
28+
AT_EGID, AT_ENTRY, AT_EUID, AT_GID, AT_PHDR, AT_PHENT, AT_PHNUM, AT_RANDOM, AT_SECURE, AT_UID,
2929
};
3030

3131
#[cfg(feature = "param")]
@@ -145,6 +145,19 @@ pub(crate) fn entry() -> usize {
145145
entry
146146
}
147147

148+
#[cfg(feature = "runtime")]
149+
#[inline]
150+
pub(crate) fn random() -> *const [u8; 16] {
151+
let mut random = RANDOM.load(Relaxed);
152+
153+
if random.is_null() {
154+
init_auxv();
155+
random = RANDOM.load(Relaxed);
156+
}
157+
158+
random
159+
}
160+
148161
static PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
149162
static CLOCK_TICKS_PER_SECOND: AtomicUsize = AtomicUsize::new(0);
150163
static HWCAP: AtomicUsize = AtomicUsize::new(0);
@@ -161,6 +174,8 @@ static PHENT: AtomicUsize = AtomicUsize::new(0);
161174
static PHNUM: AtomicUsize = AtomicUsize::new(0);
162175
#[cfg(feature = "runtime")]
163176
static ENTRY: AtomicUsize = AtomicUsize::new(0);
177+
#[cfg(feature = "runtime")]
178+
static RANDOM: AtomicPtr<[u8; 16]> = AtomicPtr::new(null_mut());
164179

165180
#[cfg(feature = "alloc")]
166181
fn pr_get_auxv() -> crate::io::Result<Vec<u8>> {
@@ -296,6 +311,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
296311
let mut gid = None;
297312
#[cfg(feature = "runtime")]
298313
let mut egid = None;
314+
#[cfg(feature = "runtime")]
315+
let mut random = null_mut();
299316

300317
for Elf_auxv_t { a_type, a_val } in aux_iter {
301318
match a_type as _ {
@@ -332,6 +349,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
332349
AT_PHENT => phent = a_val as usize,
333350
#[cfg(feature = "runtime")]
334351
AT_ENTRY => entry = a_val as usize,
352+
#[cfg(feature = "runtime")]
353+
AT_RANDOM => random = check_raw_pointer::<[u8; 16]>(a_val as *mut _)?.as_ptr(),
335354

336355
AT_NULL => break,
337356
_ => (),
@@ -365,6 +384,8 @@ unsafe fn init_from_aux_iter(aux_iter: impl Iterator<Item = Elf_auxv_t>) -> Opti
365384
PHNUM.store(phnum, Relaxed);
366385
#[cfg(feature = "runtime")]
367386
ENTRY.store(entry, Relaxed);
387+
#[cfg(feature = "runtime")]
388+
RANDOM.store(random, Relaxed);
368389

369390
Some(())
370391
}

src/backend/linux_raw/param/init.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use linux_raw_sys::general::{
1818
AT_CLKTCK, AT_EXECFN, AT_HWCAP, AT_HWCAP2, AT_NULL, AT_PAGESZ, AT_SYSINFO_EHDR,
1919
};
2020
#[cfg(feature = "runtime")]
21-
use linux_raw_sys::general::{AT_ENTRY, AT_PHDR, AT_PHENT, AT_PHNUM, AT_SECURE};
21+
use linux_raw_sys::general::{AT_ENTRY, AT_PHDR, AT_PHENT, AT_PHNUM, AT_RANDOM, AT_SECURE};
2222

2323
#[cfg(feature = "param")]
2424
#[inline]
@@ -84,6 +84,12 @@ pub(crate) fn entry() -> usize {
8484
unsafe { ENTRY.load(Ordering::Relaxed) }
8585
}
8686

87+
#[cfg(feature = "runtime")]
88+
#[inline]
89+
pub(crate) fn random() -> *const [u8; 16] {
90+
unsafe { RANDOM.load(Ordering::Relaxed) }
91+
}
92+
8793
static mut PAGE_SIZE: AtomicUsize = AtomicUsize::new(0);
8894
static mut CLOCK_TICKS_PER_SECOND: AtomicUsize = AtomicUsize::new(0);
8995
static mut HWCAP: AtomicUsize = AtomicUsize::new(0);
@@ -103,6 +109,8 @@ static mut PHENT: AtomicUsize = AtomicUsize::new(0);
103109
static mut PHNUM: AtomicUsize = AtomicUsize::new(0);
104110
#[cfg(feature = "runtime")]
105111
static mut ENTRY: AtomicUsize = AtomicUsize::new(0);
112+
#[cfg(feature = "runtime")]
113+
static mut RANDOM: AtomicPtr<[u8; 16]> = AtomicPtr::new(NonNull::dangling().as_ptr());
106114

107115
/// When "use-explicitly-provided-auxv" is enabled, we export a function to be
108116
/// called during initialization, and passed a pointer to the original
@@ -152,6 +160,8 @@ unsafe fn init_from_auxp(mut auxp: *const Elf_auxv_t) {
152160
AT_PHENT => PHENT.store(a_val as usize, Ordering::Relaxed),
153161
#[cfg(feature = "runtime")]
154162
AT_ENTRY => ENTRY.store(a_val as usize, Ordering::Relaxed),
163+
#[cfg(feature = "runtime")]
164+
AT_RANDOM => RANDOM.store(a_val.cast::<[u8; 16]>(), Ordering::Relaxed),
155165

156166
AT_NULL => break,
157167
_ => (),

src/backend/linux_raw/param/libc_auxv.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ const AT_PHNUM: c::c_ulong = 5;
3333
#[cfg(feature = "runtime")]
3434
const AT_ENTRY: c::c_ulong = 9;
3535
const AT_HWCAP: c::c_ulong = 16;
36+
#[cfg(feature = "runtime")]
37+
const AT_RANDOM: c::c_ulong = 25;
3638
const AT_HWCAP2: c::c_ulong = 26;
3739
const AT_SECURE: c::c_ulong = 23;
3840
const AT_EXECFN: c::c_ulong = 31;
@@ -68,6 +70,8 @@ fn test_abi() {
6870
const_assert_eq!(self::AT_PHNUM, ::libc::AT_PHNUM);
6971
#[cfg(feature = "runtime")]
7072
const_assert_eq!(self::AT_ENTRY, ::libc::AT_ENTRY);
73+
#[cfg(feature = "runtime")]
74+
const_assert_eq!(self::AT_RANDOM, ::libc::AT_RANDOM);
7175
}
7276

7377
#[cfg(feature = "param")]
@@ -163,3 +167,9 @@ pub(in super::super) fn sysinfo_ehdr() -> *const Elf_Ehdr {
163167
pub(crate) fn entry() -> usize {
164168
unsafe { getauxval(AT_ENTRY) as usize }
165169
}
170+
171+
#[cfg(feature = "runtime")]
172+
#[inline]
173+
pub(crate) fn random() -> *const [u8; 16] {
174+
unsafe { getauxval(AT_RANDOM) as *const [u8; 16] }
175+
}

src/runtime.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,19 @@ pub fn entry() -> usize {
229229
backend::param::auxv::entry()
230230
}
231231

232+
/// `getauxval(AT_RANDOM)`—Returns the address of 16 pseudorandom bytes.
233+
///
234+
/// These bytes are for use by libc. For anything else, use the `rand` crate.
235+
///
236+
/// # References
237+
/// - [Linux]
238+
///
239+
/// [Linux]: https://man7.org/linux/man-pages/man3/getauxval.3.html
240+
#[inline]
241+
pub fn random() -> *const [u8; 16] {
242+
backend::param::auxv::random()
243+
}
244+
232245
#[cfg(linux_raw)]
233246
pub use backend::runtime::tls::StartupTlsInfo;
234247

0 commit comments

Comments
 (0)