mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-15 12:54:27 +00:00
thread: Simplify sanitizer integration with thread creation
fork() may allocate a new thread in one of two ways: from UMA, or cached in a freed proc that was just allocated from UMA. In either case, KASAN and KMSAN need to initialize some state; in particular they need to initialize the shadow mapping of the new thread's stack. This is done differently between KASAN and KMSAN, which is confusing. This patch improves things a bit: - Add a new thread_recycle() function, which moves all kernel stack handling out of kern_fork.c, since it doesn't really belong there. - Then, thread_alloc_stack() has only one local caller, so just inline it. - Avoid redundant shadow stack initialization: thread_alloc() initializes the KMSAN shadow stack (via kmsan_thread_alloc()) even through vm_thread_new() already did that. - Add kasan_thread_alloc(), for consistency with kmsan_thread_alloc(). No functional change intended. Reviewed by: khng MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D44891
This commit is contained in:
parent
dd03eafacb
commit
800da341bc
|
@ -40,7 +40,6 @@
|
|||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/asan.h>
|
||||
#include <sys/bitstring.h>
|
||||
#include <sys/sysproto.h>
|
||||
#include <sys/eventhandler.h>
|
||||
|
@ -1019,19 +1018,9 @@ fork1(struct thread *td, struct fork_req *fr)
|
|||
}
|
||||
proc_linkup(newproc, td2);
|
||||
} else {
|
||||
kmsan_thread_alloc(td2);
|
||||
if (td2->td_kstack == 0 || td2->td_kstack_pages != pages) {
|
||||
if (td2->td_kstack != 0)
|
||||
vm_thread_dispose(td2);
|
||||
if (!thread_alloc_stack(td2, pages)) {
|
||||
error = ENOMEM;
|
||||
goto fail2;
|
||||
}
|
||||
} else {
|
||||
kasan_mark((void *)td2->td_kstack,
|
||||
ptoa(td2->td_kstack_pages),
|
||||
ptoa(td2->td_kstack_pages), 0);
|
||||
}
|
||||
error = thread_recycle(td2, pages);
|
||||
if (error != 0)
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
if ((flags & RFMEM) == 0) {
|
||||
|
|
|
@ -798,6 +798,7 @@ thread_alloc(int pages)
|
|||
}
|
||||
td->td_tid = tid;
|
||||
bzero(&td->td_sa.args, sizeof(td->td_sa.args));
|
||||
kasan_thread_alloc(td);
|
||||
kmsan_thread_alloc(td);
|
||||
cpu_thread_alloc(td);
|
||||
EVENTHANDLER_DIRECT_INVOKE(thread_ctor, td);
|
||||
|
@ -805,15 +806,18 @@ thread_alloc(int pages)
|
|||
}
|
||||
|
||||
int
|
||||
thread_alloc_stack(struct thread *td, int pages)
|
||||
thread_recycle(struct thread *td, int pages)
|
||||
{
|
||||
|
||||
KASSERT(td->td_kstack == 0,
|
||||
("thread_alloc_stack called on a thread with kstack"));
|
||||
if (!vm_thread_new(td, pages))
|
||||
return (0);
|
||||
cpu_thread_alloc(td);
|
||||
return (1);
|
||||
if (td->td_kstack == 0 || td->td_kstack_pages != pages) {
|
||||
if (td->td_kstack != 0)
|
||||
vm_thread_dispose(td);
|
||||
if (!vm_thread_new(td, pages))
|
||||
return (ENOMEM);
|
||||
cpu_thread_alloc(td);
|
||||
}
|
||||
kasan_thread_alloc(td);
|
||||
kmsan_thread_alloc(td);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: subr_asan.c,v 1.26 2020/09/10 14:10:46 maxv Exp $");
|
|||
#include <sys/systm.h>
|
||||
#include <sys/asan.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stack.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
|
@ -294,6 +295,15 @@ kasan_mark(const void *addr, size_t size, size_t redzsize, uint8_t code)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
kasan_thread_alloc(struct thread *td)
|
||||
{
|
||||
if (td->td_kstack != 0) {
|
||||
kasan_mark((void *)td->td_kstack, ptoa(td->td_kstack_pages),
|
||||
ptoa(td->td_kstack_pages), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define ADDR_CROSSES_SCALE_BOUNDARY(addr, size) \
|
||||
|
|
|
@ -53,14 +53,18 @@
|
|||
#define KASAN_KSTACK_FREED 0xFE
|
||||
#define KASAN_EXEC_ARGS_FREED 0xFF
|
||||
|
||||
struct thread;
|
||||
|
||||
void kasan_init(void);
|
||||
void kasan_init_early(vm_offset_t, size_t);
|
||||
void kasan_shadow_map(vm_offset_t, size_t);
|
||||
void kasan_mark(const void *, size_t, size_t, uint8_t);
|
||||
void kasan_thread_alloc(struct thread *);
|
||||
#else /* KASAN */
|
||||
#define kasan_init()
|
||||
#define kasan_shadow_map(a, s)
|
||||
#define kasan_mark(p, s, l, c)
|
||||
#define kasan_thread_alloc(t)
|
||||
#endif /* !KASAN */
|
||||
|
||||
#endif /* !_SYS_ASAN_H_ */
|
||||
|
|
|
@ -1262,7 +1262,6 @@ void cpu_thread_free(struct thread *);
|
|||
void cpu_thread_swapin(struct thread *);
|
||||
void cpu_thread_swapout(struct thread *);
|
||||
struct thread *thread_alloc(int pages);
|
||||
int thread_alloc_stack(struct thread *, int pages);
|
||||
int thread_check_susp(struct thread *td, bool sleep);
|
||||
void thread_cow_get_proc(struct thread *newtd, struct proc *p);
|
||||
void thread_cow_get(struct thread *newtd, struct thread *td);
|
||||
|
@ -1275,6 +1274,7 @@ void thread_exit(void) __dead2;
|
|||
void thread_free(struct thread *td);
|
||||
void thread_link(struct thread *td, struct proc *p);
|
||||
void thread_reap_barrier(void);
|
||||
int thread_recycle(struct thread *, int pages);
|
||||
int thread_single(struct proc *p, int how);
|
||||
void thread_single_end(struct proc *p, int how);
|
||||
void thread_stash(struct thread *td);
|
||||
|
|
|
@ -543,8 +543,6 @@ vm_thread_new(struct thread *td, int pages)
|
|||
td->td_kstack = ks;
|
||||
td->td_kstack_pages = pages;
|
||||
td->td_kstack_domain = ks_domain;
|
||||
kasan_mark((void *)ks, ptoa(pages), ptoa(pages), 0);
|
||||
kmsan_mark((void *)ks, ptoa(pages), KMSAN_STATE_UNINIT);
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
@ -562,11 +560,12 @@ vm_thread_dispose(struct thread *td)
|
|||
td->td_kstack = 0;
|
||||
td->td_kstack_pages = 0;
|
||||
td->td_kstack_domain = MAXMEMDOM;
|
||||
kasan_mark((void *)ks, 0, ptoa(pages), KASAN_KSTACK_FREED);
|
||||
if (pages == kstack_pages)
|
||||
if (pages == kstack_pages) {
|
||||
kasan_mark((void *)ks, 0, ptoa(pages), KASAN_KSTACK_FREED);
|
||||
uma_zfree(kstack_cache, (void *)ks);
|
||||
else
|
||||
} else {
|
||||
vm_thread_stack_dispose(ks, pages);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue