Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,2 @@
btitest
nobtitest
@@ -0,0 +1,56 @@
# SPDX-License-Identifier: GPL-2.0
TEST_GEN_PROGS := btitest nobtitest
# These tests are built as freestanding binaries since otherwise BTI
# support in ld.so is required which is not currently widespread; when
# it is available it will still be useful to test this separately as the
# cases for statically linked and dynamically lined binaries are
# slightly different.
CFLAGS_NOBTI = -mbranch-protection=none -DBTI=0
CFLAGS_BTI = -mbranch-protection=standard -DBTI=1
CFLAGS_COMMON = -ffreestanding -Wall -Wextra $(CFLAGS)
BTI_CC_COMMAND = $(CC) $(CFLAGS_BTI) $(CFLAGS_COMMON) -c -o $@ $<
NOBTI_CC_COMMAND = $(CC) $(CFLAGS_NOBTI) $(CFLAGS_COMMON) -c -o $@ $<
$(OUTPUT)/%-bti.o: %.c
$(BTI_CC_COMMAND)
$(OUTPUT)/%-bti.o: %.S
$(BTI_CC_COMMAND)
$(OUTPUT)/%-nobti.o: %.c
$(NOBTI_CC_COMMAND)
$(OUTPUT)/%-nobti.o: %.S
$(NOBTI_CC_COMMAND)
BTI_OBJS = \
$(OUTPUT)/test-bti.o \
$(OUTPUT)/signal-bti.o \
$(OUTPUT)/start-bti.o \
$(OUTPUT)/syscall-bti.o \
$(OUTPUT)/system-bti.o \
$(OUTPUT)/teststubs-bti.o \
$(OUTPUT)/trampoline-bti.o
$(OUTPUT)/btitest: $(BTI_OBJS)
$(CC) $(CFLAGS_BTI) $(CFLAGS_COMMON) -nostdlib -static -o $@ $^
NOBTI_OBJS = \
$(OUTPUT)/test-nobti.o \
$(OUTPUT)/signal-nobti.o \
$(OUTPUT)/start-nobti.o \
$(OUTPUT)/syscall-nobti.o \
$(OUTPUT)/system-nobti.o \
$(OUTPUT)/teststubs-nobti.o \
$(OUTPUT)/trampoline-nobti.o
$(OUTPUT)/nobtitest: $(NOBTI_OBJS)
$(CC) $(CFLAGS_BTI) $(CFLAGS_COMMON) -nostdlib -static -o $@ $^
# Including KSFT lib.mk here will also mangle the TEST_GEN_PROGS list
# to account for any OUTPUT target-dirs optionally provided by
# the toplevel makefile
include ../../lib.mk
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#ifndef ASSEMBLER_H
#define ASSEMBLER_H
#define NT_GNU_PROPERTY_TYPE_0 5
#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000
/* Bits for GNU_PROPERTY_AARCH64_FEATURE_1_BTI */
#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1U << 0)
#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1U << 1)
.macro startfn name:req
.globl \name
\name:
.macro endfn
.size \name, . - \name
.type \name, @function
.purgem endfn
.endm
.endm
.macro emit_aarch64_feature_1_and
.pushsection .note.gnu.property, "a"
.align 3
.long 2f - 1f
.long 6f - 3f
.long NT_GNU_PROPERTY_TYPE_0
1: .string "GNU"
2:
.align 3
3: .long GNU_PROPERTY_AARCH64_FEATURE_1_AND
.long 5f - 4f
4:
#if BTI
.long GNU_PROPERTY_AARCH64_FEATURE_1_PAC | \
GNU_PROPERTY_AARCH64_FEATURE_1_BTI
#else
.long 0
#endif
5:
.align 3
6:
.popsection
.endm
.macro paciasp
hint 0x19
.endm
.macro autiasp
hint 0x1d
.endm
.macro __bti_
hint 0x20
.endm
.macro __bti_c
hint 0x22
.endm
.macro __bti_j
hint 0x24
.endm
.macro __bti_jc
hint 0x26
.endm
.macro bti what=
__bti_\what
.endm
#endif /* ! ASSEMBLER_H */
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#ifndef BTITEST_H
#define BTITEST_H
/* Trampolines for calling the test stubs: */
void call_using_br_x0(void (*)(void));
void call_using_br_x16(void (*)(void));
void call_using_blr(void (*)(void));
/* Test stubs: */
void nohint_func(void);
void bti_none_func(void);
void bti_c_func(void);
void bti_j_func(void);
void bti_jc_func(void);
void paciasp_func(void);
#endif /* !BTITEST_H */
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "system.h"
#include "signal.h"
int sigemptyset(sigset_t *s)
{
unsigned int i;
for (i = 0; i < _NSIG_WORDS; ++i)
s->sig[i] = 0;
return 0;
}
int sigaddset(sigset_t *s, int n)
{
if (n < 1 || n > _NSIG)
return -EINVAL;
s->sig[(n - 1) / _NSIG_BPW] |= 1UL << (n - 1) % _NSIG_BPW;
return 0;
}
int sigaction(int n, struct sigaction *sa, const struct sigaction *old)
{
return syscall(__NR_rt_sigaction, n, sa, old, sizeof(sa->sa_mask));
}
int sigprocmask(int how, const sigset_t *mask, sigset_t *old)
{
return syscall(__NR_rt_sigprocmask, how, mask, old, sizeof(*mask));
}
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#ifndef SIGNAL_H
#define SIGNAL_H
#include <linux/signal.h>
#include "system.h"
typedef __sighandler_t sighandler_t;
int sigemptyset(sigset_t *s);
int sigaddset(sigset_t *s, int n);
int sigaction(int n, struct sigaction *sa, const struct sigaction *old);
int sigprocmask(int how, const sigset_t *mask, sigset_t *old);
#endif /* ! SIGNAL_H */
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "assembler.h"
startfn _start
mov x0, sp
b start
endfn
emit_aarch64_feature_1_and
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "assembler.h"
startfn syscall
bti c
mov w8, w0
mov x0, x1
mov x1, x2
mov x2, x3
mov x3, x4
mov x4, x5
mov x5, x6
mov x6, x7
svc #0
ret
endfn
emit_aarch64_feature_1_and
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "system.h"
#include <asm/unistd.h>
void __noreturn exit(int n)
{
syscall(__NR_exit, n);
unreachable();
}
ssize_t write(int fd, const void *buf, size_t size)
{
return syscall(__NR_write, fd, buf, size);
}
@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#ifndef SYSTEM_H
#define SYSTEM_H
#include <linux/types.h>
#include <linux/stddef.h>
typedef __kernel_size_t size_t;
typedef __kernel_ssize_t ssize_t;
#include <linux/errno.h>
#include <linux/compiler.h>
#include <asm/hwcap.h>
#include <asm/ptrace.h>
#include <asm/unistd.h>
long syscall(int nr, ...);
void __noreturn exit(int n);
ssize_t write(int fd, const void *buf, size_t size);
#endif /* ! SYSTEM_H */
@@ -0,0 +1,229 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2019,2021 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "system.h"
#include <stdbool.h>
#include <stddef.h>
#include <linux/errno.h>
#include <linux/auxvec.h>
#include <linux/signal.h>
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
typedef struct ucontext ucontext_t;
#include "btitest.h"
#include "signal.h"
#define EXPECTED_TESTS 18
static volatile unsigned int test_num = 1;
static unsigned int test_passed;
static unsigned int test_failed;
static unsigned int test_skipped;
static void fdputs(int fd, const char *str)
{
size_t len = 0;
const char *p = str;
while (*p++)
++len;
write(fd, str, len);
}
static void putstr(const char *str)
{
fdputs(1, str);
}
static void putnum(unsigned int num)
{
char c;
if (num / 10)
putnum(num / 10);
c = '0' + (num % 10);
write(1, &c, 1);
}
#define puttestname(test_name, trampoline_name) do { \
putstr(test_name); \
putstr("/"); \
putstr(trampoline_name); \
} while (0)
void print_summary(void)
{
putstr("# Totals: pass:");
putnum(test_passed);
putstr(" fail:");
putnum(test_failed);
putstr(" xfail:0 xpass:0 skip:");
putnum(test_skipped);
putstr(" error:0\n");
}
static const char *volatile current_test_name;
static const char *volatile current_trampoline_name;
static volatile int sigill_expected, sigill_received;
static void handler(int n, siginfo_t *si __always_unused,
void *uc_ __always_unused)
{
ucontext_t *uc = uc_;
putstr("# \t[SIGILL in ");
puttestname(current_test_name, current_trampoline_name);
putstr(", BTYPE=");
write(1, &"00011011"[((uc->uc_mcontext.pstate & PSR_BTYPE_MASK)
>> PSR_BTYPE_SHIFT) * 2], 2);
if (!sigill_expected) {
putstr("]\n");
putstr("not ok ");
putnum(test_num);
putstr(" ");
puttestname(current_test_name, current_trampoline_name);
putstr("(unexpected SIGILL)\n");
print_summary();
exit(128 + n);
}
putstr(" (expected)]\n");
sigill_received = 1;
/* zap BTYPE so that resuming the faulting code will work */
uc->uc_mcontext.pstate &= ~PSR_BTYPE_MASK;
}
/* Does the system have BTI? */
static bool have_bti;
static void __do_test(void (*trampoline)(void (*)(void)),
void (*fn)(void),
const char *trampoline_name,
const char *name,
int expect_sigill)
{
/*
* Branch Target exceptions should only happen for BTI
* binaries running on a system with BTI:
*/
if (!BTI || !have_bti)
expect_sigill = 0;
sigill_expected = expect_sigill;
sigill_received = 0;
current_test_name = name;
current_trampoline_name = trampoline_name;
trampoline(fn);
if (expect_sigill && !sigill_received) {
putstr("not ok ");
test_failed++;
} else {
putstr("ok ");
test_passed++;
}
putnum(test_num++);
putstr(" ");
puttestname(name, trampoline_name);
putstr("\n");
}
#define do_test(expect_sigill_br_x0, \
expect_sigill_br_x16, \
expect_sigill_blr, \
name) \
do { \
__do_test(call_using_br_x0, name, "call_using_br_x0", #name, \
expect_sigill_br_x0); \
__do_test(call_using_br_x16, name, "call_using_br_x16", #name, \
expect_sigill_br_x16); \
__do_test(call_using_blr, name, "call_using_blr", #name, \
expect_sigill_blr); \
} while (0)
void start(int *argcp)
{
struct sigaction sa;
void *const *p;
const struct auxv_entry {
unsigned long type;
unsigned long val;
} *auxv;
unsigned long hwcap = 0, hwcap2 = 0;
putstr("TAP version 13\n");
putstr("1..");
putnum(EXPECTED_TESTS);
putstr("\n");
/* Gross hack for finding AT_HWCAP2 from the initial process stack: */
p = (void *const *)argcp + 1 + *argcp + 1; /* start of environment */
/* step over environment */
while (*p++)
;
for (auxv = (const struct auxv_entry *)p; auxv->type != AT_NULL; ++auxv) {
switch (auxv->type) {
case AT_HWCAP:
hwcap = auxv->val;
break;
case AT_HWCAP2:
hwcap2 = auxv->val;
break;
default:
break;
}
}
if (hwcap & HWCAP_PACA)
putstr("# HWCAP_PACA present\n");
else
putstr("# HWCAP_PACA not present\n");
if (hwcap2 & HWCAP2_BTI) {
putstr("# HWCAP2_BTI present\n");
if (!(hwcap & HWCAP_PACA))
putstr("# Bad hardware? Expect problems.\n");
have_bti = true;
} else {
putstr("# HWCAP2_BTI not present\n");
have_bti = false;
}
putstr("# Test binary");
if (!BTI)
putstr(" not");
putstr(" built for BTI\n");
sa.sa_handler = (sighandler_t)(void *)handler;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sigaction(SIGILL, &sa, NULL);
sigaddset(&sa.sa_mask, SIGILL);
sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL);
do_test(1, 1, 1, nohint_func);
do_test(1, 1, 1, bti_none_func);
do_test(1, 0, 0, bti_c_func);
do_test(0, 0, 1, bti_j_func);
do_test(0, 0, 0, bti_jc_func);
do_test(1, 0, 0, paciasp_func);
print_summary();
if (test_num - 1 != EXPECTED_TESTS)
putstr("# WARNING - EXPECTED TEST COUNT WRONG\n");
if (test_failed)
exit(1);
else
exit(0);
}
@@ -0,0 +1,39 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "assembler.h"
startfn bti_none_func
bti
ret
endfn
startfn bti_c_func
bti c
ret
endfn
startfn bti_j_func
bti j
ret
endfn
startfn bti_jc_func
bti jc
ret
endfn
startfn paciasp_func
paciasp
autiasp
ret
endfn
startfn nohint_func
ret
endfn
emit_aarch64_feature_1_and
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2019 Arm Limited
* Original author: Dave Martin <Dave.Martin@arm.com>
*/
#include "assembler.h"
startfn call_using_br_x0
bti c
br x0
endfn
startfn call_using_br_x16
bti c
mov x16, x0
br x16
endfn
startfn call_using_blr
paciasp
stp x29, x30, [sp, #-16]!
blr x0
ldp x29, x30, [sp], #16
autiasp
ret
endfn
emit_aarch64_feature_1_and