Skip to content

Commit 8ff3803

Browse files
committed
Don't assume that HWCAP2 is present and non-zero.
HWCAP2 gets added on-demand for each architecture as they overflow HWCAP, and for recent users (such as AArch64), we are likely to encounter old kernels that do not provide HWCAP2. A present-but-zero value is also likely in practice, since HWCAP2 naturally contains recent architectural features. `getauxval(AT_HWCAP2)` cannot distinguish between absent and zero values, but to user-space Rust the meaning is the same: the corresponding features are not supported. Change-Id: I3bbd55049d9ed0ae1687f91ec79d383eb8b94479
1 parent b9cf2d7 commit 8ff3803

File tree

1 file changed

+18
-5
lines changed
  • crates/std_detect/src/detect/os/linux

1 file changed

+18
-5
lines changed

crates/std_detect/src/detect/os/linux/auxvec.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
7171
target_arch = "mips64"
7272
))]
7373
{
74+
// Zero could indicate that no features were detected, but it's also used to
75+
// indicate an error. In either case, try the fallback.
7476
if hwcap != 0 {
7577
return Ok(AuxVec { hwcap });
7678
}
@@ -84,7 +86,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
8486
))]
8587
{
8688
if let Ok(hwcap2) = getauxval(AT_HWCAP2) {
87-
if hwcap != 0 && hwcap2 != 0 {
89+
// Zero could indicate that no features were detected, but it's also used to
90+
// indicate an error. In particular, on many platforms AT_HWCAP2 will be
91+
// legitimately zero, since it contains the most recent feature flags. Use the
92+
// fallback only if no features were detected at all.
93+
if hwcap != 0 || hwcap2 != 0 {
8894
return Ok(AuxVec { hwcap, hwcap2 });
8995
}
9096
}
@@ -105,6 +111,8 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
105111
))]
106112
{
107113
let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize };
114+
// Zero could indicate that no features were detected, but it's also used to indicate
115+
// an error. In either case, try the fallback.
108116
if hwcap != 0 {
109117
return Ok(AuxVec { hwcap });
110118
}
@@ -119,7 +127,11 @@ pub(crate) fn auxv() -> Result<AuxVec, ()> {
119127
{
120128
let hwcap = unsafe { libc::getauxval(AT_HWCAP as libc::c_ulong) as usize };
121129
let hwcap2 = unsafe { libc::getauxval(AT_HWCAP2 as libc::c_ulong) as usize };
122-
if hwcap != 0 && hwcap2 != 0 {
130+
// Zero could indicate that no features were detected, but it's also used to indicate
131+
// an error. In particular, on many platforms AT_HWCAP2 will be legitimately zero,
132+
// since it contains the most recent feature flags. Use the fallback only if no
133+
// features were detected at all.
134+
if hwcap != 0 || hwcap2 != 0 {
123135
return Ok(AuxVec { hwcap, hwcap2 });
124136
}
125137
}
@@ -204,17 +216,18 @@ fn auxv_from_buf(buf: &[usize; 64]) -> Result<AuxVec, ()> {
204216
))]
205217
{
206218
let mut hwcap = None;
207-
let mut hwcap2 = None;
219+
// For some platforms, AT_HWCAP2 was added recently, so let it default to zero.
220+
let mut hwcap2 = 0;
208221
for el in buf.chunks(2) {
209222
match el[0] {
210223
AT_NULL => break,
211224
AT_HWCAP => hwcap = Some(el[1]),
212-
AT_HWCAP2 => hwcap2 = Some(el[1]),
225+
AT_HWCAP2 => hwcap2 = el[1],
213226
_ => (),
214227
}
215228
}
216229

217-
if let (Some(hwcap), Some(hwcap2)) = (hwcap, hwcap2) {
230+
if let Some(hwcap) = hwcap {
218231
return Ok(AuxVec { hwcap, hwcap2 });
219232
}
220233
}

0 commit comments

Comments
 (0)