3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1988 AT&T */
27 /* All Rights Reserved */
28 /*
29 * Copyright 2014, Joyent, Inc. All rights reserved.
30 */
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/sysmacros.h>
35 #include <sys/systm.h>
36 #include <sys/signal.h>
37 #include <sys/cred_impl.h>
38 #include <sys/policy.h>
39 #include <sys/user.h>
40 #include <sys/errno.h>
41 #include <sys/file.h>
42 #include <sys/vfs.h>
81 #define PRIV_RESET 0x01 /* needs to reset privs */
82 #define PRIV_SETID 0x02 /* needs to change uids */
83 #define PRIV_SETUGID 0x04 /* is setuid/setgid/forced privs */
84 #define PRIV_INCREASE 0x08 /* child runs with more privs */
85 #define MAC_FLAGS 0x10 /* need to adjust MAC flags */
86 #define PRIV_FORCED 0x20 /* has forced privileges */
87
88 static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *,
89 priv_set_t *, cred_t *, const char *);
90 static int hold_execsw(struct execsw *);
91
92 uint_t auxv_hwcap = 0; /* auxv AT_SUN_HWCAP value; determined on the fly */
93 uint_t auxv_hwcap_2 = 0; /* AT_SUN_HWCAP2 */
94 #if defined(_SYSCALL32_IMPL)
95 uint_t auxv_hwcap32 = 0; /* 32-bit version of auxv_hwcap */
96 uint_t auxv_hwcap32_2 = 0; /* 32-bit version of auxv_hwcap2 */
97 #endif
98
99 #define PSUIDFLAGS (SNOCD|SUGID)
100
101 /*
102 * exece() - system call wrapper around exec_common()
103 */
104 int
105 exece(const char *fname, const char **argp, const char **envp)
106 {
107 int error;
108
109 error = exec_common(fname, argp, envp, EBA_NONE);
110 return (error ? (set_errno(error)) : 0);
111 }
112
113 int
114 exec_common(const char *fname, const char **argp, const char **envp,
115 int brand_action)
116 {
117 vnode_t *vp = NULL, *dir = NULL, *tmpvp = NULL;
118 proc_t *p = ttoproc(curthread);
119 klwp_t *lwp = ttolwp(curthread);
120 struct user *up = PTOU(p);
181 mutex_enter(&p->p_lock);
182 prexecstart();
183 schedctl_finish_sigblock(curthread);
184 savedmask = curthread->t_hold;
185 sigorset(&curthread->t_hold, &ignoredefault);
186 mutex_exit(&p->p_lock);
187
188 /*
189 * Look up path name and remember last component for later.
190 * To help coreadm expand its %d token, we attempt to save
191 * the directory containing the executable in p_execdir. The
192 * first call to lookuppn() may fail and return EINVAL because
193 * dirvpp is non-NULL. In that case, we make a second call to
194 * lookuppn() with dirvpp set to NULL; p_execdir will be NULL,
195 * but coreadm is allowed to expand %d to the empty string and
196 * there are other cases in which that failure may occur.
197 */
198 if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
199 goto out;
200 pn_alloc(&resolvepn);
201 if ((error = lookuppn(&pn, &resolvepn, FOLLOW, &dir, &vp)) != 0) {
202 pn_free(&resolvepn);
203 pn_free(&pn);
204 if (error != EINVAL)
205 goto out;
206
207 dir = NULL;
208 if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
209 goto out;
210 pn_alloc(&resolvepn);
211 if ((error = lookuppn(&pn, &resolvepn, FOLLOW, NULLVPP,
212 &vp)) != 0) {
213 pn_free(&resolvepn);
214 pn_free(&pn);
215 goto out;
216 }
217 }
218 if (vp == NULL) {
219 if (dir != NULL)
220 VN_RELE(dir);
221 error = ENOENT;
|
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2015 Garrett D'Amore <garrett@damore.org>
24 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29 /*
30 * Copyright 2014, Joyent, Inc. All rights reserved.
31 */
32
33 #include <sys/types.h>
34 #include <sys/param.h>
35 #include <sys/sysmacros.h>
36 #include <sys/systm.h>
37 #include <sys/signal.h>
38 #include <sys/cred_impl.h>
39 #include <sys/policy.h>
40 #include <sys/user.h>
41 #include <sys/errno.h>
42 #include <sys/file.h>
43 #include <sys/vfs.h>
82 #define PRIV_RESET 0x01 /* needs to reset privs */
83 #define PRIV_SETID 0x02 /* needs to change uids */
84 #define PRIV_SETUGID 0x04 /* is setuid/setgid/forced privs */
85 #define PRIV_INCREASE 0x08 /* child runs with more privs */
86 #define MAC_FLAGS 0x10 /* need to adjust MAC flags */
87 #define PRIV_FORCED 0x20 /* has forced privileges */
88
89 static int execsetid(struct vnode *, struct vattr *, uid_t *, uid_t *,
90 priv_set_t *, cred_t *, const char *);
91 static int hold_execsw(struct execsw *);
92
93 uint_t auxv_hwcap = 0; /* auxv AT_SUN_HWCAP value; determined on the fly */
94 uint_t auxv_hwcap_2 = 0; /* AT_SUN_HWCAP2 */
95 #if defined(_SYSCALL32_IMPL)
96 uint_t auxv_hwcap32 = 0; /* 32-bit version of auxv_hwcap */
97 uint_t auxv_hwcap32_2 = 0; /* 32-bit version of auxv_hwcap2 */
98 #endif
99
100 #define PSUIDFLAGS (SNOCD|SUGID)
101
102 #define DEVFD "/dev/fd/"
103
104 /*
105 * exece() - system call wrapper around exec_common()
106 */
107 int
108 exece(const char *fname, const char **argp, const char **envp)
109 {
110 int error;
111
112 error = exec_common(fname, argp, envp, EBA_NONE);
113 return (error ? (set_errno(error)) : 0);
114 }
115
116 int
117 exec_common(const char *fname, const char **argp, const char **envp,
118 int brand_action)
119 {
120 vnode_t *vp = NULL, *dir = NULL, *tmpvp = NULL;
121 proc_t *p = ttoproc(curthread);
122 klwp_t *lwp = ttolwp(curthread);
123 struct user *up = PTOU(p);
184 mutex_enter(&p->p_lock);
185 prexecstart();
186 schedctl_finish_sigblock(curthread);
187 savedmask = curthread->t_hold;
188 sigorset(&curthread->t_hold, &ignoredefault);
189 mutex_exit(&p->p_lock);
190
191 /*
192 * Look up path name and remember last component for later.
193 * To help coreadm expand its %d token, we attempt to save
194 * the directory containing the executable in p_execdir. The
195 * first call to lookuppn() may fail and return EINVAL because
196 * dirvpp is non-NULL. In that case, we make a second call to
197 * lookuppn() with dirvpp set to NULL; p_execdir will be NULL,
198 * but coreadm is allowed to expand %d to the empty string and
199 * there are other cases in which that failure may occur.
200 */
201 if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
202 goto out;
203 pn_alloc(&resolvepn);
204
205 if (strncmp(pn.pn_path, DEVFD, strlen(DEVFD)) == 0) {
206 /* looks like a /dev/fd node */
207 char *p = pn.pn_path + strlen(DEVFD);
208 int fd = stoi(&p);
209 if ((fd < 0) || (*p != 0) || (p == pn.pn_path)) {
210 error = EBADF;
211 goto out;
212 }
213 if ((error = fgetstartvp(fd, NULL, &vp)) != 0) {
214 goto out; /* error will be EBADF */
215 }
216 (void) pn_set(&resolvepn, pn.pn_path);
217
218 } else if ((error =
219 lookuppn(&pn, &resolvepn, FOLLOW, &dir, &vp)) != 0) {
220 pn_free(&resolvepn);
221 pn_free(&pn);
222 if (error != EINVAL)
223 goto out;
224
225 dir = NULL;
226 if ((error = pn_get((char *)fname, UIO_USERSPACE, &pn)) != 0)
227 goto out;
228 pn_alloc(&resolvepn);
229 if ((error = lookuppn(&pn, &resolvepn, FOLLOW, NULLVPP,
230 &vp)) != 0) {
231 pn_free(&resolvepn);
232 pn_free(&pn);
233 goto out;
234 }
235 }
236 if (vp == NULL) {
237 if (dir != NULL)
238 VN_RELE(dir);
239 error = ENOENT;
|