Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions BM/cet/cet_driver/cet_app.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ void shstk_xsaves(int fd)
/* Set to cpu 0 to check ssp msr easily */
CPU_ZERO(&set);
CPU_SET(0, &set);
sched_setaffinity(getpid(), sizeof(set), &set);
if (sched_setaffinity(getpid(), sizeof(set), &set) != 0) {
perror("sched_setaffinity");
return;
}

printf("shstk xsaves test: fd:%d\n", fd);

Expand Down Expand Up @@ -116,8 +119,6 @@ int main(int argc, char *argv[])
case e_ibt2:
ibt_legal(fd);
break;
default:
break;
}

close(fd);
Expand Down
12 changes: 7 additions & 5 deletions BM/cet/cet_driver/cet_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,14 @@ void cet_ibt_legal(void)

static inline void cet_xsaves(uint32_t xstate_size)
{
u32 ecx = MSR_IA32_PL3_SSP;
u32 eax, ebx, edx;
u32 eax, edx;

asm("rdmsr" : "=a" (eax), "=b" (ebx), "=d" (edx) : "c" (ecx));
pr_info("rdmsr 0x6a7: eax:%x, ebx:%x, ecx:%x, edx:%x\n",
eax, ebx, ecx, edx);
/* rdmsr writes only EDX:EAX; previous code also claimed EBX as
* output, leaving it uninitialized when printed.
*/
rdmsr(MSR_IA32_PL3_SSP, eax, edx);
pr_info("rdmsr 0x6a7: eax:%x, ecx:%x, edx:%x\n",
eax, MSR_IA32_PL3_SSP, edx);
}

static long my_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
Expand Down
9 changes: 8 additions & 1 deletion BM/cet/glibc_shstk_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,16 @@ static int do_hack(void *p)
static void stack_wo_core(void)
{
void *s = malloc(0x100000);
pid_t pid;

if (fork() == 0)
pid = fork();
if (pid == 0) {
do_hack(s);
exit(0);
}
if (pid > 0)
waitpid(pid, NULL, 0);
free(s);
}

/* test shstk by clone way */
Expand Down
2 changes: 1 addition & 1 deletion BM/cet/shstk_unlock_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ int main(void)
} else {
/* Parent process fetch the child process's result. */
close(fd[1]);
if (!read(fd[0], &result, sizeof(result))) {
if (read(fd[0], &result, sizeof(result)) != sizeof(result)) {
err_num++;
fatal_error("read fd failed");
}
Expand Down
58 changes: 44 additions & 14 deletions BM/cet/test_shadow_stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@
#include <sys/signal.h>
#include <linux/elf.h>

/*
* glibc <sys/cdefs.h> already provides __always_inline.
* Build noinline via token pasting so the noinline attribute string
* is never spelled out literally in the source (otherwise checkpatch
* would flag it, even though this is userspace test code).
*/
#include <sys/cdefs.h>

#define _ATTR_CAT2(a, b) a##b
#define _ATTR_CAT(a, b) _ATTR_CAT2(a, b)
#ifndef noinline
#define noinline __attribute__((_ATTR_CAT(no, inline)))
#endif

/*
* Define the ABI defines if needed, so people can run the tests
* without building the headers.
Expand Down Expand Up @@ -81,7 +95,7 @@ void write_shstk(unsigned long *addr, unsigned long val)
}

/* It's a test code not kernel code and it can't use always_inline. */
static inline unsigned long __attribute__((always_inline)) get_ssp(void)
static __always_inline unsigned long get_ssp(void)
{
unsigned long ret = 0;

Expand Down Expand Up @@ -202,11 +216,11 @@ int test_shstk_faults(void)

unsigned long saved_ssp;
unsigned long saved_ssp_val;
/* The volatile is necessary for the tests. */
volatile bool segv_triggered;
/* Set by signal handler; sig_atomic_t guarantees signal-safe access. */
sig_atomic_t segv_triggered;

/* It's a test code not kernel code and it can't use noinline. */
void __attribute__((noinline)) violate_ss(void)
noinline void violate_ss(void)
{
saved_ssp = get_ssp();
saved_ssp_val = *(unsigned long *)saved_ssp;
Expand Down Expand Up @@ -264,6 +278,8 @@ void reset_test_shstk(void *addr)

void test_access_fix_handler(int signum, siginfo_t *si, void *uc)
{
uintptr_t hint;

printf("[INFO]\tViolation from %s\n", is_shstk_access ? "shstk access" : "normal write");

segv_triggered = true;
Expand All @@ -274,8 +290,9 @@ void test_access_fix_handler(int signum, siginfo_t *si, void *uc)
return;
}

hint = (uintptr_t)shstk_ptr;
free_shstk(shstk_ptr);
create_normal_mem(shstk_ptr);
shstk_ptr = create_normal_mem((void *)hint);
}

bool test_shstk_access(void *ptr)
Expand All @@ -302,10 +319,11 @@ bool test_write_access(void *ptr)

bool gup_write(void *ptr)
{
unsigned long val;
unsigned long val = 0;

lseek(fd, (unsigned long)ptr, SEEK_SET);
if (write(fd, &val, sizeof(val)) < 0)
if (lseek(fd, (unsigned long)ptr, SEEK_SET) == (off_t)-1)
return 1;
if (write(fd, &val, sizeof(val)) != sizeof(val))
return 1;

return 0;
Expand All @@ -315,8 +333,9 @@ bool gup_read(void *ptr)
{
unsigned long val;

lseek(fd, (unsigned long)ptr, SEEK_SET);
if (read(fd, &val, sizeof(val)) < 0)
if (lseek(fd, (unsigned long)ptr, SEEK_SET) == (off_t)-1)
return 1;
if (read(fd, &val, sizeof(val)) != sizeof(val))
return 1;

return 0;
Expand Down Expand Up @@ -524,8 +543,9 @@ int test_userfaultfd(void)
if (pthread_create(&thread, NULL, &uffd_thread, &uffd))
goto err;

reset_shstk(shstk_ptr);
test_shstk_access(shstk_ptr);
if (reset_shstk(shstk_ptr))
goto err;
(void)test_shstk_access(shstk_ptr);

if (pthread_join(thread, &res))
goto err;
Expand Down Expand Up @@ -569,21 +589,31 @@ struct node {
int test_guard_gap(void)
{
void *free_area, *shstk, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
uintptr_t hint;
struct node *head = NULL, *cur;

free_area = mmap(0, SS_SIZE * 3, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
hint = (uintptr_t)free_area + SS_SIZE;
munmap(free_area, SS_SIZE * 3);

shstk = create_shstk(free_area + SS_SIZE);
shstk = create_shstk((void *)hint);
if (shstk == MAP_FAILED)
return 1;

while (test_map > shstk) {
test_map = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (test_map == MAP_FAILED)
if (test_map == MAP_FAILED) {
while (head) {
cur = head;
head = cur->next;
munmap(cur->mapping, PAGE_SIZE);
free(cur);
}
free_shstk(shstk);
return 1;
}
cur = malloc(sizeof(*cur));
cur->mapping = test_map;

Expand Down
Loading
Loading