diff options
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_brand.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_misc.c | 92 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_pid.c | 41 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_ptrace.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_brand.h | 25 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_misc.h | 5 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_pid.h | 61 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_futex.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_getpid.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_kill.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_sched.c | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/sn1/sn1_brand.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/brand/sngl/sngl_brand.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/brand/solaris10/s10_brand.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/os/brand.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/os/exec.c | 13 | ||||
-rw-r--r-- | usr/src/uts/common/os/lwp.c | 45 | ||||
-rw-r--r-- | usr/src/uts/common/sys/brand.h | 13 | ||||
-rw-r--r-- | usr/src/uts/common/sys/proc.h | 1 |
19 files changed, 188 insertions, 165 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c index c7d6e93edb..2be3082d48 100644 --- a/usr/src/uts/common/brand/lx/os/lx_brand.c +++ b/usr/src/uts/common/brand/lx/os/lx_brand.c @@ -147,7 +147,6 @@ #include <sys/machbrand.h> #include <sys/lx_syscalls.h> #include <sys/lx_misc.h> -#include <sys/lx_pid.h> #include <sys/lx_futex.h> #include <sys/lx_brand.h> #include <sys/param.h> @@ -244,7 +243,8 @@ struct brand_ops lx_brops = { lx_proc_exit, /* b_proc_exit */ lx_exec, /* b_exec */ lx_setrval, /* b_lwp_setrval */ - lx_brandlwp, /* b_brandlwp */ + lx_lwpdata_alloc, /* b_lwpdata_alloc */ + lx_lwpdata_free, /* b_lwpdata_free */ lx_initlwp, /* b_initlwp */ lx_forklwp, /* b_forklwp */ lx_freelwp, /* b_freelwp */ diff --git a/usr/src/uts/common/brand/lx/os/lx_misc.c b/usr/src/uts/common/brand/lx/os/lx_misc.c index 8b089af0a9..5d9577f453 100644 --- a/usr/src/uts/common/brand/lx/os/lx_misc.c +++ b/usr/src/uts/common/brand/lx/os/lx_misc.c @@ -37,7 +37,6 @@ #include <sys/brand.h> #include <sys/lx_brand.h> #include <sys/lx_misc.h> -#include <sys/lx_pid.h> #include <sys/lx_futex.h> #include <sys/cmn_err.h> #include <sys/siginfo.h> @@ -256,16 +255,68 @@ lx_freelwp(klwp_t *lwp) kmem_free(lwpd, sizeof (struct lx_lwp_data)); } -int -lx_brandlwp(klwp_t *lwp) +void * +lx_lwpdata_alloc(proc_t *p) { lx_lwp_data_t *lwpd; + struct lx_pid *lpidp; + pid_t newpid = 0; + struct pid *pidp = NULL; + + VERIFY(MUTEX_NOT_HELD(&p->p_lock)); + + /* + * LWPs beyond the first will require a pid to be allocated to emulate + * Linux's goofy thread model. While this allocation may be + * unnecessary when a single-lwp process undergoes branding, it cannot + * be performed during b_initlwp due to p_lock being held. + */ + if (p->p_lwpcnt > 0) { + if ((newpid = pid_allocate(p, 0, 0)) < 0) { + return (NULL); + } + pidp = pid_find(newpid); + } + + lwpd = kmem_zalloc(sizeof (struct lx_lwp_data), KM_SLEEP); + lpidp = kmem_zalloc(sizeof (struct lx_pid), KM_SLEEP); + + lpidp->l_pid = newpid; + lpidp->l_pidp = pidp; + lwpd->br_lpid = lpidp; + return (lwpd); +} + +/* + * Free lwp brand data if an error occurred during lwp_create. + * Otherwise, lx_freelwp will be used to free the resources after they're + * associated with the lwp via lx_initlwp. + */ +void +lx_lwpdata_free(void *lwpbd) +{ + lx_lwp_data_t *lwpd = (lx_lwp_data_t *)lwpbd; + VERIFY(lwpd != NULL); + VERIFY(lwpd->br_lpid != NULL); + + if (lwpd->br_lpid->l_pidp != NULL) { + (void) pid_rele(lwpd->br_lpid->l_pidp); + } + kmem_free(lwpd->br_lpid, sizeof (*lwpd->br_lpid)); + kmem_free(lwpd, sizeof (*lwpd)); +} + +void +lx_initlwp(klwp_t *lwp, void *lwpbd) +{ + lx_lwp_data_t *lwpd = (lx_lwp_data_t *)lwpbd; lx_lwp_data_t *plwpd = ttolxlwp(curthread); kthread_t *tp = lwptot(lwp); + proc_t *p = lwptoproc(lwp); + VERIFY(MUTEX_HELD(&p->p_lock)); VERIFY(lwp->lwp_brand == NULL); - lwpd = kmem_zalloc(sizeof (struct lx_lwp_data), KM_SLEEP); lwpd->br_exitwhy = CLD_EXITED; lwpd->br_lwp = lwp; lwpd->br_clear_ctidp = NULL; @@ -302,12 +353,28 @@ lx_brandlwp(klwp_t *lwp) } lwp->lwp_brand = lwpd; - if (lx_pid_assign(tp)) { - kmem_free(lwpd, sizeof (struct lx_lwp_data)); - lwp->lwp_brand = NULL; - return (-1); - } + /* + * When during lx_lwpdata_alloc, we must decide whether or not to + * allocate a new pid to associate with the lwp. Since p_lock is not + * held at that point, the only time we can guarantee a new pid isn't + * needed is when p_lwpcnt == 0. This is because other lwps won't be + * present to race with us with regards to pid allocation. + * + * This means that in all other cases (where p_lwpcnt > 0), we expect + * that lx_lwpdata_alloc will allocate a pid for us to use here, even + * if it is uneeded. If this process is undergoing an exec, for + * example, the single existing lwp will not need a new pid when it is + * rebranded. In that case, lx_pid_assign will free the uneeded pid. + */ + VERIFY(lwpd->br_lpid->l_pidp != NULL || p->p_lwpcnt == 0); + + lx_pid_assign(tp, lwpd->br_lpid); lwpd->br_tgid = lwpd->br_pid; + /* + * Having performed the lx pid assignement, the lpid reference is no + * longer needed. The underlying data will be freed during lx_freelwp. + */ + lwpd->br_lpid = NULL; installctx(lwptot(lwp), lwp, lx_save, lx_restore, NULL, NULL, lx_save, NULL); @@ -316,14 +383,7 @@ lx_brandlwp(klwp_t *lwp) * Install branded system call hook for this LWP: */ lwp->lwp_brand_syscall = lx_syscall_enter; - return (0); -} -void -lx_initlwp(klwp_t *lwp) -{ - lx_lwp_data_t *lwpd = lwptolxlwp(lwp); - lx_lwp_data_t *plwpd = ttolxlwp(curthread); /* * If the parent LWP has a ptrace(2) tracer, the new LWP may * need to inherit that same tracer. diff --git a/usr/src/uts/common/brand/lx/os/lx_pid.c b/usr/src/uts/common/brand/lx/os/lx_pid.c index 8552754c43..40179bbdaf 100644 --- a/usr/src/uts/common/brand/lx/os/lx_pid.c +++ b/usr/src/uts/common/brand/lx/os/lx_pid.c @@ -35,7 +35,6 @@ #include <sys/brand.h> #include <sys/zone.h> #include <sys/lx_brand.h> -#include <sys/lx_pid.h> #define LINUX_PROC_FACTOR 8 /* factor down the hash table by this */ static int hash_len = 4; /* desired average hash chain length */ @@ -101,47 +100,45 @@ lx_pid_remove_hash(pid_t pid, id_t tid) return (lpidp); } -struct pid *pid_find(pid_t pid); - /* * given a solaris pid/tid pair, create a linux pid */ -int -lx_pid_assign(kthread_t *t) +void +lx_pid_assign(kthread_t *t, struct lx_pid *lpidp) { proc_t *p = ttoproc(t); + lx_lwp_data_t *lwpd = ttolxlwp(t); pid_t s_pid = p->p_pid; id_t s_tid = t->t_tid; - struct pid *pidp; - struct lx_pid *lpidp; - lx_lwp_data_t *lwpd = ttolxlwp(t); - pid_t newpid; /* * When lx_initlwp is called from lx_setbrand, p_lwpcnt will already be * equal to 1. Since lx_initlwp is being called against an lwp that - * already exists, pid_allocate is not necessary. + * already exists, an additional pid allocation is not necessary. * * We check for this by testing br_ppid == 0. */ if (p->p_lwpcnt > 0 && lwpd->br_ppid != 0) { /* - * Allocate a pid for any thread other than the first + * Assign allocated pid to any thread other than the first. + * The l_pid and l_pidp fields should be populated. */ - if ((newpid = pid_allocate(p, 0, 0)) < 0) - return (-1); - - pidp = pid_find(newpid); + VERIFY(lpidp->l_pidp != NULL); + VERIFY(lpidp->l_pid != 0); } else { - pidp = NULL; - newpid = s_pid; + /* + * There are cases where a pid is speculatively allocated but + * is not needed. We are obligated to free it here. + */ + if (lpidp->l_pidp != NULL) { + (void) pid_rele(lpidp->l_pidp); + } + lpidp->l_pidp = NULL; + lpidp->l_pid = s_pid; } - lpidp = kmem_alloc(sizeof (struct lx_pid), KM_SLEEP); - lpidp->l_pid = newpid; lpidp->s_pid = s_pid; lpidp->s_tid = s_tid; - lpidp->l_pidp = pidp; lpidp->l_start = t->t_start; /* @@ -152,9 +149,7 @@ lx_pid_assign(kthread_t *t) lx_pid_insert_hash(lpidp); mutex_exit(&hash_lock); - lwpd->br_pid = newpid; - - return (0); + lwpd->br_pid = lpidp->l_pid; } /* diff --git a/usr/src/uts/common/brand/lx/os/lx_ptrace.c b/usr/src/uts/common/brand/lx/os/lx_ptrace.c index e64b5daf76..95df7b2d53 100644 --- a/usr/src/uts/common/brand/lx/os/lx_ptrace.c +++ b/usr/src/uts/common/brand/lx/os/lx_ptrace.c @@ -207,7 +207,6 @@ #include <sys/lx_brand.h> #include <sys/lx_impl.h> #include <sys/lx_misc.h> -#include <sys/lx_pid.h> #include <lx_syscall.h> #include <lx_signum.h> diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h index d384c09033..8bd351b635 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_brand.h +++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h @@ -24,7 +24,7 @@ */ /* - * Copyright 2015 Joyent, Inc. All rights reserved. + * Copyright 2015 Joyent, Inc. */ #ifndef _LX_BRAND_H @@ -499,6 +499,16 @@ typedef enum lx_stack_mode { LX_STACK_MODE_BRAND } lx_stack_mode_t; +struct lx_pid { + pid_t s_pid; /* the SunOS pid and ... */ + id_t s_tid; /* ... tid pair */ + pid_t l_pid; /* the corresponding linux pid */ + time_t l_start; /* birthday of this pid */ + struct pid *l_pidp; + struct lx_pid *stol_next; /* link in stol hash table */ + struct lx_pid *ltos_next; /* link in ltos hash table */ +}; + /* * lx-specific data in the klwp_t */ @@ -578,6 +588,11 @@ struct lx_lwp_data { * usermode. */ boolean_t br_strict_failure; + + /* + * Hold a pre-allocated lx_pid structure to be used during lx_initlwp. + */ + struct lx_pid *br_lpid; }; /* @@ -646,6 +661,14 @@ extern void lx_emulate_user32(klwp_t *, int, uintptr_t *); extern int lx_debug; #define lx_print if (lx_debug) printf +extern void lx_pid_assign(kthread_t *, struct lx_pid *); +extern void lx_pid_reassign(kthread_t *); +extern void lx_pid_rele(pid_t, id_t); +extern pid_t lx_lpid_to_spair(pid_t, pid_t *, id_t *); +extern pid_t lx_lwp_ppid(klwp_t *, pid_t *, id_t *); +extern void lx_pid_init(void); +extern void lx_pid_fini(void); + /* * In-Kernel Linux System Call Description. */ diff --git a/usr/src/uts/common/brand/lx/sys/lx_misc.h b/usr/src/uts/common/brand/lx/sys/lx_misc.h index 892b2bd00d..949cbd8f86 100644 --- a/usr/src/uts/common/brand/lx/sys/lx_misc.h +++ b/usr/src/uts/common/brand/lx/sys/lx_misc.h @@ -28,8 +28,9 @@ extern void lx_setrval(klwp_t *, int, int); extern void lx_exec(); extern void lx_exitlwp(klwp_t *); extern void lx_freelwp(klwp_t *); -extern int lx_brandlwp(klwp_t *); -extern void lx_initlwp(klwp_t *); +extern void *lx_lwpdata_alloc(proc_t *); +extern void lx_lwpdata_free(void *); +extern void lx_initlwp(klwp_t *, void *); extern void lx_forklwp(klwp_t *, klwp_t *); extern void lx_set_gdt(int, user_desc_t *); diff --git a/usr/src/uts/common/brand/lx/sys/lx_pid.h b/usr/src/uts/common/brand/lx/sys/lx_pid.h deleted file mode 100644 index 80c8079f0b..0000000000 --- a/usr/src/uts/common/brand/lx/sys/lx_pid.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * CDDL HEADER START - * - * The contents of this file are subject to the terms of the - * Common Development and Distribution License (the "License"). - * You may not use this file except in compliance with the License. - * - * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE - * or http://www.opensolaris.org/os/licensing. - * See the License for the specific language governing permissions - * and limitations under the License. - * - * When distributing Covered Code, include this CDDL HEADER in each - * file and include the License file at usr/src/OPENSOLARIS.LICENSE. - * If applicable, add the following below this CDDL HEADER, with the - * fields enclosed by brackets "[]" replaced with your own identifying - * information: Portions Copyright [yyyy] [name of copyright owner] - * - * CDDL HEADER END - */ -/* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -#ifndef _SYS_LX_PID_H -#define _SYS_LX_PID_H - -#pragma ident "%Z%%M% %I% %E% SMI" - -#include <sys/note.h> - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _KERNEL -struct lx_pid { - pid_t s_pid; /* the solaris pid and ... */ - id_t s_tid; /* ... tid pair */ - pid_t l_pid; /* the corresponding linux pid */ - time_t l_start; /* birthday of this pid */ - struct pid *l_pidp; - struct lx_pid *stol_next; /* link in stol hash table */ - struct lx_pid *ltos_next; /* link in ltos hash table */ -}; - -extern int lx_pid_assign(kthread_t *); -extern void lx_pid_reassign(kthread_t *); -extern void lx_pid_rele(pid_t, id_t); -extern pid_t lx_lpid_to_spair(pid_t, pid_t *, id_t *); -extern pid_t lx_lwp_ppid(klwp_t *, pid_t *, id_t *); -extern void lx_pid_init(void); -extern void lx_pid_fini(void); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _SYS_LX_PID_H */ diff --git a/usr/src/uts/common/brand/lx/syscall/lx_futex.c b/usr/src/uts/common/brand/lx/syscall/lx_futex.c index 519f9bbf4d..f6a8f33f46 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_futex.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_futex.c @@ -45,7 +45,6 @@ #include <sys/lx_brand.h> #include <sys/lx_futex.h> #include <sys/lx_impl.h> -#include <sys/lx_pid.h> /* * Futexes are a Linux-specific implementation of inter-process mutexes. diff --git a/usr/src/uts/common/brand/lx/syscall/lx_getpid.c b/usr/src/uts/common/brand/lx/syscall/lx_getpid.c index 88b1792d3c..c2506f52c5 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_getpid.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_getpid.c @@ -33,7 +33,6 @@ #include <sys/cpuvar.h> #include <sys/brand.h> #include <sys/lx_brand.h> -#include <sys/lx_pid.h> /* * return the pid diff --git a/usr/src/uts/common/brand/lx/syscall/lx_kill.c b/usr/src/uts/common/brand/lx/syscall/lx_kill.c index a4f04376e2..f6830f5a07 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_kill.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_kill.c @@ -36,7 +36,6 @@ #include <sys/signal.h> #include <sys/brand.h> #include <sys/lx_brand.h> -#include <sys/lx_pid.h> #include <lx_signum.h> #include <sys/contract/process_impl.h> diff --git a/usr/src/uts/common/brand/lx/syscall/lx_sched.c b/usr/src/uts/common/brand/lx/syscall/lx_sched.c index 4ebb7ff387..0def559e29 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_sched.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_sched.c @@ -35,7 +35,6 @@ #include <sys/tspriocntl.h> #include <sys/processor.h> #include <sys/brand.h> -#include <sys/lx_pid.h> #include <sys/lx_sched.h> #include <sys/lx_brand.h> diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.c b/usr/src/uts/common/brand/sn1/sn1_brand.c index ff11c58ae5..176044f68d 100644 --- a/usr/src/uts/common/brand/sn1/sn1_brand.c +++ b/usr/src/uts/common/brand/sn1/sn1_brand.c @@ -53,7 +53,7 @@ int sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t, void sn1_copy_procdata(proc_t *, proc_t *); void sn1_proc_exit(struct proc *); void sn1_exec(); -int sn1_brandlwp(klwp_t *); +void sn1_initlwp(klwp_t *, void *); void sn1_forklwp(klwp_t *, klwp_t *); void sn1_freelwp(klwp_t *); void sn1_lwpexit(klwp_t *); @@ -72,8 +72,9 @@ struct brand_ops sn1_brops = { sn1_proc_exit, /* b_proc_exit */ sn1_exec, /* b_exec */ lwp_setrval, /* b_lwp_setrval */ - sn1_brandlwp, /* b_brandlwp */ - NULL, /* b_initlwp */ + NULL, /* b_lwpdata_alloc */ + NULL, /* b_lwpdata_free */ + sn1_initlwp, /* b_initlwp */ sn1_forklwp, /* b_forklwp */ sn1_freelwp, /* b_freelwp */ sn1_lwpexit, /* b_lwpexit */ @@ -210,10 +211,10 @@ sn1_exec() brand_solaris_exec(&sn1_brand); } -int -sn1_brandlwp(klwp_t *l) +void +sn1_initlwp(klwp_t *l, void *bd) { - return (brand_solaris_brandlwp(l, &sn1_brand)); + brand_solaris_initlwp(l, &sn1_brand); } void diff --git a/usr/src/uts/common/brand/sngl/sngl_brand.c b/usr/src/uts/common/brand/sngl/sngl_brand.c index 9a1d76d157..3d4da3c441 100644 --- a/usr/src/uts/common/brand/sngl/sngl_brand.c +++ b/usr/src/uts/common/brand/sngl/sngl_brand.c @@ -54,7 +54,7 @@ int sngl_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t, void sngl_copy_procdata(proc_t *, proc_t *); void sngl_proc_exit(struct proc *); void sngl_exec(); -int sngl_brandlwp(klwp_t *); +void sngl_initlwp(klwp_t *, void *); void sngl_forklwp(klwp_t *, klwp_t *); void sngl_freelwp(klwp_t *); void sngl_lwpexit(klwp_t *); @@ -73,8 +73,9 @@ struct brand_ops sngl_brops = { sngl_proc_exit, /* b_proc_exit */ sngl_exec, /* b_exec */ lwp_setrval, /* b_lwp_setrval */ - sngl_brandlwp, /* b_brandlwp */ - NULL, /* b_initlwp */ + NULL, /* b_lwpdata_alloc */ + NULL, /* b_lwpdata_free */ + sngl_initlwp, /* b_initlwp */ sngl_forklwp, /* b_forklwp */ sngl_freelwp, /* b_freelwp */ sngl_lwpexit, /* b_lwpexit */ @@ -196,10 +197,10 @@ sngl_exec() brand_solaris_exec(&sngl_brand); } -int -sngl_brandlwp(klwp_t *l) +void +sngl_initlwp(klwp_t *l, void *bd) { - return (brand_solaris_brandlwp(l, &sngl_brand)); + brand_solaris_initlwp(l, &sngl_brand); } void diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.c b/usr/src/uts/common/brand/solaris10/s10_brand.c index 1239dcc323..1dc2671386 100644 --- a/usr/src/uts/common/brand/solaris10/s10_brand.c +++ b/usr/src/uts/common/brand/solaris10/s10_brand.c @@ -56,7 +56,7 @@ int s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t, void s10_copy_procdata(proc_t *, proc_t *); void s10_proc_exit(struct proc *); void s10_exec(); -int s10_brandlwp(klwp_t *); +void s10_initlwp(klwp_t *, void *); void s10_forklwp(klwp_t *, klwp_t *); void s10_freelwp(klwp_t *); void s10_lwpexit(klwp_t *); @@ -77,8 +77,9 @@ struct brand_ops s10_brops = { s10_proc_exit, /* b_proc_exit */ s10_exec, /* b_exec */ lwp_setrval, /* b_lwp_setrval */ - s10_brandlwp, /* b_brandlwp */ - NULL, /* b_initlwp */ + NULL, /* b_lwpdata_alloc */ + NULL, /* b_lwpdata_free */ + s10_initlwp, /* b_initlwp */ s10_forklwp, /* b_forklwp */ s10_freelwp, /* b_freelwp */ s10_lwpexit, /* b_lwpexit */ @@ -365,10 +366,10 @@ s10_exec() brand_solaris_exec(&s10_brand); } -int -s10_brandlwp(klwp_t *l) +void +s10_initlwp(klwp_t *l, void *bd) { - return (brand_solaris_brandlwp(l, &s10_brand)); + brand_solaris_initlwp(l, &s10_brand); } void diff --git a/usr/src/uts/common/os/brand.c b/usr/src/uts/common/os/brand.c index 61aa562f73..00f2ce0440 100644 --- a/usr/src/uts/common/os/brand.c +++ b/usr/src/uts/common/os/brand.c @@ -1037,7 +1037,7 @@ brand_solaris_exec(struct brand *pbrand) /* Upon exec, reset our lwp brand data. */ (void) brand_solaris_freelwp(ttolwp(curthread), pbrand); - (void) brand_solaris_brandlwp(ttolwp(curthread), pbrand); + (void) brand_solaris_initlwp(ttolwp(curthread), pbrand); /* * Upon exec, reset all the proc brand data, except for the elf @@ -1081,7 +1081,7 @@ brand_solaris_forklwp(klwp_t *p, klwp_t *c, struct brand *pbrand) /* * Both LWPs have already had been initialized via - * brand_solaris_brandlwp(). + * brand_solaris_initlwp(). */ ASSERT(p->lwp_brand != NULL); ASSERT(c->lwp_brand != NULL); @@ -1098,14 +1098,13 @@ brand_solaris_freelwp(klwp_t *l, struct brand *pbrand) } /*ARGSUSED*/ -int -brand_solaris_brandlwp(klwp_t *l, struct brand *pbrand) +void +brand_solaris_initlwp(klwp_t *l, struct brand *pbrand) { ASSERT(l->lwp_procp->p_brand == pbrand); ASSERT(l->lwp_procp->p_brand_data != NULL); ASSERT(l->lwp_brand == NULL); l->lwp_brand = (void *)-1; - return (0); } /*ARGSUSED*/ diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c index 4b6c79997e..7e32fb0506 100644 --- a/usr/src/uts/common/os/exec.c +++ b/usr/src/uts/common/os/exec.c @@ -301,19 +301,20 @@ exec_common(const char *fname, const char **argp, const char **envp, /* If necessary, brand this process/lwp before we start the exec. */ if (brandme) { + void *brand_data = NULL; + brand_setbrand(p); - if (BROP(p)->b_brandlwp(lwp) != 0) { + if (BROP(p)->b_lwpdata_alloc != NULL && + (brand_data = BROP(p)->b_lwpdata_alloc(p)) == NULL) { VN_RELE(vp); if (dir != NULL) VN_RELE(dir); pn_free(&resolvepn); goto fail; } - if (BROP(p)->b_initlwp != NULL) { - mutex_enter(&p->p_lock); - BROP(p)->b_initlwp(lwp); - mutex_exit(&p->p_lock); - } + mutex_enter(&p->p_lock); + BROP(p)->b_initlwp(lwp, brand_data); + mutex_exit(&p->p_lock); } if ((error = gexec(&vp, &ua, &args, NULL, 0, &execsz, diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c index 6b91e410d7..f5be1b40b3 100644 --- a/usr/src/uts/common/os/lwp.c +++ b/usr/src/uts/common/os/lwp.c @@ -115,7 +115,7 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p, ret_tidhash_t *ret_tidhash = NULL; int i; int rctlfail = 0; - boolean_t branded = B_FALSE; + void *brand_data = NULL; struct ctxop *ctx = NULL; ASSERT(cid != sysdccid); /* system threads must start in SYS */ @@ -283,6 +283,19 @@ lwp_create(void (*proc)(), caddr_t arg, size_t len, proc_t *p, */ lep = kmem_zalloc(sizeof (*lep), KM_SLEEP); + /* + * If necessary, speculatively allocate lwp brand data. This is done + * ahead of time so p_lock need not be dropped during lwp branding. + */ + if (PROC_IS_BRANDED(p) && BROP(p)->b_lwpdata_alloc != NULL) { + if ((brand_data = BROP(p)->b_lwpdata_alloc(p)) == NULL) { + mutex_enter(&p->p_lock); + err = 1; + atomic_inc_32(&p->p_zone->zone_ffmisc); + goto error; + } + } + mutex_enter(&p->p_lock); grow: /* @@ -682,25 +695,15 @@ grow: t->t_pre_sys = 1; t->t_post_sys = 1; - mutex_exit(&p->p_lock); - /* - * If this is a branded process, allocate any brand-specific lwp data. - */ - if (PROC_IS_BRANDED(p)) { - if (BROP(p)->b_brandlwp(lwp) != 0) { - mutex_enter(&p->p_lock); - err = 1; - atomic_inc_32(&p->p_zone->zone_ffmisc); - goto error; - } - branded = B_TRUE; - } - - mutex_enter(&p->p_lock); - /* Complete branded lwp initialization */ - if (branded && BROP(p)->b_initlwp != NULL) { - BROP(p)->b_initlwp(lwp); + if (PROC_IS_BRANDED(p)) { + BROP(p)->b_initlwp(lwp, brand_data); + /* + * The b_initlwp hook is expected to consume any preallocated + * brand_data in a way that prepares it for deallocation by the + * b_freelwp hook. + */ + brand_data = NULL; } /* @@ -762,8 +765,8 @@ error: if (cid != NOCLASS && bufp != NULL) CL_FREE(cid, bufp); - if (branded) { - BROP(p)->b_freelwp(lwp); + if (brand_data != NULL) { + BROP(p)->b_lwpdata_free(brand_data); } mutex_exit(&p->p_lock); diff --git a/usr/src/uts/common/sys/brand.h b/usr/src/uts/common/sys/brand.h index f94c93d748..79e02dcf17 100644 --- a/usr/src/uts/common/sys/brand.h +++ b/usr/src/uts/common/sys/brand.h @@ -117,7 +117,7 @@ struct execa; * b_proc_exit - Perform process brand exit processing * b_exec - Reset branded process state on exec * b_lwp_setrval - Set return code for forked child - * b_brandlwp - Allocate lwp brand data (p_lock not held) + * b_initlwp - Initialize lwp brand data * b_forklwp - Copy lwp brand data during fork * b_freelwp - Free lwp brand data * b_lwpexit - Perform lwp-specific brand exit processing @@ -128,7 +128,9 @@ struct execa; * b_sendsig - Update process state after sendsig * * Optional Fields: - * b_initlwp - Populate lwp brand data after b_brandlwp (p_lock held) + * b_lwpdata_alloc - Speculatively allocate data for use in b_initlwp + * b_lwpdata_free - Free data from allocated by b_lwpdata_alloc if errors occur + * during lwp creation before b_initlwp could be called. * b_exit_with_sig - Instead of sending SIGCLD, exit with custom behavior * b_psig_to_proc - Custom additional behavior during psig * b_wait_filter - Filter processes from being matched by waitid @@ -157,8 +159,9 @@ struct brand_ops { void (*b_proc_exit)(struct proc *); void (*b_exec)(); void (*b_lwp_setrval)(klwp_t *, int, int); - int (*b_brandlwp)(klwp_t *); - void (*b_initlwp)(klwp_t *); + void *(*b_lwpdata_alloc)(struct proc *); + void (*b_lwpdata_free)(void *); + void (*b_initlwp)(klwp_t *, void *); void (*b_forklwp)(klwp_t *, klwp_t *); void (*b_freelwp)(klwp_t *); void (*b_lwpexit)(klwp_t *); @@ -251,7 +254,7 @@ extern int brand_solaris_fini(char **, struct modlinkage *, struct brand *); extern void brand_solaris_forklwp(klwp_t *, klwp_t *, struct brand *); extern void brand_solaris_freelwp(klwp_t *, struct brand *); -extern int brand_solaris_brandlwp(klwp_t *, struct brand *); +extern void brand_solaris_initlwp(klwp_t *, struct brand *); extern void brand_solaris_lwpexit(klwp_t *, struct brand *); extern void brand_solaris_proc_exit(struct proc *, struct brand *); extern void brand_solaris_setbrand(proc_t *, struct brand *); diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h index 8c70743aa4..e811bebf25 100644 --- a/usr/src/uts/common/sys/proc.h +++ b/usr/src/uts/common/sys/proc.h @@ -629,6 +629,7 @@ extern int signal_is_blocked(kthread_t *, int); extern int sigcheck(proc_t *, kthread_t *); extern void sigdefault(proc_t *); +extern struct pid *pid_find(pid_t pid); extern void pid_setmin(void); extern pid_t pid_allocate(proc_t *, pid_t, int); extern int pid_rele(struct pid *); |