diff options
author | kib <kib@FreeBSD.org> | 2007-11-05 11:36:16 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-11-05 11:36:16 +0000 |
commit | 9ae733819b7cdf0eef51ba1b18d39feb136a9dbf (patch) | |
tree | cccec36134d2cab5ce1eabb67dcaab5981e9beb0 /sys/kern/kern_proc.c | |
parent | f3f033b9b90ea07350fbe7483af3d9636cb31d1d (diff) | |
download | FreeBSD-src-9ae733819b7cdf0eef51ba1b18d39feb136a9dbf.zip FreeBSD-src-9ae733819b7cdf0eef51ba1b18d39feb136a9dbf.tar.gz |
Fix for the panic("vm_thread_new: kstack allocation failed") and
silent NULL pointer dereference in the i386 and sparc64 pmap_pinit()
when the kmem_alloc_nofault() failed to allocate address space. Both
functions now return error instead of panicing or dereferencing NULL.
As consequence, vmspace_exec() and vmspace_unshare() returns the errno
int. struct vmspace arg was added to vm_forkproc() to avoid dealing
with failed allocation when most of the fork1() job is already done.
The kernel stack for the thread is now set up in the thread_alloc(),
that itself may return NULL. Also, allocation of the first process
thread is performed in the fork1() to properly deal with stack
allocation failure. proc_linkup() is separated into proc_linkup()
called from fork1(), and proc_linkup0(), that is used to set up the
kernel process (was known as swapper).
In collaboration with: Peter Holm
Reviewed by: jhb
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 28 |
1 files changed, 13 insertions, 15 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index f75112f..71e2b10 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -145,20 +145,21 @@ proc_dtor(void *mem, int size, void *arg) /* INVARIANTS checks go here */ p = (struct proc *)mem; td = FIRST_THREAD_IN_PROC(p); + if (td != NULL) { #ifdef INVARIANTS - KASSERT((p->p_numthreads == 1), - ("bad number of threads in exiting process")); - KASSERT((td != NULL), ("proc_dtor: bad thread pointer")); - KASSERT(STAILQ_EMPTY(&p->p_ktr), ("proc_dtor: non-empty p_ktr")); + KASSERT((p->p_numthreads == 1), + ("bad number of threads in exiting process")); + KASSERT(STAILQ_EMPTY(&p->p_ktr), ("proc_dtor: non-empty p_ktr")); #endif - /* Dispose of an alternate kstack, if it exists. - * XXX What if there are more than one thread in the proc? - * The first thread in the proc is special and not - * freed, so you gotta do this here. - */ - if (((p->p_flag & P_KTHREAD) != 0) && (td->td_altkstack != 0)) - vm_thread_dispose_altkstack(td); + /* Dispose of an alternate kstack, if it exists. + * XXX What if there are more than one thread in the proc? + * The first thread in the proc is special and not + * freed, so you gotta do this here. + */ + if (((p->p_flag & P_KTHREAD) != 0) && (td->td_altkstack != 0)) + vm_thread_dispose_altkstack(td); + } if (p->p_ksi != NULL) KASSERT(! KSI_ONQ(p->p_ksi), ("SIGCHLD queue")); } @@ -170,17 +171,14 @@ static int proc_init(void *mem, int size, int flags) { struct proc *p; - struct thread *td; p = (struct proc *)mem; p->p_sched = (struct p_sched *)&p[1]; - td = thread_alloc(); bzero(&p->p_mtx, sizeof(struct mtx)); mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK); mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_RECURSE); + TAILQ_INIT(&p->p_threads); /* all threads in proc */ p->p_stats = pstats_alloc(); - proc_linkup(p, td); - sched_newproc(p, td); return (0); } |