Module Name: src Committed By: ad Date: Sat Jan 25 15:41:52 UTC 2020
Modified Files: src/lib/libpthread: pthread.c src/sys/compat/netbsd32: netbsd32_lwp.c src/sys/kern: sys_lwp.c src/sys/sys: lwp.h Log Message: - Fix a race between the kernel and libpthread, where a new thread can start life without its self->pt_lid being filled in. - Fix an error path in _lwp_create(). If the new LID can't be copied out, then get rid of the new LWP (i.e. either succeed or fail, not both). - Mark l_dopreempt and l_nopreempt volatile in struct lwp. To generate a diff of this commit: cvs rdiff -u -r1.154 -r1.155 src/lib/libpthread/pthread.c cvs rdiff -u -r1.19 -r1.20 src/sys/compat/netbsd32/netbsd32_lwp.c cvs rdiff -u -r1.71 -r1.72 src/sys/kern/sys_lwp.c cvs rdiff -u -r1.197 -r1.198 src/sys/sys/lwp.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/lib/libpthread/pthread.c diff -u src/lib/libpthread/pthread.c:1.154 src/lib/libpthread/pthread.c:1.155 --- src/lib/libpthread/pthread.c:1.154 Mon Jan 13 18:22:56 2020 +++ src/lib/libpthread/pthread.c Sat Jan 25 15:41:52 2020 @@ -1,7 +1,8 @@ -/* $NetBSD: pthread.c,v 1.154 2020/01/13 18:22:56 ad Exp $ */ +/* $NetBSD: pthread.c,v 1.155 2020/01/25 15:41:52 ad Exp $ */ /*- - * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc. + * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008, 2020 + * The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -30,7 +31,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: pthread.c,v 1.154 2020/01/13 18:22:56 ad Exp $"); +__RCSID("$NetBSD: pthread.c,v 1.155 2020/01/25 15:41:52 ad Exp $"); #define __EXPOSE_STACK 1 @@ -571,10 +572,6 @@ pthread__create_tramp(void *cookie) * thrash. May help for SMT processors. XXX We should not * be allocating stacks on fixed 2MB boundaries. Needs a * thread register or decent thread local storage. - * - * Note that we may race with the kernel in _lwp_create(), - * and so pt_lid can be unset at this point, but we don't - * care. */ (void)alloca(((unsigned)self->pt_lid & 7) << 8); Index: src/sys/compat/netbsd32/netbsd32_lwp.c diff -u src/sys/compat/netbsd32/netbsd32_lwp.c:1.19 src/sys/compat/netbsd32/netbsd32_lwp.c:1.20 --- src/sys/compat/netbsd32/netbsd32_lwp.c:1.19 Fri Apr 21 15:10:34 2017 +++ src/sys/compat/netbsd32/netbsd32_lwp.c Sat Jan 25 15:41:52 2020 @@ -1,7 +1,7 @@ -/* $NetBSD: netbsd32_lwp.c,v 1.19 2017/04/21 15:10:34 christos Exp $ */ +/* $NetBSD: netbsd32_lwp.c,v 1.20 2020/01/25 15:41:52 ad Exp $ */ /* - * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation. + * Copyright (c) 2005, 2006, 2007, 2020 The NetBSD Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_lwp.c,v 1.19 2017/04/21 15:10:34 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_lwp.c,v 1.20 2020/01/25 15:41:52 ad Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -55,7 +55,7 @@ netbsd32__lwp_create(struct lwp *l, cons } */ struct proc *p = l->l_proc; ucontext32_t *newuc = NULL; - lwpid_t lid; + lwp_t *l2; int error; KASSERT(p->p_emul->e_ucsize == sizeof(*newuc)); @@ -77,18 +77,20 @@ netbsd32__lwp_create(struct lwp *l, cons const sigset_t *sigmask = newuc->uc_flags & _UC_SIGMASK ? &newuc->uc_sigmask : &l->l_sigmask; - error = do_lwp_create(l, newuc, SCARG(uap, flags), &lid, sigmask, + error = do_lwp_create(l, newuc, SCARG(uap, flags), &l2, sigmask, &SS_INIT); - if (error) + if (error != 0) goto fail; - /* - * do not free ucontext in case of an error here, - * the lwp will actually run and access it - */ - return copyout(&lid, SCARG_P32(uap, new_lwp), sizeof(lid)); + error = copyout(&l2->l_lid, SCARG_P32(uap, new_lwp), + sizeof(l2->l_lid)); + if (error != 0) + lwp_exit(l2); + else + lwp_start(l2, SCARG(uap, flags)); + return error; -fail: + fail: kmem_free(newuc, sizeof(ucontext_t)); return error; } Index: src/sys/kern/sys_lwp.c diff -u src/sys/kern/sys_lwp.c:1.71 src/sys/kern/sys_lwp.c:1.72 --- src/sys/kern/sys_lwp.c:1.71 Sat Nov 23 19:42:52 2019 +++ src/sys/kern/sys_lwp.c Sat Jan 25 15:41:52 2020 @@ -1,7 +1,7 @@ -/* $NetBSD: sys_lwp.c,v 1.71 2019/11/23 19:42:52 ad Exp $ */ +/* $NetBSD: sys_lwp.c,v 1.72 2020/01/25 15:41:52 ad Exp $ */ /*- - * Copyright (c) 2001, 2006, 2007, 2008, 2019 The NetBSD Foundation, Inc. + * Copyright (c) 2001, 2006, 2007, 2008, 2019, 2020 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.71 2019/11/23 19:42:52 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.72 2020/01/25 15:41:52 ad Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -97,11 +97,10 @@ mi_startlwp(void *arg) } int -do_lwp_create(lwp_t *l, void *arg, u_long flags, lwpid_t *new_lwp, +do_lwp_create(lwp_t *l, void *arg, u_long flags, lwp_t **l2, const sigset_t *sigmask, const stack_t *sigstk) { struct proc *p = l->l_proc; - struct lwp *l2; vaddr_t uaddr; int error; @@ -112,14 +111,12 @@ do_lwp_create(lwp_t *l, void *arg, u_lon return ENOMEM; error = lwp_create(l, p, uaddr, flags & LWP_DETACHED, NULL, 0, - mi_startlwp, arg, &l2, l->l_class, sigmask, &lwp_ss_init); + mi_startlwp, arg, l2, l->l_class, sigmask, &lwp_ss_init); if (__predict_false(error)) { uvm_uarea_free(uaddr); return error; } - *new_lwp = l2->l_lid; - lwp_start(l2, flags); return 0; } @@ -134,7 +131,7 @@ sys__lwp_create(struct lwp *l, const str } */ struct proc *p = l->l_proc; ucontext_t *newuc; - lwpid_t lid; + lwp_t *l2; int error; newuc = kmem_alloc(sizeof(ucontext_t), KM_SLEEP); @@ -153,18 +150,19 @@ sys__lwp_create(struct lwp *l, const str const sigset_t *sigmask = newuc->uc_flags & _UC_SIGMASK ? &newuc->uc_sigmask : &l->l_sigmask; - error = do_lwp_create(l, newuc, SCARG(uap, flags), &lid, sigmask, + error = do_lwp_create(l, newuc, SCARG(uap, flags), &l2, sigmask, &SS_INIT); if (error) goto fail; - /* - * do not free ucontext in case of an error here, - * the lwp will actually run and access it - */ - return copyout(&lid, SCARG(uap, new_lwp), sizeof(lid)); + error = copyout(&l2->l_lid, SCARG(uap, new_lwp), sizeof(l2->l_lid)); + if (error != 0) + lwp_exit(l2); + else + lwp_start(l2, SCARG(uap, flags)); + return error; -fail: + fail: kmem_free(newuc, sizeof(ucontext_t)); return error; } Index: src/sys/sys/lwp.h diff -u src/sys/sys/lwp.h:1.197 src/sys/sys/lwp.h:1.198 --- src/sys/sys/lwp.h:1.197 Tue Jan 21 20:31:57 2020 +++ src/sys/sys/lwp.h Sat Jan 25 15:41:52 2020 @@ -1,7 +1,7 @@ -/* $NetBSD: lwp.h,v 1.197 2020/01/21 20:31:57 ad Exp $ */ +/* $NetBSD: lwp.h,v 1.198 2020/01/25 15:41:52 ad Exp $ */ /* - * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010, 2019 + * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010, 2019, 2020 * The NetBSD Foundation, Inc. * All rights reserved. * @@ -186,8 +186,8 @@ struct lwp { u_short l_exlocks; /* !: lockdebug: excl. locks held */ u_short l_psrefs; /* !: count of psref held */ u_short l_blcnt; /* !: count of kernel_lock held */ - int l_nopreempt; /* !: don't preempt me! */ - u_int l_dopreempt; /* s: kernel preemption pending */ + volatile int l_nopreempt; /* !: don't preempt me! */ + volatile u_int l_dopreempt; /* s: kernel preemption pending */ int l_pflag; /* !: LWP private flags */ int l_dupfd; /* !: side return from cloning devs XXX */ const struct sysent * volatile l_sysent;/* !: currently active syscall */ @@ -352,7 +352,7 @@ void lwp_need_userret(lwp_t *); void lwp_free(lwp_t *, bool, bool); uint64_t lwp_pctr(void); int lwp_setprivate(lwp_t *, void *); -int do_lwp_create(lwp_t *, void *, u_long, lwpid_t *, const sigset_t *, +int do_lwp_create(lwp_t *, void *, u_long, lwp_t **, const sigset_t *, const stack_t *); void lwpinit_specificdata(void);