#define PAC_COLLISION_ATTEMPTS 1000 /* *ThekernelsetsTBIDbydefault.Sobits55andaboveshouldremain *untouchednomatterwhat. *TheVAspacesizeis48bits.Biggerisopt-in.
*/ #define PAC_MASK (~0xff80ffffffffffff) #define ARBITRARY_VALUE (0x1234) #define ASSERT_PAUTH_ENABLED() \ do { \ unsignedlong hwcaps = getauxval(AT_HWCAP); \ /* data key instructions are not in NOP space. This prevents a SIGILL */ \ if (!(hwcaps & HWCAP_PACA)) \
SKIP(return, "PAUTH not enabled"); \
} while (0) #define ASSERT_GENERIC_PAUTH_ENABLED() \ do { \ unsignedlong hwcaps = getauxval(AT_HWCAP); \ /* generic key instructions are not in NOP space. This prevents a SIGILL */ \ if (!(hwcaps & HWCAP_PACG)) \
SKIP(return, "Generic PAUTH not enabled"); \
} while (0)
int n_same(struct signatures *old, struct signatures *new, int nkeys)
{ int res = 0;
res += old->keyia == new->keyia;
res += old->keyib == new->keyib;
res += old->keyda == new->keyda;
res += old->keydb == new->keydb; if (nkeys == NKEYS)
res += old->keyg == new->keyg;
return res;
}
int n_same_single_set(struct signatures *sign, int nkeys)
{
size_t vals[nkeys]; int same = 0;
for (int i = 0; i < nkeys - 1; i++) { for (int j = i + 1; j < nkeys; j++) { if (vals[i] == vals[j])
same += 1;
}
} return same;
}
int exec_sign_all(struct signatures *signed_vals, size_t val)
{ int new_stdin[2]; int new_stdout[2]; int status; int i;
ssize_t ret;
pid_t pid;
cpu_set_t mask;
ret = pipe(new_stdin); if (ret == -1) {
perror("pipe returned error"); return -1;
}
ret = pipe(new_stdout); if (ret == -1) {
perror("pipe returned error"); return -1;
}
for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++)
keyg |= keyg_sign(i) & PAC_MASK;
ASSERT_NE(0, keyg) TH_LOG("keyg instructions did nothing");
}
TEST(single_thread_different_keys)
{ int same = 10; int nkeys = NKEYS; int tmp; struct signatures signed_vals; unsignedlong hwcaps = getauxval(AT_HWCAP);
/* generic and data key instructions are not in NOP space. This prevents a SIGILL */
ASSERT_PAUTH_ENABLED(); if (!(hwcaps & HWCAP_PACG)) {
TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks");
nkeys = NKEYS - 1;
}
/* *InLinuxthePACfieldcanbeupto7bitswide.Evenifkeysare *different,thereisabout5%chanceforPACstocollidewith *differentaddresses.Thischancerapidlyincreaseswithfewerbits *allocatedforthePAC(e.g.wideraddress).Acomparisonofthekeys *directlywillbemorereliable. *Allsignedvaluesneedtobedifferentatleastonceoutofn *attemptstobecertainthatthekeysaredifferent
*/ for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) { if (nkeys == NKEYS)
sign_all(&signed_vals, i); else
sign_specific(&signed_vals, i);
tmp = n_same_single_set(&signed_vals, nkeys); if (tmp < same)
same = tmp;
}
ASSERT_EQ(0, same) TH_LOG("%d keys clashed every time", same);
}
/* *fork()doesnotchangekeys.Onlyexec()doessocallaworkerprogram. *Itsonlyjobistosignavalueandreportbacktheresutls
*/
TEST(exec_changed_keys)
{ struct signatures new_keys; struct signatures old_keys; int ret; int same = 10; int nkeys = NKEYS; unsignedlong hwcaps = getauxval(AT_HWCAP);
/* generic and data key instructions are not in NOP space. This prevents a SIGILL */
ASSERT_PAUTH_ENABLED(); if (!(hwcaps & HWCAP_PACG)) {
TH_LOG("WARNING: Generic PAUTH not enabled. Skipping generic key checks");
nkeys = NKEYS - 1;
}
for (int i = 0; i < PAC_COLLISION_ATTEMPTS; i++) {
ret = exec_sign_all(&new_keys, i);
ASSERT_EQ(0, ret) TH_LOG("failed to run worker");
if (nkeys == NKEYS)
sign_all(&old_keys, i); else
sign_specific(&old_keys, i);
ret = n_same(&old_keys, &new_keys, nkeys); if (ret < same)
same = ret;
}
ASSERT_EQ(0, same) TH_LOG("exec() did not change %d keys", same);
}
/* will context switch with a process with different keys at least once */
ret = exec_sign_all(&trash, ARBITRARY_VALUE);
ASSERT_EQ(0, ret) TH_LOG("failed to run worker");
sign_specific(&after, ARBITRARY_VALUE);
ASSERT_EQ(before.keyia, after.keyia) TH_LOG("keyia changed after context switching");
ASSERT_EQ(before.keyib, after.keyib) TH_LOG("keyib changed after context switching");
ASSERT_EQ(before.keyda, after.keyda) TH_LOG("keyda changed after context switching");
ASSERT_EQ(before.keydb, after.keydb) TH_LOG("keydb changed after context switching");
}
/* will context switch with a process with different keys at least once */
ret = exec_sign_all(&trash, ARBITRARY_VALUE);
ASSERT_EQ(0, ret) TH_LOG("failed to run worker");
after = keyg_sign(ARBITRARY_VALUE);
ASSERT_EQ(before, after) TH_LOG("keyg changed after context switching");
}
TEST_HARNESS_MAIN
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-10-12)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.