usr/src/uts/common/os/exec.c
author stevel@tonic-gate
Tue, 14 Jun 2005 00:00:00 -0700
changeset 0 68f95e015346
child 1043 3dbf7cd1f771
permissions -rw-r--r--
OpenSolaris Launch
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*	Copyright (c) 1988 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
/*	  All Rights Reserved  	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
#include <sys/sysmacros.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
#include <sys/systm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
#include <sys/signal.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
#include <sys/cred_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
#include <sys/policy.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
#include <sys/user.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
#include <sys/errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
#include <sys/file.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
#include <sys/vfs.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
#include <sys/vnode.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
#include <sys/mman.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
#include <sys/acct.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
#include <sys/cpuvar.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
#include <sys/proc.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
#include <sys/cmn_err.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
#include <sys/debug.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
#include <sys/pathname.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
#include <sys/vm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
#include <sys/vtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
#include <sys/exec.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
#include <sys/exechdr.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
#include <sys/kmem.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
#include <sys/prsystm.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
#include <sys/modctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
#include <sys/vmparam.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
#include <sys/schedctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
#include <sys/utrap.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
#include <sys/systeminfo.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
#include <sys/stack.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
#include <sys/rctl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
#include <sys/dtrace.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
#include <sys/lwpchan_impl.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
#include <sys/pool.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
#include <sys/sdt.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#include <c2/audit.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
#include <vm/hat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
#include <vm/anon.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include <vm/as.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <vm/seg.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#include <vm/seg_vn.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#define	PRIV_RESET		0x01	/* needs to reset privs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
#define	PRIV_SETID		0x02	/* needs to change uids */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#define	PRIV_SETUGID		0x04	/* is setuid/setgid/forced privs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
#define	PRIV_INCREASE		0x08	/* child runs with more privs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
static int hold_execsw(struct execsw *);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
uint_t auxv_hwcap = 0;	/* auxv AT_SUN_HWCAP value; determined on the fly */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
#if defined(_SYSCALL32_IMPL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
uint_t auxv_hwcap32 = 0;	/* 32-bit version of auxv_hwcap */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
#if defined(__i386) || defined(__amd64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
extern void ldt_free(proc_t *p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
extern void ldt_load(void);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
int exec_lpg_disable = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
#define	PSUIDFLAGS		(SNOCD|SUGID)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 * exec() - wrapper around exece providing NULL environment pointer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
exec(const char *fname, const char **argp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
	return (exece(fname, argp, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
 * exece() - system call wrapper around exec_common()
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
exece(const char *fname, const char **argp, const char **envp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	error = exec_common(fname, argp, envp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
	return (error ? (set_errno(error)) : 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
exec_common(const char *fname, const char **argp, const char **envp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
	vnode_t *vp = NULL, *dir = NULL, *tmpvp = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	proc_t *p = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	klwp_t *lwp = ttolwp(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	struct user *up = PTOU(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	long execsz;		/* temporary count of exec size */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
	char exec_file[MAXCOMLEN+1];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	struct pathname pn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
	struct pathname resolvepn;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
	struct uarg args;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	struct execa ua;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	k_sigset_t savedmask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	lwpdir_t *lwpdir = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	lwpdir_t **tidhash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	lwpdir_t *old_lwpdir = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	uint_t old_lwpdir_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	lwpdir_t **old_tidhash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	uint_t old_tidhash_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
	lwpent_t *lep;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	 * exec() is not supported for the /proc agent lwp.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	if (curthread == p->p_agenttp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
		return (ENOTSUP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	if ((error = secpolicy_basic_exec(CRED())) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
	 * Inform /proc that an exec() has started.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
	 * Hold signals that are ignored by default so that we will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
	 * not be interrupted by a signal that will be ignored after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
	 * successful completion of gexec().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
	prexecstart();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	schedctl_finish_sigblock(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	savedmask = curthread->t_hold;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
	sigorset(&curthread->t_hold, &ignoredefault);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	 * Look up path name and remember last component for later.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	 * To help coreadm expand its %d token, we attempt to save
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
	 * the directory containing the executable in p_execdir. The
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
	 * first call to lookuppn() may fail and return EINVAL because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	 * dirvpp is non-NULL. In that case, we make a second call to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	 * lookuppn() with dirvpp set to NULL; p_execdir will be NULL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	 * but coreadm is allowed to expand %d to the empty string and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	 * there are other cases in which that failure may occur.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	pn_alloc(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	if ((error = lookuppn(&pn, &resolvepn, FOLLOW, &dir, &vp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
		pn_free(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
		pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
		if (error != EINVAL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
		dir = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
		if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
		pn_alloc(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
		if ((error = lookuppn(&pn, &resolvepn, FOLLOW, NULLVPP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		    &vp)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
			pn_free(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
			pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
			goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	if (vp == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
		if (dir != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
			VN_RELE(dir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
		error = ENOENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
		pn_free(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
		pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
		goto out;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	bzero(exec_file, MAXCOMLEN+1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	(void) strncpy(exec_file, pn.pn_path, MAXCOMLEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	bzero(&args, sizeof (args));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
	args.pathname = resolvepn.pn_path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
	/* don't free resolvepn until we are done with args */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	pn_free(&pn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
	 * Specific exec handlers, or policies determined via
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	 * /etc/system may override the historical default.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	args.stk_prot = PROT_ZFOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	args.dat_prot = PROT_ZFOD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
	CPU_STATS_ADD_K(sys, sysexec, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
	DTRACE_PROC1(exec, char *, args.pathname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	ua.fname = fname;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
	ua.argp = argp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
	ua.envp = envp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
	if ((error = gexec(&vp, &ua, &args, NULL, 0, &execsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
	    exec_file, p->p_cred)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
		if (dir != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
			VN_RELE(dir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
		pn_free(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
	 * Free floating point registers (sun4u only)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
	ASSERT(lwp != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
	lwp_freeregs(lwp, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
	 * Free device context
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
	if (curthread->t_ctx)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		freectx(curthread, 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
	 * Remember file name for accounting; clear any cached DTrace predicate.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	up->u_acflag &= ~AFORK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	bcopy(exec_file, up->u_comm, MAXCOMLEN+1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
	curthread->t_predcache = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
	 * Clear contract template state
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
	lwp_ctmpl_clear(lwp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
	 * Save the directory in which we found the executable for expanding
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
	 * the %d token used in core file patterns.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   262
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   263
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   264
	tmpvp = p->p_execdir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   265
	p->p_execdir = dir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   266
	if (p->p_execdir != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   267
		VN_HOLD(p->p_execdir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
	if (tmpvp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
		VN_RELE(tmpvp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
	 * Reset stack state to the user stack, clear set of signals
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
	 * caught on the signal stack, and reset list of signals that
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
	 * restart system calls; the new program's environment should
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
	 * not be affected by detritus from the old program.  Any
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	 * pending held signals remain held, so don't clear t_hold.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
	lwp->lwp_oldcontext = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
	lwp->lwp_ustack = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
	lwp->lwp_old_stk_ctl = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
	sigemptyset(&up->u_signodefer);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
	sigemptyset(&up->u_sigonstack);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
	sigemptyset(&up->u_sigresethand);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
	lwp->lwp_sigaltstack.ss_sp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
	lwp->lwp_sigaltstack.ss_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
	lwp->lwp_sigaltstack.ss_flags = SS_DISABLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
	 * Make saved resource limit == current resource limit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	for (i = 0; i < RLIM_NLIMITS; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
		/*CONSTCOND*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		if (RLIM_SAVED(i)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
			(void) rctl_rlimit_get(rctlproc_legacy[i], p,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
			    &up->u_saved_rlimit[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	 * If the action was to catch the signal, then the action
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
	 * must be reset to SIG_DFL.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
	sigdefault(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
	p->p_flag &= ~(SNOWAIT|SJCTL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
	p->p_flag |= (SEXECED|SMSACCT|SMSFORK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
	up->u_signal[SIGCLD - 1] = SIG_DFL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
	 * Delete the dot4 sigqueues/signotifies.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   313
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	sigqfree(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
	mutex_enter(&p->p_pflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
	p->p_prof.pr_base = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
	p->p_prof.pr_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
	p->p_prof.pr_off = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
	p->p_prof.pr_scale = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
	p->p_prof.pr_samples = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
	mutex_exit(&p->p_pflock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
	ASSERT(curthread->t_schedctl == NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
#if defined(__i386) || defined(__amd64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
	/* If the process uses a private LDT then change it to default */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
	if (p->p_ldt)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
		ldt_free(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
#endif	/* __i386 || __amd64 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
#if defined(__amd64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
	 * Make sure the process has the correct LDT descriptor for its data
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
	 * model.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	if (p->p_model == DATAMODEL_LP64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   340
		p->p_ldt_desc = ldt0_default64_desc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   341
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   342
		p->p_ldt_desc = ldt0_default_desc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   345
	 * Ensure the change of LDT is propagated into the LDTR.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   346
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
	kpreempt_disable();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
	ldt_load();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
	kpreempt_enable();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
#endif /* __amd64 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
#if defined(__sparc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
	if (p->p_utraps != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   354
		utrap_free(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   355
#endif	/* __sparc */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   357
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   358
	 * Close all close-on-exec files.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   359
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
	close_exec(P_FINFO(p));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   361
	TRACE_2(TR_FAC_PROC, TR_PROC_EXEC, "proc_exec:p %p up %p", p, up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
	setregs(&args);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	/* Mark this as an executable vnode */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	mutex_enter(&vp->v_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	vp->v_flag |= VVMEXEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	mutex_exit(&vp->v_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
	if (dir != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
		VN_RELE(dir);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
	pn_free(&resolvepn);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
	 * Allocate a new lwp directory and lwpid hash table if necessary.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
	if (curthread->t_tid != 1 || p->p_lwpdir_sz != 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		lwpdir = kmem_zalloc(2 * sizeof (lwpdir_t), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   379
		lwpdir->ld_next = lwpdir + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   380
		tidhash = kmem_zalloc(2 * sizeof (lwpdir_t *), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   381
		if (p->p_lwpdir != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   382
			lep = p->p_lwpdir[curthread->t_dslot].ld_entry;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   383
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   384
			lep = kmem_zalloc(sizeof (*lep), KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   385
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   387
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   388
	prbarrier(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   389
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   390
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   391
	 * Reset lwp id to the default value of 1.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   392
	 * This is a single-threaded process now
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   393
	 * and lwp #1 is lwp_wait()able by default.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   394
	 * The t_unpark flag should not be inherited.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   395
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   396
	ASSERT(p->p_lwpcnt == 1 && p->p_zombcnt == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   397
	curthread->t_tid = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   398
	curthread->t_unpark = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   399
	curthread->t_proc_flag |= TP_TWAIT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   400
	curthread->t_proc_flag &= ~TP_DAEMON;	/* daemons shouldn't exec */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   401
	p->p_lwpdaemon = 0;			/* but oh well ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   402
	p->p_lwpid = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   403
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   404
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   405
	 * Install the newly-allocated lwp directory and lwpid hash table
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   406
	 * and insert the current thread into the new hash table.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   407
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   408
	if (lwpdir != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   409
		old_lwpdir = p->p_lwpdir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   410
		old_lwpdir_sz = p->p_lwpdir_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		old_tidhash = p->p_tidhash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   412
		old_tidhash_sz = p->p_tidhash_sz;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
		p->p_lwpdir = p->p_lwpfree = lwpdir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
		p->p_lwpdir_sz = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
		p->p_tidhash = tidhash;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
		p->p_tidhash_sz = 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		lep->le_thread = curthread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		lep->le_lwpid = curthread->t_tid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   419
		lep->le_start = curthread->t_start;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   420
		lwp_hash_in(p, lep);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   421
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   422
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   423
	 * Restore the saved signal mask and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
	 * inform /proc that the exec() has finished.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
	curthread->t_hold = savedmask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
	prexecend();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
	if (old_lwpdir) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   430
		kmem_free(old_lwpdir, old_lwpdir_sz * sizeof (lwpdir_t));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
		kmem_free(old_tidhash, old_tidhash_sz * sizeof (lwpdir_t *));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
	ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
	DTRACE_PROC(exec__success);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
	DTRACE_PROC1(exec__failure, int, error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
out:		/* error return */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
	curthread->t_hold = savedmask;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
	prexecend();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
	ASSERT(error != 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
 * Perform generic exec duties and switchout to object-file specific
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
 * handler.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
gexec(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
	struct vnode **vpp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
	struct execa *uap,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
	struct uarg *args,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
	struct intpdata *idatap,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
	int level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
	long *execsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
	caddr_t exec_file,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   462
	struct cred *cred)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
	struct vnode *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
	proc_t *pp = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
	struct execsw *eswp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
	int suidflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
	ssize_t resid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
	uid_t uid, gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
	struct vattr vattr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   472
	char magbuf[MAGIC_BYTES];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   473
	int setid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   474
	cred_t *oldcred, *newcred = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   475
	int privflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   476
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   477
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   478
	 * If the SNOCD or SUGID flag is set, turn it off and remember the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   479
	 * previous setting so we can restore it if we encounter an error.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   480
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
	if (level == 0 && (pp->p_flag & PSUIDFLAGS)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
		mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
		suidflags = pp->p_flag & PSUIDFLAGS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
		pp->p_flag &= ~PSUIDFLAGS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   485
		mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	if ((error = execpermissions(*vpp, &vattr, args)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
	/* need to open vnode for stateful file systems like rfs */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
	if ((error = VOP_OPEN(vpp, FREAD, CRED())) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
	vp = *vpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   495
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
	 * Note: to support binary compatibility with SunOS a.out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
	 * executables, we read in the first four bytes, as the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	 * magic number is in bytes 2-3.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	if (error = vn_rdwr(UIO_READ, vp, magbuf, sizeof (magbuf),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	    (offset_t)0, UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
	if (resid != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
	if ((eswp = findexec_by_hdr(magbuf)) == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   508
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   509
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   510
	if (level == 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   511
	    (privflags = execsetid(vp, &vattr, &uid, &gid)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   512
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   513
		newcred = cred = crdup(cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   514
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
		/* If we can, drop the PA bit */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
		if ((privflags & PRIV_RESET) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
			priv_adjust_PA(cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   518
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
		if (privflags & PRIV_SETID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
			cred->cr_uid = uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   521
			cred->cr_gid = gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   522
			cred->cr_suid = uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
			cred->cr_sgid = gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   524
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   526
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
		 * Implement the privilege updates:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
		 * Restrict with L:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   531
		 *	I' = I & L
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
		 *	E' = P' = (I' + F) & A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
		 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   535
		 * But if running under ptrace, we cap I with P.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		if ((privflags & PRIV_RESET) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
			if ((privflags & PRIV_INCREASE) != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
			    (pp->p_proc_flag & P_PR_PTRACE) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
				priv_intersect(&CR_OPPRIV(cred),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
						    &CR_IPRIV(cred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
			priv_intersect(&CR_LPRIV(cred), &CR_IPRIV(cred));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
			CR_EPRIV(cred) = CR_PPRIV(cred) = CR_IPRIV(cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   544
			priv_adjust_PA(cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
	/* SunOS 4.x buy-back */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
	if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
	    (vattr.va_mode & (VSUID|VSGID))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   551
		cmn_err(CE_NOTE,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   552
		    "!%s, uid %d: setuid execution not allowed, dev=%lx",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   553
		    exec_file, cred->cr_uid, vp->v_vfsp->vfs_dev);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   554
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   555
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   556
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   557
	 * execsetid() told us whether or not we had to change the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   558
	 * credentials of the process.  In privflags, it told us
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
	 * whether we gained any privileges or executed a set-uid executable.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   560
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   561
	setid = (privflags & (PRIV_SETUGID|PRIV_INCREASE));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   563
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   564
	 * Use /etc/system variable to determine if the stack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   565
	 * should be marked as executable by default.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   566
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   567
	if (noexec_user_stack)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   568
		args->stk_prot &= ~PROT_EXEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   569
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   570
	args->execswp = eswp; /* Save execsw pointer in uarg for exec_func */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   571
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   572
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   573
	 * Traditionally, the setid flags told the sub processes whether
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   574
	 * the file just executed was set-uid or set-gid; this caused
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   575
	 * some confusion as the 'setid' flag did not match the SUGID
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
	 * process flag which is only set when the uids/gids do not match.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	 * A script set-gid/set-uid to the real uid/gid would start with
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	 * /dev/fd/X but an executable would happily trust LD_LIBRARY_PATH.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
	 * Now we flag those cases where the calling process cannot
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	 * be trusted to influence the newly exec'ed process, either
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
	 * because it runs with more privileges or when the uids/gids
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   582
	 * do in fact not match.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
	 * This also makes the runtime linker agree with the on exec
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
	 * values of SNOCD and SUGID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	error = (*eswp->exec_func)(vp, uap, args, idatap, level, execsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
		(setid & PRIV_INCREASE) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
		cred->cr_uid != cred->cr_ruid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
		(cred->cr_rgid != cred->cr_gid &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
		!supgroupmember(cred->cr_gid, cred)), exec_file, cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	rw_exit(eswp->exec_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	if (error != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
		if (newcred != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
			crfree(newcred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
		goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	if (level == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
		mutex_enter(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
		if (newcred != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
			 * Free the old credentials, and set the new ones.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   603
			 * Do this for both the process and the (single) thread.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   604
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
			crfree(pp->p_cred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
			pp->p_cred = cred;	/* cred already held for proc */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
			crhold(cred);		/* hold new cred for thread */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   609
			 * DTrace accesses t_cred in probe context.  t_cred
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   610
			 * must always be either NULL, or point to a valid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   611
			 * allocated cred structure.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   612
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   613
			oldcred = curthread->t_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   614
			curthread->t_cred = cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   615
			crfree(oldcred);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   616
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   617
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   618
		 * On emerging from a successful exec(), the saved
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   619
		 * uid and gid equal the effective uid and gid.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   620
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   621
		cred->cr_suid = cred->cr_uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   622
		cred->cr_sgid = cred->cr_gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   623
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   624
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   625
		 * If the real and effective ids do not match, this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   626
		 * is a setuid process that should not dump core.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   627
		 * The group comparison is tricky; we prevent the code
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   628
		 * from flagging SNOCD when executing with an effective gid
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   629
		 * which is a supplementary group.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   630
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   631
		if (cred->cr_ruid != cred->cr_uid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   632
		    (cred->cr_rgid != cred->cr_gid &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   633
		    !supgroupmember(cred->cr_gid, cred)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   634
		    (privflags & PRIV_INCREASE) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   635
			suidflags = PSUIDFLAGS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   636
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   637
			suidflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   638
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   639
		mutex_exit(&pp->p_crlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   640
		if (suidflags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   641
			mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   642
			pp->p_flag |= suidflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   643
			mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   644
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   645
		if (setid && (pp->p_proc_flag & P_PR_PTRACE) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   646
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   647
			 * If process is traced via /proc, arrange to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   648
			 * invalidate the associated /proc vnode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   649
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   650
			if (pp->p_plist || (pp->p_proc_flag & P_PR_TRACE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   651
				args->traceinval = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   652
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   653
		if (pp->p_proc_flag & P_PR_PTRACE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   654
			psignal(pp, SIGTRAP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   655
		if (args->traceinval)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   656
			prinvalidate(&pp->p_user);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   657
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   658
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   659
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   660
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   661
	if (error == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   662
		error = ENOEXEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   663
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   664
	if (suidflags) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   665
		mutex_enter(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   666
		pp->p_flag |= suidflags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   667
		mutex_exit(&pp->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   668
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   669
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   670
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   671
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   672
extern char *execswnames[];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   673
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   674
struct execsw *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   675
allocate_execsw(char *name, char *magic, size_t magic_size)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   676
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   677
	int i, j;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   678
	char *ename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   679
	char *magicp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   680
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   681
	mutex_enter(&execsw_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   682
	for (i = 0; i < nexectype; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   683
		if (execswnames[i] == NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   684
			ename = kmem_alloc(strlen(name) + 1, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   685
			(void) strcpy(ename, name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   686
			execswnames[i] = ename;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   687
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   688
			 * Set the magic number last so that we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   689
			 * don't need to hold the execsw_lock in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   690
			 * findexectype().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   691
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   692
			magicp = kmem_alloc(magic_size, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   693
			for (j = 0; j < magic_size; j++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   694
				magicp[j] = magic[j];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   695
			execsw[i].exec_magic = magicp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   696
			mutex_exit(&execsw_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   697
			return (&execsw[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   698
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   699
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   700
	mutex_exit(&execsw_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   701
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   702
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   703
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   704
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   705
 * Find the exec switch table entry with the corresponding magic string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   706
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   707
struct execsw *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   708
findexecsw(char *magic)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   709
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   710
	struct execsw *eswp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   711
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   712
	for (eswp = execsw; eswp < &execsw[nexectype]; eswp++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   713
		ASSERT(eswp->exec_maglen <= MAGIC_BYTES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   714
		if (magic && eswp->exec_maglen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   715
		    bcmp(magic, eswp->exec_magic, eswp->exec_maglen) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   716
			return (eswp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   717
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   718
	return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   719
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   720
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   721
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   722
 * Find the execsw[] index for the given exec header string by looking for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   723
 * magic string at a specified offset and length for each kind of executable
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   724
 * file format until one matches.  If no execsw[] entry is found, try to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   725
 * autoload a module for this magic string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   726
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   727
struct execsw *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   728
findexec_by_hdr(char *header)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   729
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   730
	struct execsw *eswp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   731
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   732
	for (eswp = execsw; eswp < &execsw[nexectype]; eswp++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   733
		ASSERT(eswp->exec_maglen <= MAGIC_BYTES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   734
		if (header && eswp->exec_maglen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   735
		    bcmp(&header[eswp->exec_magoff], eswp->exec_magic,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   736
			    eswp->exec_maglen) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   737
			if (hold_execsw(eswp) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   738
				return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   739
			return (eswp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   740
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   741
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   742
	return (NULL);	/* couldn't find the type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   743
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   744
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   745
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   746
 * Find the execsw[] index for the given magic string.  If no execsw[] entry
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   747
 * is found, try to autoload a module for this magic string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   748
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   749
struct execsw *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   750
findexec_by_magic(char *magic)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   751
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   752
	struct execsw *eswp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   753
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
	for (eswp = execsw; eswp < &execsw[nexectype]; eswp++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
		ASSERT(eswp->exec_maglen <= MAGIC_BYTES);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
		if (magic && eswp->exec_maglen != 0 &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
		    bcmp(magic, eswp->exec_magic, eswp->exec_maglen) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
			if (hold_execsw(eswp) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
				return (NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
			return (eswp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
	return (NULL);	/* couldn't find the type */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
hold_execsw(struct execsw *eswp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
	char *name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
	rw_enter(eswp->exec_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
	while (!LOADED_EXEC(eswp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
		rw_exit(eswp->exec_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
		name = execswnames[eswp-execsw];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   775
		ASSERT(name);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   776
		if (modload("exec", name) == -1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   777
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   778
		rw_enter(eswp->exec_lock, RW_READER);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   779
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   780
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   781
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   782
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   783
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   784
execsetid(struct vnode *vp, struct vattr *vattrp, uid_t *uidp, uid_t *gidp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   785
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   786
	proc_t *pp = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   787
	uid_t uid, gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   788
	cred_t *cr = pp->p_cred;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   789
	int privflags = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   790
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   791
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   792
	 * Remember credentials.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   793
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   794
	uid = cr->cr_uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   795
	gid = cr->cr_gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   796
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   797
	/* Will try to reset the PRIV_AWARE bit later. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   798
	if ((CR_FLAGS(cr) & (PRIV_AWARE|PRIV_AWARE_INHERIT)) == PRIV_AWARE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   799
		privflags |= PRIV_RESET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   800
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   801
	if ((vp->v_vfsp->vfs_flag & VFS_NOSETUID) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   802
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   803
		 * Set-uid root execution only allowed if the limit set
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   804
		 * holds all unsafe privileges.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   805
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   806
		if ((vattrp->va_mode & VSUID) && (vattrp->va_uid != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   807
		    priv_issubset(&priv_unsafe, &CR_LPRIV(cr)))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   808
			uid = vattrp->va_uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   809
			privflags |= PRIV_SETUGID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   810
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   811
		if (vattrp->va_mode & VSGID) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   812
			gid = vattrp->va_gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   813
			privflags |= PRIV_SETUGID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   814
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   815
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   816
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   817
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   818
	 * Do we need to change our credential anyway?
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   819
	 * This is the case when E != I or P != I, as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   820
	 * we need to do the assignments (with F empty and A full)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   821
	 * Or when I is not a subset of L; in that case we need to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   822
	 * enforce L.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   823
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   824
	 *		I' = L & I
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   825
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   826
	 *		E' = P' = (I' + F) & A
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   827
	 * or
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   828
	 *		E' = P' = I'
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   829
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   830
	if (!priv_isequalset(&CR_EPRIV(cr), &CR_IPRIV(cr)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   831
	    !priv_issubset(&CR_IPRIV(cr), &CR_LPRIV(cr)) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   832
	    !priv_isequalset(&CR_PPRIV(cr), &CR_IPRIV(cr)))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   833
		privflags |= PRIV_RESET;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   834
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   835
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   836
	 * When we introduce the "forced" set then we will need
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   837
	 * to set PRIV_INCREASE here if I not a subset of P.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   838
	 * If the "allowed" set is introduced we will need to do
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   839
	 * a similar thing; however, it seems more reasonable to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   840
	 * have the allowed set reduce "L": script language interpreters
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   841
	 * would typically have an allowed set of "all".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   842
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   843
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   844
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   845
	 * Set setuid/setgid protections if no ptrace() compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   846
	 * For privileged processes, honor setuid/setgid even in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   847
	 * the presence of ptrace() compatibility.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   848
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   849
	if (((pp->p_proc_flag & P_PR_PTRACE) == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   850
	    PRIV_POLICY_ONLY(cr, PRIV_PROC_OWNER, (uid == 0))) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   851
	    (cr->cr_uid != uid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   852
	    cr->cr_gid != gid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   853
	    cr->cr_suid != uid ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   854
	    cr->cr_sgid != gid)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   855
		*uidp = uid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   856
		*gidp = gid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   857
		privflags |= PRIV_SETID;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   858
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   859
	return (privflags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   860
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   861
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   862
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   863
execpermissions(struct vnode *vp, struct vattr *vattrp, struct uarg *args)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   864
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   865
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   866
	proc_t *p = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   867
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   868
	vattrp->va_mask = AT_MODE | AT_UID | AT_GID | AT_SIZE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   869
	if (error = VOP_GETATTR(vp, vattrp, ATTR_EXEC, p->p_cred))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   870
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   871
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   872
	 * Check the access mode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   873
	 * If VPROC, ask /proc if the file is an object file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   874
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   875
	if ((error = VOP_ACCESS(vp, VEXEC, 0, p->p_cred)) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   876
	    !(vp->v_type == VREG || (vp->v_type == VPROC && pr_isobject(vp))) ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   877
	    (vp->v_vfsp->vfs_flag & VFS_NOEXEC) != 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   878
	    (vattrp->va_mode & (VEXEC|(VEXEC>>3)|(VEXEC>>6))) == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   879
		if (error == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   880
			error = EACCES;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   881
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   882
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   883
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   884
	if ((p->p_plist || (p->p_proc_flag & (P_PR_PTRACE|P_PR_TRACE))) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   885
	    (error = VOP_ACCESS(vp, VREAD, 0, p->p_cred))) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   886
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   887
		 * If process is under ptrace(2) compatibility,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   888
		 * fail the exec(2).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   889
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   890
		if (p->p_proc_flag & P_PR_PTRACE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   891
			goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   892
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   893
		 * Process is traced via /proc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   894
		 * Arrange to invalidate the /proc vnode.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   895
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   896
		args->traceinval = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   897
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   898
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   899
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   900
	if (error == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   901
		error = ENOEXEC;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   902
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   903
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   904
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   905
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   906
 * Map a section of an executable file into the user's
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   907
 * address space.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   908
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   909
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   910
execmap(struct vnode *vp, caddr_t addr, size_t len, size_t zfodlen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   911
    off_t offset, int prot, int page, uint_t szc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   912
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   913
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   914
	off_t oldoffset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   915
	caddr_t zfodbase, oldaddr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   916
	size_t end, oldlen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   917
	size_t zfoddiff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   918
	label_t ljb;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   919
	proc_t *p = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   920
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   921
	oldaddr = addr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   922
	addr = (caddr_t)((uintptr_t)addr & (uintptr_t)PAGEMASK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   923
	if (len) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   924
		oldlen = len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   925
		len += ((size_t)oldaddr - (size_t)addr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   926
		oldoffset = offset;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   927
		offset = (off_t)((uintptr_t)offset & PAGEMASK);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   928
		if (page) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   929
			spgcnt_t  prefltmem, availm, npages;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   930
			int preread;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   931
			uint_t mflag = MAP_PRIVATE | MAP_FIXED;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   932
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   933
			if ((prot & (PROT_WRITE | PROT_EXEC)) == PROT_EXEC) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   934
				mflag |= MAP_TEXT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   935
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   936
				mflag |= MAP_INITDATA;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   937
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   938
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   939
			if (valid_usr_range(addr, len, prot, p->p_as,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   940
			    p->p_as->a_userlimit) != RANGE_OKAY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   941
				error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   942
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   943
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   944
			if (error = VOP_MAP(vp, (offset_t)offset,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   945
			    p->p_as, &addr, len, prot, PROT_ALL,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   946
			    mflag, CRED()))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   947
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   948
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   949
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   950
			 * If the segment can fit, then we prefault
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   951
			 * the entire segment in.  This is based on the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   952
			 * model that says the best working set of a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   953
			 * small program is all of its pages.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   954
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   955
			npages = (spgcnt_t)btopr(len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   956
			prefltmem = freemem - desfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   957
			preread =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   958
			    (npages < prefltmem && len < PGTHRESH) ? 1 : 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   959
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   960
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   961
			 * If we aren't prefaulting the segment,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   962
			 * increment "deficit", if necessary to ensure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   963
			 * that pages will become available when this
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   964
			 * process starts executing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   965
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   966
			availm = freemem - lotsfree;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   967
			if (preread == 0 && npages > availm &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   968
			    deficit < lotsfree) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   969
				deficit += MIN((pgcnt_t)(npages - availm),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   970
				    lotsfree - deficit);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   971
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   972
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   973
			if (preread) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   974
				TRACE_2(TR_FAC_PROC, TR_EXECMAP_PREREAD,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   975
				    "execmap preread:freemem %d size %lu",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   976
				    freemem, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   977
				(void) as_fault(p->p_as->a_hat, p->p_as,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   978
				    (caddr_t)addr, len, F_INVAL, S_READ);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   979
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   980
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   981
			if (valid_usr_range(addr, len, prot, p->p_as,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   982
			    p->p_as->a_userlimit) != RANGE_OKAY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   983
				error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   984
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   985
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   986
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   987
			if (error = as_map(p->p_as, addr, len,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   988
			    segvn_create, zfod_argsp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   989
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   990
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   991
			 * Read in the segment in one big chunk.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   992
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   993
			if (error = vn_rdwr(UIO_READ, vp, (caddr_t)oldaddr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   994
			    oldlen, (offset_t)oldoffset, UIO_USERSPACE, 0,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   995
			    (rlim64_t)0, CRED(), (ssize_t *)0))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   996
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   997
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   998
			 * Now set protections.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   999
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1000
			if (prot != PROT_ZFOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1001
				(void) as_setprot(p->p_as, (caddr_t)addr,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1002
				    len, prot);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1003
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1004
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1005
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1006
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1007
	if (zfodlen) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1008
		end = (size_t)addr + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1009
		zfodbase = (caddr_t)roundup(end, PAGESIZE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1010
		zfoddiff = (uintptr_t)zfodbase - end;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1011
		if (zfoddiff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1012
			if (on_fault(&ljb)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1013
				no_fault();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1014
				error = EFAULT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1015
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1016
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1017
			uzero((void *)end, zfoddiff);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1018
			no_fault();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1019
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1020
		if (zfodlen > zfoddiff) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1021
			struct segvn_crargs crargs =
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1022
			    SEGVN_ZFOD_ARGS(PROT_ZFOD, PROT_ALL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1024
			zfodlen -= zfoddiff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1025
			if (valid_usr_range(zfodbase, zfodlen, prot, p->p_as,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1026
			    p->p_as->a_userlimit) != RANGE_OKAY) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1027
				error = ENOMEM;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1028
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1029
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1030
			crargs.szc = szc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1031
			if (error = as_map(p->p_as, (caddr_t)zfodbase,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1032
			    zfodlen, segvn_create, &crargs))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1033
				goto bad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1034
			if (prot != PROT_ZFOD) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1035
				(void) as_setprot(p->p_as, (caddr_t)zfodbase,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1036
				    zfodlen, prot);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1037
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1038
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1039
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1040
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1041
bad:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1042
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1043
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1044
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1045
void
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1046
setexecenv(struct execenv *ep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1047
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1048
	proc_t *p = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1049
	klwp_t *lwp = ttolwp(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1050
	struct vnode *vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1051
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1052
	p->p_bssbase = ep->ex_bssbase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1053
	p->p_brkbase = ep->ex_brkbase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1054
	p->p_brksize = ep->ex_brksize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1055
	if (p->p_exec)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1056
		VN_RELE(p->p_exec);	/* out with the old */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1057
	vp = p->p_exec = ep->ex_vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1058
	if (vp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1059
		VN_HOLD(vp);		/* in with the new */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1060
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1061
	lwp->lwp_sigaltstack.ss_sp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1062
	lwp->lwp_sigaltstack.ss_size = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1063
	lwp->lwp_sigaltstack.ss_flags = SS_DISABLE;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1064
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1065
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1066
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1067
execopen(struct vnode **vpp, int *fdp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1068
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1069
	struct vnode *vp = *vpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1070
	file_t *fp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1071
	int error = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1072
	int filemode = FREAD;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1073
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1074
	VN_HOLD(vp);		/* open reference */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1075
	if (error = falloc(NULL, filemode, &fp, fdp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1076
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1077
		*fdp = -1;	/* just in case falloc changed value */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1078
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1079
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1080
	if (error = VOP_OPEN(&vp, filemode, CRED())) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1081
		VN_RELE(vp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1082
		setf(*fdp, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1083
		unfalloc(fp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1084
		*fdp = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1085
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1086
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1087
	*vpp = vp;		/* vnode should not have changed */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1088
	fp->f_vnode = vp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1089
	mutex_exit(&fp->f_tlock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1090
	setf(*fdp, fp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1091
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1092
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1093
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1094
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1095
execclose(int fd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1096
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1097
	return (closeandsetf(fd, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1098
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1099
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1100
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1101
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1102
 * noexec stub function.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1104
/*ARGSUSED*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1105
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1106
noexec(
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1107
    struct vnode *vp,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1108
    struct execa *uap,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1109
    struct uarg *args,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1110
    struct intpdata *idatap,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1111
    int level,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1112
    long *execsz,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1113
    int setid,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1114
    caddr_t exec_file,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1115
    struct cred *cred)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1116
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1117
	cmn_err(CE_WARN, "missing exec capability for %s", uap->fname);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1118
	return (ENOEXEC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1119
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1120
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1121
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1122
 * Support routines for building a user stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1123
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1124
 * execve(path, argv, envp) must construct a new stack with the specified
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1125
 * arguments and environment variables (see exec_args() for a description
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1126
 * of the user stack layout).  To do this, we copy the arguments and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1127
 * environment variables from the old user address space into the kernel,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1128
 * free the old as, create the new as, and copy our buffered information
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1129
 * to the new stack.  Our kernel buffer has the following structure:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1130
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1131
 *	+-----------------------+ <--- stk_base + stk_size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1132
 *	| string offsets	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1133
 *	+-----------------------+ <--- stk_offp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1134
 *	|			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1135
 *	| STK_AVAIL() space	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1136
 *	|			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1137
 *	+-----------------------+ <--- stk_strp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1138
 *	| strings		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1139
 *	+-----------------------+ <--- stk_base
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1140
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1141
 * When we add a string, we store the string's contents (including the null
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1142
 * terminator) at stk_strp, and we store the offset of the string relative to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1143
 * stk_base at --stk_offp.  At strings are added, stk_strp increases and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1144
 * stk_offp decreases.  The amount of space remaining, STK_AVAIL(), is just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1145
 * the difference between these pointers.  If we run out of space, we return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1146
 * an error and exec_args() starts all over again with a buffer twice as large.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1147
 * When we're all done, the kernel buffer looks like this:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1148
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1149
 *	+-----------------------+ <--- stk_base + stk_size
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1150
 *	| argv[0] offset	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1151
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1152
 *	| ...			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1153
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1154
 *	| argv[argc-1] offset	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1155
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1156
 *	| envp[0] offset	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1157
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1158
 *	| ...			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1159
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1160
 *	| envp[envc-1] offset	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1161
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1162
 *	| AT_SUN_PLATFORM offset|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1163
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1164
 *	| AT_SUN_EXECNAME offset|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1165
 *	+-----------------------+ <--- stk_offp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1166
 *	|			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1167
 *	| STK_AVAIL() space	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1168
 *	|			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1169
 *	+-----------------------+ <--- stk_strp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1170
 *	| AT_SUN_EXECNAME offset|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1171
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1172
 *	| AT_SUN_PLATFORM offset|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1173
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1174
 *	| envp[envc-1] string	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1175
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1176
 *	| ...			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1177
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1178
 *	| envp[0] string	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1179
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1180
 *	| argv[argc-1] string	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1181
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1182
 *	| ...			|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1183
 *	+-----------------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1184
 *	| argv[0] string	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1185
 *	+-----------------------+ <--- stk_base
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1186
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1188
#define	STK_AVAIL(args)		((char *)(args)->stk_offp - (args)->stk_strp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1190
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1191
 * Add a string to the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1192
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1193
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1194
stk_add(uarg_t *args, const char *sp, enum uio_seg segflg)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1195
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1196
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1197
	size_t len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1198
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1199
	if (STK_AVAIL(args) < sizeof (int))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1200
		return (E2BIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1201
	*--args->stk_offp = args->stk_strp - args->stk_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1202
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1203
	if (segflg == UIO_USERSPACE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1204
		error = copyinstr(sp, args->stk_strp, STK_AVAIL(args), &len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1205
		if (error != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1206
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1207
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1208
		len = strlen(sp) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1209
		if (len > STK_AVAIL(args))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1210
			return (E2BIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1211
		bcopy(sp, args->stk_strp, len);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1212
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1214
	args->stk_strp += len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1216
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1217
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1218
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1219
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1220
stk_getptr(uarg_t *args, char *src, char **dst)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1221
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1222
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1223
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1224
	if (args->from_model == DATAMODEL_NATIVE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1225
		ulong_t ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1226
		error = fulword(src, &ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1227
		*dst = (caddr_t)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1228
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1229
		uint32_t ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1230
		error = fuword32(src, &ptr);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1231
		*dst = (caddr_t)(uintptr_t)ptr;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1232
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1233
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1234
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1235
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1236
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1237
stk_putptr(uarg_t *args, char *addr, char *value)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1238
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1239
	if (args->to_model == DATAMODEL_NATIVE)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1240
		return (sulword(addr, (ulong_t)value));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1241
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1242
		return (suword32(addr, (uint32_t)(uintptr_t)value));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1243
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1244
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1245
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1246
stk_copyin(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1247
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1248
	char *sp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1249
	int argc, error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1250
	int argv_empty = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1251
	size_t ptrsize = args->from_ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1252
	size_t size, pad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1253
	char *argv = (char *)uap->argp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1254
	char *envp = (char *)uap->envp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1255
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1256
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1257
	 * Copy interpreter's name and argument to argv[0] and argv[1].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1258
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1259
	if (intp != NULL && intp->intp_name != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1260
		if ((error = stk_add(args, intp->intp_name, UIO_SYSSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1261
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1262
		if (intp->intp_arg != NULL &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1263
		    (error = stk_add(args, intp->intp_arg, UIO_SYSSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1264
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1265
		if (args->fname != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1266
			error = stk_add(args, args->fname, UIO_SYSSPACE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1267
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1268
			error = stk_add(args, uap->fname, UIO_USERSPACE);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1269
		if (error)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1270
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1271
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1272
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1273
		 * Check for an empty argv[].
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1274
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1275
		if (stk_getptr(args, argv, &sp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1276
			return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1277
		if (sp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1278
			argv_empty = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1279
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1280
		argv += ptrsize;		/* ignore original argv[0] */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1281
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1282
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1283
	if (argv_empty == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1284
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1285
		 * Add argv[] strings to the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1286
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1287
		for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1288
			if (stk_getptr(args, argv, &sp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1289
				return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1290
			if (sp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1291
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1292
			if ((error = stk_add(args, sp, UIO_USERSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1293
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1294
			argv += ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1295
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1296
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1297
	argc = (int *)(args->stk_base + args->stk_size) - args->stk_offp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1298
	args->arglen = args->stk_strp - args->stk_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1299
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1300
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1301
	 * Add environ[] strings to the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1302
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1303
	if (envp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1304
		for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1305
			if (stk_getptr(args, envp, &sp))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1306
				return (EFAULT);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1307
			if (sp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1308
				break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1309
			if ((error = stk_add(args, sp, UIO_USERSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1310
				return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1311
			envp += ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1312
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1313
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1314
	args->na = (int *)(args->stk_base + args->stk_size) - args->stk_offp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1315
	args->ne = args->na - argc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1316
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1317
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1318
	 * Add AT_SUN_PLATFORM and AT_SUN_EXECNAME strings to the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1319
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1320
	if (auxvpp != NULL && *auxvpp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1321
		if ((error = stk_add(args, platform, UIO_SYSSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1322
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1323
		if ((error = stk_add(args, args->pathname, UIO_SYSSPACE)) != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1324
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1325
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1326
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1327
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1328
	 * Compute the size of the stack.  This includes all the pointers,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1329
	 * the space reserved for the aux vector, and all the strings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1330
	 * The total number of pointers is args->na (which is argc + envc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1331
	 * plus 4 more: (1) a pointer's worth of space for argc; (2) the NULL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1332
	 * after the last argument (i.e. argv[argc]); (3) the NULL after the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1333
	 * last environment variable (i.e. envp[envc]); and (4) the NULL after
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1334
	 * all the strings, at the very top of the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1335
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1336
	size = (args->na + 4) * args->to_ptrsize + args->auxsize +
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1337
	    (args->stk_strp - args->stk_base);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1339
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1340
	 * Pad the string section with zeroes to align the stack size.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1341
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1342
	pad = P2NPHASE(size, args->stk_align);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1343
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1344
	if (STK_AVAIL(args) < pad)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1345
		return (E2BIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1346
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1347
	args->usrstack_size = size + pad;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1348
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1349
	while (pad-- != 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1350
		*args->stk_strp++ = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1351
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1352
	args->nc = args->stk_strp - args->stk_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1353
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1354
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1355
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1356
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1357
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1358
stk_copyout(uarg_t *args, char *usrstack, void **auxvpp, user_t *up)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1359
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1360
	size_t ptrsize = args->to_ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1361
	ssize_t pslen;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1362
	char *kstrp = args->stk_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1363
	char *ustrp = usrstack - args->nc - ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1364
	char *usp = usrstack - args->usrstack_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1365
	int *offp = (int *)(args->stk_base + args->stk_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1366
	int envc = args->ne;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1367
	int argc = args->na - envc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1368
	int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1369
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1370
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1371
	 * Record argc for /proc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1372
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1373
	up->u_argc = argc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1374
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1375
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1376
	 * Put argc on the stack.  Note that even though it's an int,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1377
	 * it always consumes ptrsize bytes (for alignment).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1378
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1379
	if (stk_putptr(args, usp, (char *)(uintptr_t)argc))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1380
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1381
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1382
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1383
	 * Add argc space (ptrsize) to usp and record argv for /proc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1384
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1385
	up->u_argv = (uintptr_t)(usp += ptrsize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1386
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1387
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1388
	 * Put the argv[] pointers on the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1389
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1390
	for (i = 0; i < argc; i++, usp += ptrsize)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1391
		if (stk_putptr(args, usp, &ustrp[*--offp]))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1392
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1393
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1394
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1395
	 * Copy arguments to u_psargs.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1396
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1397
	pslen = MIN(args->arglen, PSARGSZ) - 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1398
	for (i = 0; i < pslen; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1399
		up->u_psargs[i] = (kstrp[i] == '\0' ? ' ' : kstrp[i]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1400
	while (i < PSARGSZ)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1401
		up->u_psargs[i++] = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1402
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1403
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1404
	 * Add space for argv[]'s NULL terminator (ptrsize) to usp and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1405
	 * record envp for /proc.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1406
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1407
	up->u_envp = (uintptr_t)(usp += ptrsize);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1408
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1409
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1410
	 * Put the envp[] pointers on the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1411
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1412
	for (i = 0; i < envc; i++, usp += ptrsize)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1413
		if (stk_putptr(args, usp, &ustrp[*--offp]))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1414
			return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1415
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1416
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1417
	 * Add space for envp[]'s NULL terminator (ptrsize) to usp and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1418
	 * remember where the stack ends, which is also where auxv begins.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1419
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1420
	args->stackend = usp += ptrsize;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1421
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1422
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1423
	 * Put all the argv[], envp[], and auxv strings on the stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1424
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1425
	if (copyout(args->stk_base, ustrp, args->nc))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1426
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1427
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1428
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1429
	 * Fill in the aux vector now that we know the user stack addresses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1430
	 * for the AT_SUN_PLATFORM and AT_SUN_EXECNAME strings.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1431
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1432
	if (auxvpp != NULL && *auxvpp != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1433
		if (args->to_model == DATAMODEL_NATIVE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1434
			auxv_t **a = (auxv_t **)auxvpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1435
			ADDAUX(*a, AT_SUN_PLATFORM, (long)&ustrp[*--offp])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1436
			ADDAUX(*a, AT_SUN_EXECNAME, (long)&ustrp[*--offp])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1437
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1438
			auxv32_t **a = (auxv32_t **)auxvpp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1439
			ADDAUX(*a,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1440
			    AT_SUN_PLATFORM, (int)(uintptr_t)&ustrp[*--offp])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1441
			ADDAUX(*a,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1442
			    AT_SUN_EXECNAME, (int)(uintptr_t)&ustrp[*--offp]);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1443
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1444
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1445
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1446
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1447
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1448
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1449
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1450
int mpss_brkpgszsel = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1451
int mpss_stkpgszsel = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1452
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1453
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1454
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1455
 * Initialize a new user stack with the specified arguments and environment.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1456
 * The initial user stack layout is as follows:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1457
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1458
 *	User Stack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1459
 *	+---------------+ <--- curproc->p_usrstack
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1460
 *	| NULL		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1461
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1462
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1463
 *	| auxv strings	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1464
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1465
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1466
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1467
 *	| envp strings	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1468
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1469
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1470
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1471
 *	| argv strings	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1472
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1473
 *	+---------------+ <--- ustrp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1474
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1475
 *	| aux vector	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1476
 *	|		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1477
 *	+---------------+ <--- auxv
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1478
 *	| NULL		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1479
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1480
 *	| envp[envc-1]	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1481
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1482
 *	| ...		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1483
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1484
 *	| envp[0]	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1485
 *	+---------------+ <--- envp[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1486
 *	| NULL		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1487
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1488
 *	| argv[argc-1]	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1489
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1490
 *	| ...		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1491
 *	+---------------+
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1492
 *	| argv[0]	|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1493
 *	+---------------+ <--- argv[]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1494
 *	| argc		|
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1495
 *	+---------------+ <--- stack base
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1496
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1497
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1498
exec_args(execa_t *uap, uarg_t *args, intpdata_t *intp, void **auxvpp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1499
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1500
	size_t size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1501
	int error;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1502
	proc_t *p = ttoproc(curthread);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1503
	user_t *up = PTOU(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1504
	char *usrstack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1505
	rctl_entity_p_t e;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1506
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1507
	struct as *as;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1508
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1509
	args->from_model = p->p_model;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1510
	if (p->p_model == DATAMODEL_NATIVE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1511
		args->from_ptrsize = sizeof (long);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1512
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1513
		args->from_ptrsize = sizeof (int32_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1514
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1516
	if (args->to_model == DATAMODEL_NATIVE) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1517
		args->to_ptrsize = sizeof (long);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1518
		args->ncargs = NCARGS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1519
		args->stk_align = STACK_ALIGN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1520
		usrstack = (char *)USRSTACK;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1521
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1522
		args->to_ptrsize = sizeof (int32_t);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1523
		args->ncargs = NCARGS32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1524
		args->stk_align = STACK_ALIGN32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1525
		usrstack = (char *)USRSTACK32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1526
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1527
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1528
	ASSERT(P2PHASE((uintptr_t)usrstack, args->stk_align) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1529
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1530
#if defined(__sparc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1531
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1532
	 * Make sure user register windows are empty before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1533
	 * attempting to make a new stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1534
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1535
	(void) flush_user_windows_to_stack(NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1536
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1537
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1538
	for (size = PAGESIZE; ; size *= 2) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1539
		args->stk_size = size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1540
		args->stk_base = kmem_alloc(size, KM_SLEEP);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1541
		args->stk_strp = args->stk_base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1542
		args->stk_offp = (int *)(args->stk_base + size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1543
		error = stk_copyin(uap, args, intp, auxvpp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1544
		if (error == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1545
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1546
		kmem_free(args->stk_base, size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1547
		if (error != E2BIG && error != ENAMETOOLONG)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1548
			return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1549
		if (size >= args->ncargs)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1550
			return (E2BIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1551
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1552
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1553
	size = args->usrstack_size;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1554
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1555
	ASSERT(error == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1556
	ASSERT(P2PHASE(size, args->stk_align) == 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1557
	ASSERT((ssize_t)STK_AVAIL(args) >= 0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1558
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1559
	if (size > args->ncargs) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1560
		kmem_free(args->stk_base, args->stk_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1561
		return (E2BIG);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1562
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1563
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1564
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1565
	 * Leave only the current lwp and force the other lwps to exit.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1566
	 * If another lwp beat us to the punch by calling exit(), bail out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1567
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1568
	if ((error = exitlwps(0)) != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1569
		kmem_free(args->stk_base, args->stk_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1570
		return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1571
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1572
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1573
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1574
	 * Revoke any doors created by the process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1575
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1576
	if (p->p_door_list)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1577
		door_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1578
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1579
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1580
	 * Release schedctl data structures.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1581
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1582
	if (p->p_pagep)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1583
		schedctl_proc_cleanup();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1584
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1585
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1586
	 * Clean up any DTrace helpers for the process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1587
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1588
	if (p->p_dtrace_helpers != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1589
		ASSERT(dtrace_helpers_cleanup != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1590
		(*dtrace_helpers_cleanup)();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1591
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1592
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1593
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1594
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1595
	 * Cleanup the DTrace provider associated with this process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1596
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1597
	if (p->p_dtrace_probes) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1598
		ASSERT(dtrace_fasttrap_exec_ptr != NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1599
		dtrace_fasttrap_exec_ptr(p);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1600
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1601
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1602
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1603
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1604
	 * discard the lwpchan cache.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1605
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1606
	if (p->p_lcp != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1607
		lwpchan_destroy_cache(1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1608
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1609
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1610
	 * Delete the POSIX timers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1611
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1612
	if (p->p_itimer != NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1613
		timer_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1614
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1615
#ifdef C2_AUDIT
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1616
	if (audit_active)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1617
		audit_exec(args->stk_base, args->stk_base + args->arglen,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1618
		    args->na - args->ne, args->ne);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1619
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1620
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1621
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1622
	 * Ensure that we don't change resource associations while we
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1623
	 * change address spaces.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1624
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1625
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1626
	pool_barrier_enter();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1627
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1628
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1629
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1630
	 * Destroy the old address space and create a new one.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1631
	 * From here on, any errors are fatal to the exec()ing process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1632
	 * On error we return -1, which means the caller must SIGKILL
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1633
	 * the process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1634
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1635
	relvm();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1636
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1637
	mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1638
	pool_barrier_exit();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1639
	mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1640
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1641
	up->u_execsw = args->execswp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1642
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1643
	p->p_brkbase = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1644
	p->p_brksize = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1645
	p->p_stksize = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1646
	p->p_model = args->to_model;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1647
	p->p_usrstack = usrstack;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1648
	p->p_stkprot = args->stk_prot;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1649
	p->p_datprot = args->dat_prot;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1650
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1651
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1652
	 * Reset resource controls such that all controls are again active as
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1653
	 * well as appropriate to the potentially new address model for the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1654
	 * process.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1655
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1656
	e.rcep_p.proc = p;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1657
	e.rcep_t = RCENTITY_PROCESS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1658
	rctl_set_reset(p->p_rctls, p, &e);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1659
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1660
	if (exec_lpg_disable == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1661
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1662
		uint_t pgsizes = page_num_pagesizes();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1663
		uint_t szc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1664
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1665
		p->p_brkpageszc = args->brkpageszc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1666
		p->p_stkpageszc = args->stkpageszc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1667
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1668
		if (p->p_brkpageszc == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1669
			p->p_brkpageszc = page_szc(map_pgsz(MAPPGSZ_HEAP,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1670
			    p, 0, 0, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1671
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1672
		if (p->p_stkpageszc == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1673
			p->p_stkpageszc = page_szc(map_pgsz(MAPPGSZ_STK,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1674
			    p, 0, 0, NULL));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1675
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1676
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1677
#ifdef DEBUG
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1678
		if (mpss_brkpgszsel != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1679
			if (mpss_brkpgszsel == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1680
				szc = ((uint_t)gethrtime() >> 8) % pgsizes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1681
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1682
				szc = mpss_brkpgszsel % pgsizes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1683
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1684
			p->p_brkpageszc = szc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1685
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1686
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1687
		if (mpss_stkpgszsel != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1688
			if (mpss_stkpgszsel == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1689
				szc = ((uint_t)gethrtime() >> 7) % pgsizes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1690
			} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1691
				szc = mpss_stkpgszsel % pgsizes;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1692
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1693
			p->p_stkpageszc = szc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1694
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1695
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1696
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1697
		mutex_enter(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1698
		p->p_flag |= SAUTOLPG;	/* kernel controls page sizes */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1699
		mutex_exit(&p->p_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1700
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1701
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1702
		p->p_brkpageszc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1703
		p->p_stkpageszc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1704
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1705
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1706
	exec_set_sp(size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1707
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1708
	as = as_alloc();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1709
	p->p_as = as;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1710
	if (p->p_model == DATAMODEL_ILP32)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1711
		as->a_userlimit = (caddr_t)USERLIMIT32;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1712
	(void) hat_setup(as->a_hat, HAT_ALLOC);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1713
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1714
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1715
	 * Finally, write out the contents of the new stack.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1716
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1717
	error = stk_copyout(args, usrstack, auxvpp, up);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1718
	kmem_free(args->stk_base, args->stk_size);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1719
	return (error);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
  1720
}