1e71ca95cSGerald Jelinek /*
2e71ca95cSGerald Jelinek  * CDDL HEADER START
3e71ca95cSGerald Jelinek  *
4e71ca95cSGerald Jelinek  * The contents of this file are subject to the terms of the
5e71ca95cSGerald Jelinek  * Common Development and Distribution License (the "License").
6e71ca95cSGerald Jelinek  * You may not use this file except in compliance with the License.
7e71ca95cSGerald Jelinek  *
8e71ca95cSGerald Jelinek  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e71ca95cSGerald Jelinek  * or http://www.opensolaris.org/os/licensing.
10e71ca95cSGerald Jelinek  * See the License for the specific language governing permissions
11e71ca95cSGerald Jelinek  * and limitations under the License.
12e71ca95cSGerald Jelinek  *
13e71ca95cSGerald Jelinek  * When distributing Covered Code, include this CDDL HEADER in each
14e71ca95cSGerald Jelinek  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15e71ca95cSGerald Jelinek  * If applicable, add the following below this CDDL HEADER, with the
16e71ca95cSGerald Jelinek  * fields enclosed by brackets "[]" replaced with your own identifying
17e71ca95cSGerald Jelinek  * information: Portions Copyright [yyyy] [name of copyright owner]
18e71ca95cSGerald Jelinek  *
19e71ca95cSGerald Jelinek  * CDDL HEADER END
20e71ca95cSGerald Jelinek  */
218fd04b83SRoger A. Faulkner 
22e71ca95cSGerald Jelinek /*
23406fc510SToomas Soome  * Copyright 2016 Toomas Soome <tsoome@me.com>
24b49b27dcSTheo Schlossnagle  * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
2580e2ca85S  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
26e71ca95cSGerald Jelinek  */
27e71ca95cSGerald Jelinek 
28e71ca95cSGerald Jelinek #include <errno.h>
29e71ca95cSGerald Jelinek #include <fcntl.h>
308b4cf837Sjv #include <dirent.h>
318b4cf837Sjv #include <stddef.h>
32e71ca95cSGerald Jelinek #include <stdio.h>
33e71ca95cSGerald Jelinek #include <stdlib.h>
34e71ca95cSGerald Jelinek #include <strings.h>
35e71ca95cSGerald Jelinek #include <unistd.h>
36e71ca95cSGerald Jelinek #include <thread.h>
37e71ca95cSGerald Jelinek #include <sys/auxv.h>
38e71ca95cSGerald Jelinek #include <sys/brand.h>
39e71ca95cSGerald Jelinek #include <sys/inttypes.h>
40e71ca95cSGerald Jelinek #include <sys/lwp.h>
41e71ca95cSGerald Jelinek #include <sys/syscall.h>
42e71ca95cSGerald Jelinek #include <sys/systm.h>
43e71ca95cSGerald Jelinek #include <sys/utsname.h>
44bdf0047cSRoger A. Faulkner #include <sys/sysconfig.h>
45e71ca95cSGerald Jelinek #include <sys/systeminfo.h>
46e71ca95cSGerald Jelinek #include <sys/zone.h>
47e71ca95cSGerald Jelinek #include <sys/stat.h>
48e71ca95cSGerald Jelinek #include <sys/mntent.h>
49e71ca95cSGerald Jelinek #include <sys/ctfs.h>
50e71ca95cSGerald Jelinek #include <sys/priv.h>
51e71ca95cSGerald Jelinek #include <sys/acctctl.h>
52e71ca95cSGerald Jelinek #include <libgen.h>
53e71ca95cSGerald Jelinek #include <bsm/audit.h>
54e71ca95cSGerald Jelinek #include <sys/crypto/ioctl.h>
55e71ca95cSGerald Jelinek #include <sys/fs/zfs.h>
56e71ca95cSGerald Jelinek #include <sys/zfs_ioctl.h>
57e71ca95cSGerald Jelinek #include <sys/ucontext.h>
58835ee219SRobert Harris #include <sys/mntio.h>
59835ee219SRobert Harris #include <sys/mnttab.h>
608b4cf837Sjv #include <sys/attr.h>
610fbb751dSJohn Levon #include <sys/lofi.h>
62835ee219SRobert Harris #include <atomic.h>
63f3f1e74cS #include <sys/acl.h>
64b49b27dcSTheo Schlossnagle #include <sys/socket.h>
65e71ca95cSGerald Jelinek 
66e71ca95cSGerald Jelinek #include <s10_brand.h>
6780e2ca85S #include <brand_misc.h>
68e71ca95cSGerald Jelinek #include <s10_misc.h>
69bdf0047cSRoger A. Faulkner #include <s10_signal.h>
70e71ca95cSGerald Jelinek 
71e71ca95cSGerald Jelinek /*
7280e2ca85S  * See usr/src/lib/brand/shared/brand/common/brand_util.c for general
7380e2ca85S  * emulation notes.
74e71ca95cSGerald Jelinek  */
75e71ca95cSGerald Jelinek 
76e71ca95cSGerald Jelinek static zoneid_t zoneid;
77e71ca95cSGerald Jelinek static boolean_t emul_global_zone = B_FALSE;
78ad601a05Sjv static s10_emul_bitmap_t emul_bitmap;
79e71ca95cSGerald Jelinek pid_t zone_init_pid;
80e71ca95cSGerald Jelinek 
81ad601a05Sjv /*
82ad601a05Sjv  * S10_FEATURE_IS_PRESENT is a macro that helps facilitate conditional
83ad601a05Sjv  * emulation.  For each constant N defined in the s10_emulated_features
84ad601a05Sjv  * enumeration in usr/src/uts/common/brand/solaris10/s10_brand.h,
85ad601a05Sjv  * S10_FEATURE_IS_PRESENT(N) is true iff the feature/backport represented by N
86ad601a05Sjv  * is present in the Solaris 10 image hosted within the zone.  In other words,
87ad601a05Sjv  * S10_FEATURE_IS_PRESENT(N) is true iff the file /usr/lib/brand/solaris10/M,
88ad601a05Sjv  * where M is the enum value of N, was present in the zone when the zone booted.
89ad601a05Sjv  *
90ad601a05Sjv  *
91ad601a05Sjv  * *** Sample Usage
92ad601a05Sjv  *
93ad601a05Sjv  * Suppose that you need to backport a fix to Solaris 10 and there is
94ad601a05Sjv  * emulation in place for the fix.  Suppose further that the emulation won't be
95ad601a05Sjv  * needed if the fix is backported (i.e., if the fix is present in the hosted
96ad601a05Sjv  * Solaris 10 environment, then the brand won't need the emulation).  Then if
97ad601a05Sjv  * you add a constant named "S10_FEATURE_X" to the end of the
98ad601a05Sjv  * s10_emulated_features enumeration that represents the backported fix and
99ad601a05Sjv  * S10_FEATURE_X evaluates to four, then you should create a file named
100ad601a05Sjv  * /usr/lib/brand/solaris10/4 as part of your backport.  Additionally, you
101ad601a05Sjv  * should retain the aforementioned emulation but modify it so that it's
102ad601a05Sjv  * performed only when S10_FEATURE_IS_PRESENT(S10_FEATURE_X) is false.  Thus the
103ad601a05Sjv  * emulation function should look something like the following:
104ad601a05Sjv  *
105ad601a05Sjv  *	static int
106ad601a05Sjv  *	my_emul_function(sysret_t *rv, ...)
107ad601a05Sjv  *	{
108ad601a05Sjv  *		if (S10_FEATURE_IS_PRESENT(S10_FEATURE_X)) {
109ad601a05Sjv  *			// Don't emulate
110ad601a05Sjv  *			return (__systemcall(rv, ...));
111ad601a05Sjv  *		} else {
112ad601a05Sjv  *			// Emulate whatever needs to be emulated when the
113ad601a05Sjv  *			// backport isn't present in the Solaris 10 image.
114ad601a05Sjv  *		}
115ad601a05Sjv  *	}
116ad601a05Sjv  */
117ad601a05Sjv #define	S10_FEATURE_IS_PRESENT(s10_emulated_features_constant)	\
118ad601a05Sjv 	((emul_bitmap[(s10_emulated_features_constant) >> 3] &	\
119ad601a05Sjv 	(1 << ((s10_emulated_features_constant) & 0x7))) != 0)
120ad601a05Sjv 
12180e2ca85S brand_sysent_table_t brand_sysent_table[];
122e71ca95cSGerald Jelinek 
123e71ca95cSGerald Jelinek #define	S10_UTS_RELEASE	"5.10"
124e71ca95cSGerald Jelinek #define	S10_UTS_VERSION	"Generic_Virtual"
125e71ca95cSGerald Jelinek 
1260fbb751dSJohn Levon /*
1270fbb751dSJohn Levon  * If the ioctl fd's major doesn't match "major", then pass through the
1280fbb751dSJohn Levon  * ioctl, since it is not the expected device.  major should be a
1290fbb751dSJohn Levon  * pointer to a static dev_t initialized to -1, and devname should be
1300fbb751dSJohn Levon  * the path of the device.
1310fbb751dSJohn Levon  *
1320fbb751dSJohn Levon  * Returns 1 if the ioctl was handled (in which case *err contains the
1330fbb751dSJohn Levon  * error code), or 0 if it still needs handling.
1340fbb751dSJohn Levon  */
1350fbb751dSJohn Levon static int
passthru_otherdev_ioctl(dev_t * majordev,const char * devname,int * err,sysret_t * rval,int fdes,int cmd,intptr_t arg)1360fbb751dSJohn Levon passthru_otherdev_ioctl(dev_t *majordev, const char *devname, int *err,
1370fbb751dSJohn Levon     sysret_t *rval, int fdes, int cmd, intptr_t arg)
1380fbb751dSJohn Levon {
1390fbb751dSJohn Levon 	struct stat sbuf;
1400fbb751dSJohn Levon 
1410fbb751dSJohn Levon 	if (*majordev == (dev_t)-1) {
1420fbb751dSJohn Levon 		if ((*err = __systemcall(rval, SYS_fstatat + 1024,
1430fbb751dSJohn Levon 		    AT_FDCWD, devname, &sbuf, 0) != 0) != 0)
1440fbb751dSJohn Levon 			goto doioctl;
1450fbb751dSJohn Levon 
1460fbb751dSJohn Levon 		*majordev = major(sbuf.st_rdev);
1470fbb751dSJohn Levon 	}
1480fbb751dSJohn Levon 
1490fbb751dSJohn Levon 	if ((*err = __systemcall(rval, SYS_fstatat + 1024, fdes,
1500fbb751dSJohn Levon 	    NULL, &sbuf, 0)) != 0)
1510fbb751dSJohn Levon 		goto doioctl;
1520fbb751dSJohn Levon 
1530fbb751dSJohn Levon 	if (major(sbuf.st_rdev) == *majordev)
1540fbb751dSJohn Levon 		return (0);
1550fbb751dSJohn Levon 
1560fbb751dSJohn Levon doioctl:
1570fbb751dSJohn Levon 	*err = (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
1580fbb751dSJohn Levon 	return (1);
1590fbb751dSJohn Levon }
1600fbb751dSJohn Levon 
161e71ca95cSGerald Jelinek /*
162e71ca95cSGerald Jelinek  * Figures out the PID of init for the zone.  Also returns a boolean
163e71ca95cSGerald Jelinek  * indicating whether this process currently has that pid: if so,
164e71ca95cSGerald Jelinek  * then at this moment, we are init.
165e71ca95cSGerald Jelinek  */
166e71ca95cSGerald Jelinek static boolean_t
get_initpid_info(void)167e71ca95cSGerald Jelinek get_initpid_info(void)
168e71ca95cSGerald Jelinek {
169e71ca95cSGerald Jelinek 	pid_t pid;
170e71ca95cSGerald Jelinek 	sysret_t rval;
171e71ca95cSGerald Jelinek 	int err;
172e71ca95cSGerald Jelinek 
173e71ca95cSGerald Jelinek 	/*
174e71ca95cSGerald Jelinek 	 * Determine the current process PID and the PID of the zone's init.
175e71ca95cSGerald Jelinek 	 * We use care not to call getpid() here, because we're not supposed
176e71ca95cSGerald Jelinek 	 * to call getpid() until after the program is fully linked-- the
177e71ca95cSGerald Jelinek 	 * first call to getpid() is a signal from the linker to debuggers
178e71ca95cSGerald Jelinek 	 * that linking has been completed.
179e71ca95cSGerald Jelinek 	 */
180e71ca95cSGerald Jelinek 	if ((err = __systemcall(&rval, SYS_brand,
181e71ca95cSGerald Jelinek 	    B_S10_PIDINFO, &pid, &zone_init_pid)) != 0) {
18280e2ca85S 		brand_abort(err, "Failed to get init's pid");
183e71ca95cSGerald Jelinek 	}
184e71ca95cSGerald Jelinek 
185e71ca95cSGerald Jelinek 	/*
186e71ca95cSGerald Jelinek 	 * Note that we need to be cautious with the pid we get back--
187e71ca95cSGerald Jelinek 	 * it should not be stashed and used in place of getpid(), since
188e71ca95cSGerald Jelinek 	 * we might fork(2).  So we keep zone_init_pid and toss the pid
189e71ca95cSGerald Jelinek 	 * we otherwise got.
190e71ca95cSGerald Jelinek 	 */
191e71ca95cSGerald Jelinek 	if (pid == zone_init_pid)
192e71ca95cSGerald Jelinek 		return (B_TRUE);
193e71ca95cSGerald Jelinek 
194e71ca95cSGerald Jelinek 	return (B_FALSE);
195e71ca95cSGerald Jelinek }
196e71ca95cSGerald Jelinek 
197c5aee804SRobert Harris /* Free the thread-local storage provided by mntfs_get_mntentbuf(). */
198835ee219SRobert Harris static void
mntfs_free_mntentbuf(void * arg)199835ee219SRobert Harris mntfs_free_mntentbuf(void *arg)
200835ee219SRobert Harris {
201835ee219SRobert Harris 	struct mntentbuf *embufp = arg;
202835ee219SRobert Harris 
203835ee219SRobert Harris 	if (embufp == NULL)
204835ee219SRobert Harris 		return;
205835ee219SRobert Harris 	if (embufp->mbuf_emp)
206835ee219SRobert Harris 		free(embufp->mbuf_emp);
207835ee219SRobert Harris 	if (embufp->mbuf_buf)
208835ee219SRobert Harris 		free(embufp->mbuf_buf);
209835ee219SRobert Harris 	bzero(embufp, sizeof (struct mntentbuf));
210835ee219SRobert Harris 	free(embufp);
211835ee219SRobert Harris }
212835ee219SRobert Harris 
213c5aee804SRobert Harris /* Provide the thread-local storage required by mntfs_ioctl(). */
214835ee219SRobert Harris static struct mntentbuf *
mntfs_get_mntentbuf(size_t size)215835ee219SRobert Harris mntfs_get_mntentbuf(size_t size)
216835ee219SRobert Harris {
217835ee219SRobert Harris 	static mutex_t keylock;
218835ee219SRobert Harris 	static thread_key_t key;
219835ee219SRobert Harris 	static int once_per_keyname = 0;
220835ee219SRobert Harris 	void *tsd = NULL;
221835ee219SRobert Harris 	struct mntentbuf *embufp;
222835ee219SRobert Harris 
223835ee219SRobert Harris 	/* Create the key. */
224835ee219SRobert Harris 	if (!once_per_keyname) {
225835ee219SRobert Harris 		(void) mutex_lock(&keylock);
226835ee219SRobert Harris 		if (!once_per_keyname) {
227835ee219SRobert Harris 			if (thr_keycreate(&key, mntfs_free_mntentbuf)) {
228835ee219SRobert Harris 				(void) mutex_unlock(&keylock);
229835ee219SRobert Harris 				return (NULL);
230835ee219SRobert Harris 			} else {
231835ee219SRobert Harris 				once_per_keyname++;
232835ee219SRobert Harris 			}
233835ee219SRobert Harris 		}
234835ee219SRobert Harris 		(void) mutex_unlock(&keylock);
235835ee219SRobert Harris 	}
236835ee219SRobert Harris 
237835ee219SRobert Harris 	/*
238835ee219SRobert Harris 	 * The thread-specific datum for this key is the address of a struct
239835ee219SRobert Harris 	 * mntentbuf. If this is the first time here then we allocate the struct
240835ee219SRobert Harris 	 * and its contents, and associate its address with the thread; if there
241835ee219SRobert Harris 	 * are any problems then we abort.
242835ee219SRobert Harris 	 */
243835ee219SRobert Harris 	if (thr_getspecific(key, &tsd))
244835ee219SRobert Harris 		return (NULL);
245835ee219SRobert Harris 	if (tsd == NULL) {
246835ee219SRobert Harris 		if (!(embufp = calloc(1, sizeof (struct mntentbuf))) ||
247835ee219SRobert Harris 		    !(embufp->mbuf_emp = malloc(sizeof (struct extmnttab))) ||
248835ee219SRobert Harris 		    thr_setspecific(key, embufp)) {
249835ee219SRobert Harris 			mntfs_free_mntentbuf(embufp);
250835ee219SRobert Harris 			return (NULL);
251835ee219SRobert Harris 		}
252835ee219SRobert Harris 	} else {
253835ee219SRobert Harris 		embufp = tsd;
254835ee219SRobert Harris 	}
255835ee219SRobert Harris 
256835ee219SRobert Harris 	/* Return the buffer, resizing it if necessary. */
257835ee219SRobert Harris 	if (size > embufp->mbuf_bufsize) {
258835ee219SRobert Harris 		if (embufp->mbuf_buf)
259835ee219SRobert Harris 			free(embufp->mbuf_buf);
260835ee219SRobert Harris 		if ((embufp->mbuf_buf = malloc(size)) == NULL) {
261835ee219SRobert Harris 			embufp->mbuf_bufsize = 0;
262835ee219SRobert Harris 			return (NULL);
263835ee219SRobert Harris 		} else {
264835ee219SRobert Harris 			embufp->mbuf_bufsize = size;
265835ee219SRobert Harris 		}
266835ee219SRobert Harris 	}
267835ee219SRobert Harris 	return (embufp);
268835ee219SRobert Harris }
269835ee219SRobert Harris 
270835ee219SRobert Harris /*
271c5aee804SRobert Harris  * The MNTIOC_GETMNTENT command in this release differs from that in early
272c5aee804SRobert Harris  * versions of Solaris 10.
273c5aee804SRobert Harris  *
274835ee219SRobert Harris  * Previously, the command would copy a pointer to a struct extmnttab to an
275835ee219SRobert Harris  * address provided as an argument. The pointer would be somewhere within a
276835ee219SRobert Harris  * mapping already present within the user's address space. In addition, the
277835ee219SRobert Harris  * text to which the struct's members pointed would also be within a
278835ee219SRobert Harris  * pre-existing mapping. Now, the user is required to allocate memory for both
279835ee219SRobert Harris  * the struct and the text buffer, and to pass the address of each within a
280835ee219SRobert Harris  * struct mntentbuf. In order to conceal these details from a Solaris 10 client
281835ee219SRobert Harris  * we allocate some thread-local storage in which to create the necessary data
282835ee219SRobert Harris  * structures; this is static, thread-safe memory that will be cleaned up
283835ee219SRobert Harris  * without the caller's intervention.
284835ee219SRobert Harris  *
285835ee219SRobert Harris  * MNTIOC_GETEXTMNTENT and MNTIOC_GETMNTANY are new in this release; they should
286835ee219SRobert Harris  * not work for older clients.
287835ee219SRobert Harris  */
288835ee219SRobert Harris int
mntfs_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)289835ee219SRobert Harris mntfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
290835ee219SRobert Harris {
291835ee219SRobert Harris 	int err;
292835ee219SRobert Harris 	struct stat statbuf;
293835ee219SRobert Harris 	struct mntentbuf *embufp;
294835ee219SRobert Harris 	static size_t bufsize = MNT_LINE_MAX;
295835ee219SRobert Harris 
296c5aee804SRobert Harris 	/* Do not emulate mntfs commands from up-to-date clients. */
297c5aee804SRobert Harris 	if (S10_FEATURE_IS_PRESENT(S10_FEATURE_ALTERED_MNTFS_IOCTL))
298c5aee804SRobert Harris 		return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
299c5aee804SRobert Harris 
300c5aee804SRobert Harris 	/* Do not emulate mntfs commands directed at other file systems. */
3018fd04b83SRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_fstatat + 1024,
3028fd04b83SRoger A. Faulkner 	    fdes, NULL, &statbuf, 0)) != 0)
303835ee219SRobert Harris 		return (err);
304835ee219SRobert Harris 	if (strcmp(statbuf.st_fstype, MNTTYPE_MNTFS) != 0)
305835ee219SRobert Harris 		return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
306835ee219SRobert Harris 
307835ee219SRobert Harris 	if (cmd == MNTIOC_GETEXTMNTENT || cmd == MNTIOC_GETMNTANY)
308835ee219SRobert Harris 		return (EINVAL);
309835ee219SRobert Harris 
310835ee219SRobert Harris 	if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
311835ee219SRobert Harris 		return (ENOMEM);
312835ee219SRobert Harris 
313835ee219SRobert Harris 	/*
314835ee219SRobert Harris 	 * MNTIOC_GETEXTMNTENT advances the file pointer once it has
315835ee219SRobert Harris 	 * successfully copied out the result to the address provided. We
316835ee219SRobert Harris 	 * therefore need to check the user-supplied address now since the
317835ee219SRobert Harris 	 * one we'll be providing is guaranteed to work.
318835ee219SRobert Harris 	 */
31980e2ca85S 	if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
320835ee219SRobert Harris 		return (EFAULT);
321835ee219SRobert Harris 
322835ee219SRobert Harris 	/*
323835ee219SRobert Harris 	 * Keep retrying for as long as we fail for want of a large enough
324835ee219SRobert Harris 	 * buffer.
325835ee219SRobert Harris 	 */
326835ee219SRobert Harris 	for (;;) {
327835ee219SRobert Harris 		if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes,
328835ee219SRobert Harris 		    MNTIOC_GETEXTMNTENT, embufp)) != 0)
329835ee219SRobert Harris 			return (err);
330835ee219SRobert Harris 
331835ee219SRobert Harris 		if (rval->sys_rval1 == MNTFS_TOOLONG) {
332835ee219SRobert Harris 			/* The buffer wasn't large enough. */
333835ee219SRobert Harris 			(void) atomic_swap_ulong((unsigned long *)&bufsize,
334835ee219SRobert Harris 			    2 * embufp->mbuf_bufsize);
335835ee219SRobert Harris 			if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
336835ee219SRobert Harris 				return (ENOMEM);
337835ee219SRobert Harris 		} else {
338835ee219SRobert Harris 			break;
339835ee219SRobert Harris 		}
340835ee219SRobert Harris 	}
341835ee219SRobert Harris 
34280e2ca85S 	if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
343835ee219SRobert Harris 		return (EFAULT);
344835ee219SRobert Harris 
345835ee219SRobert Harris 	return (0);
346835ee219SRobert Harris }
347835ee219SRobert Harris 
348e71ca95cSGerald Jelinek /*
349e71ca95cSGerald Jelinek  * Assign the structure member value from the s (source) structure to the
350e71ca95cSGerald Jelinek  * d (dest) structure.
351e71ca95cSGerald Jelinek  */
352e71ca95cSGerald Jelinek #define	struct_assign(d, s, val)	(((d).val) = ((s).val))
353e71ca95cSGerald Jelinek 
354e71ca95cSGerald Jelinek /*
355e71ca95cSGerald Jelinek  * The CRYPTO_GET_FUNCTION_LIST parameter structure crypto_function_list_t
356e71ca95cSGerald Jelinek  * changed between S10 and Nevada, so we have to emulate the old S10
357e71ca95cSGerald Jelinek  * crypto_function_list_t structure when interposing on the ioctl syscall.
358e71ca95cSGerald Jelinek  */
359e71ca95cSGerald Jelinek typedef struct s10_crypto_function_list {
360e71ca95cSGerald Jelinek 	boolean_t fl_digest_init;
361e71ca95cSGerald Jelinek 	boolean_t fl_digest;
362e71ca95cSGerald Jelinek 	boolean_t fl_digest_update;
363e71ca95cSGerald Jelinek 	boolean_t fl_digest_key;
364e71ca95cSGerald Jelinek 	boolean_t fl_digest_final;
365e71ca95cSGerald Jelinek 
366e71ca95cSGerald Jelinek 	boolean_t fl_encrypt_init;
367e71ca95cSGerald Jelinek 	boolean_t fl_encrypt;
368e71ca95cSGerald Jelinek 	boolean_t fl_encrypt_update;
369e71ca95cSGerald Jelinek 	boolean_t fl_encrypt_final;
370e71ca95cSGerald Jelinek 
371e71ca95cSGerald Jelinek 	boolean_t fl_decrypt_init;
372e71ca95cSGerald Jelinek 	boolean_t fl_decrypt;
373e71ca95cSGerald Jelinek 	boolean_t fl_decrypt_update;
374e71ca95cSGerald Jelinek 	boolean_t fl_decrypt_final;
375e71ca95cSGerald Jelinek 
376e71ca95cSGerald Jelinek 	boolean_t fl_mac_init;
377e71ca95cSGerald Jelinek 	boolean_t fl_mac;
378e71ca95cSGerald Jelinek 	boolean_t fl_mac_update;
379e71ca95cSGerald Jelinek 	boolean_t fl_mac_final;
380e71ca95cSGerald Jelinek 
381e71ca95cSGerald Jelinek 	boolean_t fl_sign_init;
382e71ca95cSGerald Jelinek 	boolean_t fl_sign;
383e71ca95cSGerald Jelinek 	boolean_t fl_sign_update;
384e71ca95cSGerald Jelinek 	boolean_t fl_sign_final;
385e71ca95cSGerald Jelinek 	boolean_t fl_sign_recover_init;
386e71ca95cSGerald Jelinek 	boolean_t fl_sign_recover;
387e71ca95cSGerald Jelinek 
388e71ca95cSGerald Jelinek 	boolean_t fl_verify_init;
389e71ca95cSGerald Jelinek 	boolean_t fl_verify;
390e71ca95cSGerald Jelinek 	boolean_t fl_verify_update;
391e71ca95cSGerald Jelinek 	boolean_t fl_verify_final;
392e71ca95cSGerald Jelinek 	boolean_t fl_verify_recover_init;
393e71ca95cSGerald Jelinek 	boolean_t fl_verify_recover;
394e71ca95cSGerald Jelinek 
395e71ca95cSGerald Jelinek 	boolean_t fl_digest_encrypt_update;
396e71ca95cSGerald Jelinek 	boolean_t fl_decrypt_digest_update;
397e71ca95cSGerald Jelinek 	boolean_t fl_sign_encrypt_update;
398e71ca95cSGerald Jelinek 	boolean_t fl_decrypt_verify_update;
399e71ca95cSGerald Jelinek 
400e71ca95cSGerald Jelinek 	boolean_t fl_seed_random;
401e71ca95cSGerald Jelinek 	boolean_t fl_generate_random;
402e71ca95cSGerald Jelinek 
403e71ca95cSGerald Jelinek 	boolean_t fl_session_open;
404e71ca95cSGerald Jelinek 	boolean_t fl_session_close;
405e71ca95cSGerald Jelinek 	boolean_t fl_session_login;
406e71ca95cSGerald Jelinek 	boolean_t fl_session_logout;
407e71ca95cSGerald Jelinek 
408e71ca95cSGerald Jelinek 	boolean_t fl_object_create;
409e71ca95cSGerald Jelinek 	boolean_t fl_object_copy;
410e71ca95cSGerald Jelinek 	boolean_t fl_object_destroy;
411e71ca95cSGerald Jelinek 	boolean_t fl_object_get_size;
412e71ca95cSGerald Jelinek 	boolean_t fl_object_get_attribute_value;
413e71ca95cSGerald Jelinek 	boolean_t fl_object_set_attribute_value;
414e71ca95cSGerald Jelinek 	boolean_t fl_object_find_init;
415e71ca95cSGerald Jelinek 	boolean_t fl_object_find;
416e71ca95cSGerald Jelinek 	boolean_t fl_object_find_final;
417e71ca95cSGerald Jelinek 
418e71ca95cSGerald Jelinek 	boolean_t fl_key_generate;
419e71ca95cSGerald Jelinek 	boolean_t fl_key_generate_pair;
420e71ca95cSGerald Jelinek 	boolean_t fl_key_wrap;
421e71ca95cSGerald Jelinek 	boolean_t fl_key_unwrap;
422e71ca95cSGerald Jelinek 	boolean_t fl_key_derive;
423e71ca95cSGerald Jelinek 
424e71ca95cSGerald Jelinek 	boolean_t fl_init_token;
425e71ca95cSGerald Jelinek 	boolean_t fl_init_pin;
426e71ca95cSGerald Jelinek 	boolean_t fl_set_pin;
427e71ca95cSGerald Jelinek 
4284df55fdeSJanie Lu 	boolean_t prov_is_hash_limited;
429e71ca95cSGerald Jelinek 	uint32_t prov_hash_threshold;
430e71ca95cSGerald Jelinek 	uint32_t prov_hash_limit;
431e71ca95cSGerald Jelinek } s10_crypto_function_list_t;
432e71ca95cSGerald Jelinek 
433e71ca95cSGerald Jelinek typedef struct s10_crypto_get_function_list {
434e71ca95cSGerald Jelinek 	uint_t				fl_return_value;
435e71ca95cSGerald Jelinek 	crypto_provider_id_t		fl_provider_id;
436e71ca95cSGerald Jelinek 	s10_crypto_function_list_t	fl_list;
437e71ca95cSGerald Jelinek } s10_crypto_get_function_list_t;
438e71ca95cSGerald Jelinek 
439e71ca95cSGerald Jelinek /*
440e71ca95cSGerald Jelinek  * The structure returned by the CRYPTO_GET_FUNCTION_LIST ioctl on /dev/crypto
441e71ca95cSGerald Jelinek  * increased in size due to:
442e71ca95cSGerald Jelinek  *	6482533 Threshold for HW offload via PKCS11 interface
443e71ca95cSGerald Jelinek  * between S10 and Nevada.  This is a relatively simple process of filling
444e71ca95cSGerald Jelinek  * in the S10 structure fields with the Nevada data.
445e71ca95cSGerald Jelinek  *
446e71ca95cSGerald Jelinek  * We stat the device to make sure that the ioctl is meant for /dev/crypto.
447e71ca95cSGerald Jelinek  *
448e71ca95cSGerald Jelinek  */
449e71ca95cSGerald Jelinek static int
crypto_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)450e71ca95cSGerald Jelinek crypto_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
451e71ca95cSGerald Jelinek {
452e71ca95cSGerald Jelinek 	int				err;
453e71ca95cSGerald Jelinek 	s10_crypto_get_function_list_t	s10_param;
454e71ca95cSGerald Jelinek 	crypto_get_function_list_t	native_param;
455e71ca95cSGerald Jelinek 	static dev_t			crypto_dev = (dev_t)-1;
456e71ca95cSGerald Jelinek 
4570fbb751dSJohn Levon 	if (passthru_otherdev_ioctl(&crypto_dev, "/dev/crypto", &err,
4580fbb751dSJohn Levon 	    rval, fdes, cmd, arg) == 1)
459e71ca95cSGerald Jelinek 		return (err);
460e71ca95cSGerald Jelinek 
46180e2ca85S 	if (brand_uucopy((const void *)arg, &s10_param, sizeof (s10_param))
46280e2ca85S 	    != 0)
463e71ca95cSGerald Jelinek 		return (EFAULT);
464e71ca95cSGerald Jelinek 	struct_assign(native_param, s10_param, fl_provider_id);
465e71ca95cSGerald Jelinek 	if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd,
466e71ca95cSGerald Jelinek 	    &native_param)) != 0)
467e71ca95cSGerald Jelinek 		return (err);
468e71ca95cSGerald Jelinek 
469e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_return_value);
470e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_provider_id);
471e71ca95cSGerald Jelinek 
472e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_digest_init);
473e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_digest);
474e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_digest_update);
475e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_digest_key);
476e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_digest_final);
477e71ca95cSGerald Jelinek 
478e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_encrypt_init);
479e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_encrypt);
480e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_encrypt_update);
481e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_encrypt_final);
482e71ca95cSGerald Jelinek 
483e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_decrypt_init);
484e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_decrypt);
485e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_decrypt_update);
486e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_decrypt_final);
487e71ca95cSGerald Jelinek 
488e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_mac_init);
489e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_mac);
490e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_mac_update);
491e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_mac_final);
492e71ca95cSGerald Jelinek 
493e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_init);
494e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign);
495e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_update);
496e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_final);
497e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_recover_init);
498e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_recover);
499e71ca95cSGerald Jelinek 
500e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify_init);
501e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify);
502e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify_update);
503e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify_final);
504e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify_recover_init);
505e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_verify_recover);
506e71ca95cSGerald Jelinek 
507e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param,
508e71ca95cSGerald Jelinek 	    fl_list.fl_digest_encrypt_update);
509e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param,
510e71ca95cSGerald Jelinek 	    fl_list.fl_decrypt_digest_update);
511e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_sign_encrypt_update);
512e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param,
513e71ca95cSGerald Jelinek 	    fl_list.fl_decrypt_verify_update);
514e71ca95cSGerald Jelinek 
515e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_seed_random);
516e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_generate_random);
517e71ca95cSGerald Jelinek 
518e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_session_open);
519e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_session_close);
520e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_session_login);
521e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_session_logout);
522e71ca95cSGerald Jelinek 
523e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_create);
524e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_copy);
525e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_destroy);
526e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_get_size);
527e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param,
528e71ca95cSGerald Jelinek 	    fl_list.fl_object_get_attribute_value);
529e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param,
530e71ca95cSGerald Jelinek 	    fl_list.fl_object_set_attribute_value);
531e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_find_init);
532e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_find);
533e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_object_find_final);
534e71ca95cSGerald Jelinek 
535e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_key_generate);
536e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_key_generate_pair);
537e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_key_wrap);
538e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_key_unwrap);
539e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_key_derive);
540e71ca95cSGerald Jelinek 
541e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_init_token);
542e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_init_pin);
543e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.fl_set_pin);
544e71ca95cSGerald Jelinek 
5454df55fdeSJanie Lu 	struct_assign(s10_param, native_param, fl_list.prov_is_hash_limited);
546e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.prov_hash_threshold);
547e71ca95cSGerald Jelinek 	struct_assign(s10_param, native_param, fl_list.prov_hash_limit);
548e71ca95cSGerald Jelinek 
54980e2ca85S 	return (brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param)));
550e71ca95cSGerald Jelinek }
551e71ca95cSGerald Jelinek 
552e71ca95cSGerald Jelinek /*
553e71ca95cSGerald Jelinek  * The process contract CT_TGET and CT_TSET parameter structure ct_param_t
554e71ca95cSGerald Jelinek  * changed between S10 and Nevada, so we have to emulate the old S10
555e71ca95cSGerald Jelinek  * ct_param_t structure when interposing on the ioctl syscall.
556e71ca95cSGerald Jelinek  */
557e71ca95cSGerald Jelinek typedef struct s10_ct_param {
558e71ca95cSGerald Jelinek 	uint32_t ctpm_id;
559e71ca95cSGerald Jelinek 	uint32_t ctpm_pad;
560e71ca95cSGerald Jelinek 	uint64_t ctpm_value;
561e71ca95cSGerald Jelinek } s10_ct_param_t;
562e71ca95cSGerald Jelinek 
563e71ca95cSGerald Jelinek /*
564bbf21555SRichard Lowe  * We have to emulate process contract ioctls for init(8) because the
565e71ca95cSGerald Jelinek  * ioctl parameter structure changed between S10 and Nevada.  This is
566e71ca95cSGerald Jelinek  * a relatively simple process of filling Nevada structure fields,
567e71ca95cSGerald Jelinek  * shuffling values, and initiating a native system call.
568e71ca95cSGerald Jelinek  *
569e71ca95cSGerald Jelinek  * For now, we'll assume that all consumers of CT_TGET and CT_TSET will
570e71ca95cSGerald Jelinek  * need emulation.  We'll issue a stat to make sure that the ioctl
571e71ca95cSGerald Jelinek  * is meant for the contract file system.
572e71ca95cSGerald Jelinek  *
573e71ca95cSGerald Jelinek  */
574e71ca95cSGerald Jelinek static int
ctfs_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)575e71ca95cSGerald Jelinek ctfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
576e71ca95cSGerald Jelinek {
577e71ca95cSGerald Jelinek 	int err;
578e71ca95cSGerald Jelinek 	s10_ct_param_t s10param;
579e71ca95cSGerald Jelinek 	ct_param_t param;
580e71ca95cSGerald Jelinek 	struct stat statbuf;
581e71ca95cSGerald Jelinek 
5828fd04b83SRoger A. Faulkner 	if ((err = __systemcall(rval, SYS_fstatat + 1024,
5838fd04b83SRoger A. Faulkner 	    fdes, NULL, &statbuf, 0)) != 0)
584e71ca95cSGerald Jelinek 		return (err);
585e71ca95cSGerald Jelinek 	if (strcmp(statbuf.st_fstype, MNTTYPE_CTFS) != 0)
586e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
587e71ca95cSGerald Jelinek 
58880e2ca85S 	if (brand_uucopy((const void *)arg, &s10param, sizeof (s10param)) != 0)
589e71ca95cSGerald Jelinek 		return (EFAULT);
590e71ca95cSGerald Jelinek 	param.ctpm_id = s10param.ctpm_id;
591e71ca95cSGerald Jelinek 	param.ctpm_size = sizeof (uint64_t);
592e71ca95cSGerald Jelinek 	param.ctpm_value = &s10param.ctpm_value;
593e71ca95cSGerald Jelinek 	if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, &param))
594e71ca95cSGerald Jelinek 	    != 0)
595e71ca95cSGerald Jelinek 		return (err);
596e71ca95cSGerald Jelinek 
597e71ca95cSGerald Jelinek 	if (cmd == CT_TGET)
59880e2ca85S 		return (brand_uucopy(&s10param, (void *)arg,
59980e2ca85S 		    sizeof (s10param)));
600e71ca95cSGerald Jelinek 
601e71ca95cSGerald Jelinek 	return (0);
602e71ca95cSGerald Jelinek }
603e71ca95cSGerald Jelinek 
604fcdeb91bSjv /*
605f3680c6cS  * ZFS ioctls have changed in each Solaris 10 (S10) release as well as in
606f3680c6cS  * Solaris Next.  The brand wraps ZFS commands so that the native commands
607f3680c6cS  * are used, but we want to be sure no command sneaks in that uses ZFS
608f3680c6cS  * without our knowledge.  We'll abort the process if we see a ZFS ioctl.
609e71ca95cSGerald Jelinek  */
610e71ca95cSGerald Jelinek static int
zfs_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)611e71ca95cSGerald Jelinek zfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
612e71ca95cSGerald Jelinek {
6130fbb751dSJohn Levon 	static dev_t zfs_dev = (dev_t)-1;
6140fbb751dSJohn Levon 	int err;
615e71ca95cSGerald Jelinek 
6160fbb751dSJohn Levon 	if (passthru_otherdev_ioctl(&zfs_dev, ZFS_DEV, &err,
6170fbb751dSJohn Levon 	    rval, fdes, cmd, arg) == 1)
6180fbb751dSJohn Levon 		return (err);
619e71ca95cSGerald Jelinek 
620f3680c6cS 	brand_abort(0, "ZFS ioctl!");
621f3680c6cS 	/*NOTREACHED*/
622f3680c6cS 	return (0);
623e71ca95cSGerald Jelinek }
624e71ca95cSGerald Jelinek 
6250fbb751dSJohn Levon struct s10_lofi_ioctl {
626406fc510SToomas Soome 	uint32_t li_id;
6270fbb751dSJohn Levon 	boolean_t li_force;
6280fbb751dSJohn Levon 	char li_filename[MAXPATHLEN + 1];
6290fbb751dSJohn Levon };
6300fbb751dSJohn Levon 
6310fbb751dSJohn Levon static int
lofi_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)6320fbb751dSJohn Levon lofi_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
6330fbb751dSJohn Levon {
6340fbb751dSJohn Levon 	static dev_t lofi_dev = (dev_t)-1;
6350fbb751dSJohn Levon 	struct s10_lofi_ioctl s10_param;
6360fbb751dSJohn Levon 	struct lofi_ioctl native_param;
6370fbb751dSJohn Levon 	int err;
6380fbb751dSJohn Levon 
6390fbb751dSJohn Levon 	if (passthru_otherdev_ioctl(&lofi_dev, "/dev/lofictl", &err,
6400fbb751dSJohn Levon 	    rval, fdes, cmd, arg) == 1)
6410fbb751dSJohn Levon 		return (err);
6420fbb751dSJohn Levon 
6430fbb751dSJohn Levon 	if (brand_uucopy((const void *)arg, &s10_param,
6440fbb751dSJohn Levon 	    sizeof (s10_param)) != 0)
6450fbb751dSJohn Levon 		return (EFAULT);
6460fbb751dSJohn Levon 
6470fbb751dSJohn Levon 	/*
6480fbb751dSJohn Levon 	 * Somewhat weirdly, EIO is what the S10 lofi driver would
6490fbb751dSJohn Levon 	 * return for unrecognised cmds.
6500fbb751dSJohn Levon 	 */
6510fbb751dSJohn Levon 	if (cmd >= LOFI_CHECK_COMPRESSED)
6520fbb751dSJohn Levon 		return (EIO);
6530fbb751dSJohn Levon 
6540fbb751dSJohn Levon 	bzero(&native_param, sizeof (native_param));
6550fbb751dSJohn Levon 
656406fc510SToomas Soome 	struct_assign(native_param, s10_param, li_id);
6570fbb751dSJohn Levon 	struct_assign(native_param, s10_param, li_force);
6580fbb751dSJohn Levon 
6590fbb751dSJohn Levon 	/*
6600fbb751dSJohn Levon 	 * Careful here, this has changed from [MAXPATHLEN + 1] to
6610fbb751dSJohn Levon 	 * [MAXPATHLEN].
6620fbb751dSJohn Levon 	 */
6630fbb751dSJohn Levon 	bcopy(s10_param.li_filename, native_param.li_filename,
6640fbb751dSJohn Levon 	    sizeof (native_param.li_filename));
6650fbb751dSJohn Levon 	native_param.li_filename[MAXPATHLEN - 1] = '\0';
6660fbb751dSJohn Levon 
6670fbb751dSJohn Levon 	err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, &native_param);
6680fbb751dSJohn Levon 
669406fc510SToomas Soome 	struct_assign(s10_param, native_param, li_id);
6700fbb751dSJohn Levon 	/* li_force is input-only */
6710fbb751dSJohn Levon 
6720fbb751dSJohn Levon 	bcopy(native_param.li_filename, s10_param.li_filename,
6730fbb751dSJohn Levon 	    sizeof (native_param.li_filename));
6740fbb751dSJohn Levon 
6750fbb751dSJohn Levon 	(void) brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param));
6760fbb751dSJohn Levon 	return (err);
6770fbb751dSJohn Levon }
6780fbb751dSJohn Levon 
679e71ca95cSGerald Jelinek int
s10_ioctl(sysret_t * rval,int fdes,int cmd,intptr_t arg)680e71ca95cSGerald Jelinek s10_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
681e71ca95cSGerald Jelinek {
682e71ca95cSGerald Jelinek 	switch (cmd) {
683e71ca95cSGerald Jelinek 	case CRYPTO_GET_FUNCTION_LIST:
684e71ca95cSGerald Jelinek 		return (crypto_ioctl(rval, fdes, cmd, arg));
685e71ca95cSGerald Jelinek 	case CT_TGET:
686e71ca95cSGerald Jelinek 		/*FALLTHRU*/
687e71ca95cSGerald Jelinek 	case CT_TSET:
688e71ca95cSGerald Jelinek 		return (ctfs_ioctl(rval, fdes, cmd, arg));
689835ee219SRobert Harris 	case MNTIOC_GETMNTENT:
690835ee219SRobert Harris 		/*FALLTHRU*/
691835ee219SRobert Harris 	case MNTIOC_GETEXTMNTENT:
692835ee219SRobert Harris 		/*FALLTHRU*/
693835ee219SRobert Harris 	case MNTIOC_GETMNTANY:
694835ee219SRobert Harris 		return (mntfs_ioctl(rval, fdes, cmd, arg));
695e71ca95cSGerald Jelinek 	}
696e71ca95cSGerald Jelinek 
6970fbb751dSJohn Levon 	switch (cmd & ~0xff) {
6980fbb751dSJohn Levon 	case ZFS_IOC:
699e71ca95cSGerald Jelinek 		return (zfs_ioctl(rval, fdes, cmd, arg));
700e71ca95cSGerald Jelinek 
7010fbb751dSJohn Levon 	case LOFI_IOC_BASE:
7020fbb751dSJohn Levon 		return (lofi_ioctl(rval, fdes, cmd, arg));
7030fbb751dSJohn Levon 
7040fbb751dSJohn Levon 	default:
7050fbb751dSJohn Levon 		break;
7060fbb751dSJohn Levon 	}
7070fbb751dSJohn Levon 
708e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
709e71ca95cSGerald Jelinek }
710e71ca95cSGerald Jelinek 
711e71ca95cSGerald Jelinek /*
712e71ca95cSGerald Jelinek  * Unfortunately, pwrite()'s behavior differs between S10 and Nevada when
713e71ca95cSGerald Jelinek  * applied to files opened with O_APPEND.  The offset argument is ignored and
714e71ca95cSGerald Jelinek  * the buffer is appended to the target file in S10, whereas the current file
715e71ca95cSGerald Jelinek  * position is ignored in Nevada (i.e., pwrite() acts as though the target file
716e71ca95cSGerald Jelinek  * wasn't opened with O_APPEND).  This is a result of the fix for CR 6655660
717e71ca95cSGerald Jelinek  * (pwrite() must ignore the O_APPEND/FAPPEND flag).
718e71ca95cSGerald Jelinek  *
719e71ca95cSGerald Jelinek  * We emulate the old S10 pwrite() behavior by checking whether the target file
720e71ca95cSGerald Jelinek  * was opened with O_APPEND.  If it was, then invoke the write() system call
721e71ca95cSGerald Jelinek  * instead of pwrite(); otherwise, invoke the pwrite() system call as usual.
722e71ca95cSGerald Jelinek  */
723e71ca95cSGerald Jelinek static int
s10_pwrite(sysret_t * rval,int fd,const void * bufferp,size_t num_bytes,off_t offset)724e71ca95cSGerald Jelinek s10_pwrite(sysret_t *rval, int fd, const void *bufferp, size_t num_bytes,
725e71ca95cSGerald Jelinek     off_t offset)
726e71ca95cSGerald Jelinek {
727e71ca95cSGerald Jelinek 	int err;
728e71ca95cSGerald Jelinek 
729e71ca95cSGerald Jelinek 	if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL)) != 0)
730e71ca95cSGerald Jelinek 		return (err);
731e71ca95cSGerald Jelinek 	if (rval->sys_rval1 & O_APPEND)
732e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
733e71ca95cSGerald Jelinek 		    num_bytes));
734e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_pwrite + 1024, fd, bufferp, num_bytes,
735e71ca95cSGerald Jelinek 	    offset));
736e71ca95cSGerald Jelinek }
737e71ca95cSGerald Jelinek 
7388fd04b83SRoger A. Faulkner #if !defined(_LP64)
739e71ca95cSGerald Jelinek /*
740e71ca95cSGerald Jelinek  * This is the large file version of the pwrite() system call for 32-bit
741e71ca95cSGerald Jelinek  * processes.  This exists for the same reason that s10_pwrite() exists; see
742e71ca95cSGerald Jelinek  * the comment above s10_pwrite().
743e71ca95cSGerald Jelinek  */
744e71ca95cSGerald Jelinek static int
s10_pwrite64(sysret_t * rval,int fd,const void * bufferp,size32_t num_bytes,uint32_t offset_1,uint32_t offset_2)745e71ca95cSGerald Jelinek s10_pwrite64(sysret_t *rval, int fd, const void *bufferp, size32_t num_bytes,
746e71ca95cSGerald Jelinek     uint32_t offset_1, uint32_t offset_2)
747e71ca95cSGerald Jelinek {
748e71ca95cSGerald Jelinek 	int err;
749e71ca95cSGerald Jelinek 
750e71ca95cSGerald Jelinek 	if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL)) != 0)
751e71ca95cSGerald Jelinek 		return (err);
752e71ca95cSGerald Jelinek 	if (rval->sys_rval1 & O_APPEND)
753e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
754e71ca95cSGerald Jelinek 		    num_bytes));
755e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_pwrite64 + 1024, fd, bufferp,
756e71ca95cSGerald Jelinek 	    num_bytes, offset_1, offset_2));
757e71ca95cSGerald Jelinek }
758e71ca95cSGerald Jelinek #endif	/* !_LP64 */
759e71ca95cSGerald Jelinek 
7608b4cf837Sjv /*
7618b4cf837Sjv  * These are convenience macros that s10_getdents_common() uses.  Both treat
7628b4cf837Sjv  * their arguments, which should be character pointers, as dirent pointers or
7638b4cf837Sjv  * dirent64 pointers and yield their d_name and d_reclen fields.  These
7648b4cf837Sjv  * macros shouldn't be used outside of s10_getdents_common().
7658b4cf837Sjv  */
7668b4cf837Sjv #define	dirent_name(charptr)	((charptr) + name_offset)
7678b4cf837Sjv #define	dirent_reclen(charptr)	\
7688b4cf837Sjv 	(*(unsigned short *)(uintptr_t)((charptr) + reclen_offset))
7698b4cf837Sjv 
7708b4cf837Sjv /*
7718b4cf837Sjv  * This function contains code that is common to both s10_getdents() and
7728b4cf837Sjv  * s10_getdents64().  See the comment above s10_getdents() for details.
7738b4cf837Sjv  *
7748b4cf837Sjv  * rval, fd, buf, and nbyte should be passed unmodified from s10_getdents()
7758b4cf837Sjv  * and s10_getdents64().  getdents_syscall_id should be either SYS_getdents
7768b4cf837Sjv  * or SYS_getdents64.  name_offset should be the the byte offset of
7778b4cf837Sjv  * the d_name field in the dirent structures passed to the kernel via the
7788b4cf837Sjv  * syscall represented by getdents_syscall_id.  reclen_offset should be
7798b4cf837Sjv  * the byte offset of the d_reclen field in the aforementioned dirent
7808b4cf837Sjv  * structures.
7818b4cf837Sjv  */
7828b4cf837Sjv static int
s10_getdents_common(sysret_t * rval,int fd,char * buf,size_t nbyte,int getdents_syscall_id,size_t name_offset,size_t reclen_offset)7838b4cf837Sjv s10_getdents_common(sysret_t *rval, int fd, char *buf, size_t nbyte,
7848b4cf837Sjv     int getdents_syscall_id, size_t name_offset, size_t reclen_offset)
7858b4cf837Sjv {
7868b4cf837Sjv 	int err;
7878b4cf837Sjv 	size_t buf_size;
7888b4cf837Sjv 	char *local_buf;
7898b4cf837Sjv 	char *buf_current;
7908b4cf837Sjv 
7918b4cf837Sjv 	/*
7928b4cf837Sjv 	 * Use a special brand operation, B_S10_ISFDXATTRDIR, to determine
7938b4cf837Sjv 	 * whether the specified file descriptor refers to an extended file
7948b4cf837Sjv 	 * attribute directory.  If it doesn't, then SYS_getdents won't
7958b4cf837Sjv 	 * reveal extended file attributes, in which case we can simply
7968b4cf837Sjv 	 * hand the syscall to the native kernel.
7978b4cf837Sjv 	 */
7988b4cf837Sjv 	if ((err = __systemcall(rval, SYS_brand + 1024, B_S10_ISFDXATTRDIR,
7998b4cf837Sjv 	    fd)) != 0)
8008b4cf837Sjv 		return (err);
8018b4cf837Sjv 	if (rval->sys_rval1 == 0)
8028b4cf837Sjv 		return (__systemcall(rval, getdents_syscall_id + 1024, fd, buf,
8038b4cf837Sjv 		    nbyte));
8048b4cf837Sjv 
8058b4cf837Sjv 	/*
8068b4cf837Sjv 	 * The file descriptor refers to an extended file attributes directory.
8078b4cf837Sjv 	 * We need to create a dirent buffer that's as large as buf into which
8088b4cf837Sjv 	 * the native SYS_getdents will store the special extended file
8098b4cf837Sjv 	 * attribute directory's entries.  We can't dereference buf because
8108b4cf837Sjv 	 * it might be an invalid pointer!
8118b4cf837Sjv 	 */
8128b4cf837Sjv 	if (nbyte > MAXGETDENTS_SIZE)
8138b4cf837Sjv 		nbyte = MAXGETDENTS_SIZE;
8148b4cf837Sjv 	local_buf = (char *)malloc(nbyte);
8158b4cf837Sjv 	if (local_buf == NULL) {
8168b4cf837Sjv 		/*
8178b4cf837Sjv 		 * getdents(2) doesn't return an error code indicating a memory
8188b4cf837Sjv 		 * allocation error and it doesn't make sense to return any of
8198b4cf837Sjv 		 * its documented error codes for a malloc(3C) failure.  We'll
8208b4cf837Sjv 		 * use ENOMEM even though getdents(2) doesn't use it because it
8218b4cf837Sjv 		 * best describes the failure.
8228b4cf837Sjv 		 */
82380e2ca85S 		(void) B_TRUSS_POINT_3(rval, getdents_syscall_id, ENOMEM, fd,
8248b4cf837Sjv 		    buf, nbyte);
8258b4cf837Sjv 		rval->sys_rval1 = -1;
8268b4cf837Sjv 		rval->sys_rval2 = 0;
8278b4cf837Sjv 		return (EIO);
8288b4cf837Sjv 	}
8298b4cf837Sjv 
8308b4cf837Sjv 	/*
8318b4cf837Sjv 	 * Issue a native SYS_getdents syscall but use our local dirent buffer
8328b4cf837Sjv 	 * instead of buf.  This will allow us to examine the returned dirent
8338b4cf837Sjv 	 * structures immediately and copy them to buf later.  That way the
8348b4cf837Sjv 	 * calling process won't be able to see the dirent structures until
8358b4cf837Sjv 	 * we finish examining them.
8368b4cf837Sjv 	 */
8378b4cf837Sjv 	if ((err = __systemcall(rval, getdents_syscall_id + 1024, fd, local_buf,
8388b4cf837Sjv 	    nbyte)) != 0) {
8398b4cf837Sjv 		free(local_buf);
8408b4cf837Sjv 		return (err);
8418b4cf837Sjv 	}
8428b4cf837Sjv 	buf_size = rval->sys_rval1;
8438b4cf837Sjv 	if (buf_size == 0) {
8448b4cf837Sjv 		free(local_buf);
8458b4cf837Sjv 		return (0);
8468b4cf837Sjv 	}
8478b4cf837Sjv 
8488b4cf837Sjv 	/*
8498b4cf837Sjv 	 * Look for SUNWattr_ro (VIEW_READONLY) and SUNWattr_rw
8508b4cf837Sjv 	 * (VIEW_READWRITE) in the directory entries and remove them
8518b4cf837Sjv 	 * from the dirent buffer.
8528b4cf837Sjv 	 */
8538b4cf837Sjv 	for (buf_current = local_buf;
8548b4cf837Sjv 	    (size_t)(buf_current - local_buf) < buf_size; /* cstyle */) {
8558b4cf837Sjv 		if (strcmp(dirent_name(buf_current), VIEW_READONLY) != 0 &&
8568b4cf837Sjv 		    strcmp(dirent_name(buf_current), VIEW_READWRITE) != 0) {
8578b4cf837Sjv 			/*
8588b4cf837Sjv 			 * The dirent refers to an attribute that should
8598b4cf837Sjv 			 * be visible to Solaris 10 processes.  Keep it
8608b4cf837Sjv 			 * and examine the next entry in the buffer.
8618b4cf837Sjv 			 */
8628b4cf837Sjv 			buf_current += dirent_reclen(buf_current);
8638b4cf837Sjv 		} else {
8648b4cf837Sjv 			/*
8658b4cf837Sjv 			 * We found either SUNWattr_ro (VIEW_READONLY)
8668b4cf837Sjv 			 * or SUNWattr_rw (VIEW_READWRITE).  Remove it
8678b4cf837Sjv 			 * from the dirent buffer by decrementing
8688b4cf837Sjv 			 * buf_size by the size of the entry and
8698b4cf837Sjv 			 * overwriting the entry with the remaining
8708b4cf837Sjv 			 * entries.
8718b4cf837Sjv 			 */
8728b4cf837Sjv 			buf_size -= dirent_reclen(buf_current);
8738b4cf837Sjv 			(void) memmove(buf_current, buf_current +
8748b4cf837Sjv 			    dirent_reclen(buf_current), buf_size -
8758b4cf837Sjv 			    (size_t)(buf_current - local_buf));
8768b4cf837Sjv 		}
8778b4cf837Sjv 	}
8788b4cf837Sjv 
8798b4cf837Sjv 	/*
8808b4cf837Sjv 	 * Copy local_buf into buf so that the calling process can see
8818b4cf837Sjv 	 * the results.
8828b4cf837Sjv 	 */
88380e2ca85S 	if ((err = brand_uucopy(local_buf, buf, buf_size)) != 0) {
8848b4cf837Sjv 		free(local_buf);
8858b4cf837Sjv 		rval->sys_rval1 = -1;
8868b4cf837Sjv 		rval->sys_rval2 = 0;
8878b4cf837Sjv 		return (err);
8888b4cf837Sjv 	}
8898b4cf837Sjv 	rval->sys_rval1 = buf_size;
8908b4cf837Sjv 	free(local_buf);
8918b4cf837Sjv 	return (0);
8928b4cf837Sjv }
8938b4cf837Sjv 
8948b4cf837Sjv /*
8958b4cf837Sjv  * Solaris Next added two special extended file attributes, SUNWattr_ro and
8968b4cf837Sjv  * SUNWattr_rw, which are called "extended system attributes".  They have
8978b4cf837Sjv  * special semantics (e.g., a process cannot unlink SUNWattr_ro) and should
8988b4cf837Sjv  * not appear in solaris10-branded zones because no Solaris 10 applications,
8998b4cf837Sjv  * including system commands such as tar(1), are coded to correctly handle these
9008b4cf837Sjv  * special attributes.
9018b4cf837Sjv  *
9028b4cf837Sjv  * This emulation function solves the aforementioned problem by emulating
9038b4cf837Sjv  * the getdents(2) syscall and filtering both system attributes out of resulting
9048b4cf837Sjv  * directory entry lists.  The emulation function only filters results when
9058b4cf837Sjv  * the given file descriptor refers to an extended file attribute directory.
9068b4cf837Sjv  * Filtering getdents(2) results is expensive because it requires dynamic
9078b4cf837Sjv  * memory allocation; however, the performance cost is tolerable because
9088b4cf837Sjv  * we don't expect Solaris 10 processes to frequently examine extended file
9098b4cf837Sjv  * attribute directories.
9108b4cf837Sjv  *
9118b4cf837Sjv  * The brand's emulation library needs two getdents(2) emulation functions
9128b4cf837Sjv  * because getdents(2) comes in two flavors: non-largefile-aware getdents(2)
9138b4cf837Sjv  * and largefile-aware getdents64(2).  s10_getdents() handles the non-largefile-
9148b4cf837Sjv  * aware case for 32-bit processes and all getdents(2) syscalls for 64-bit
9158b4cf837Sjv  * processes (64-bit processes use largefile-aware interfaces by default).
9168b4cf837Sjv  * See s10_getdents64() below for the largefile-aware getdents64(2) emulation
9178b4cf837Sjv  * function for 32-bit processes.
9188b4cf837Sjv  */
9198b4cf837Sjv static int
s10_getdents(sysret_t * rval,int fd,struct dirent * buf,size_t nbyte)9208b4cf837Sjv s10_getdents(sysret_t *rval, int fd, struct dirent *buf, size_t nbyte)
9218b4cf837Sjv {
9228b4cf837Sjv 	return (s10_getdents_common(rval, fd, (char *)buf, nbyte, SYS_getdents,
9238b4cf837Sjv 	    offsetof(struct dirent, d_name),
9248b4cf837Sjv 	    offsetof(struct dirent, d_reclen)));
9258b4cf837Sjv }
9268b4cf837Sjv 
9278b4cf837Sjv #ifndef	_LP64
9288b4cf837Sjv /*
9298b4cf837Sjv  * This is the largefile-aware version of getdents(2) for 32-bit processes.
9308b4cf837Sjv  * This exists for the same reason that s10_getdents() exists.  See the comment
9318b4cf837Sjv  * above s10_getdents().
9328b4cf837Sjv  */
9338b4cf837Sjv static int
s10_getdents64(sysret_t * rval,int fd,struct dirent64 * buf,size_t nbyte)9348b4cf837Sjv s10_getdents64(sysret_t *rval, int fd, struct dirent64 *buf, size_t nbyte)
9358b4cf837Sjv {
9368b4cf837Sjv 	return (s10_getdents_common(rval, fd, (char *)buf, nbyte,
9378b4cf837Sjv 	    SYS_getdents64, offsetof(struct dirent64, d_name),
9388b4cf837Sjv 	    offsetof(struct dirent64, d_reclen)));
9398b4cf837Sjv }
9408b4cf837Sjv #endif	/* !_LP64 */
9418b4cf837Sjv 
942f3f1e74cS #define	S10_TRIVIAL_ACL_CNT	6
943f3f1e74cS #define	NATIVE_TRIVIAL_ACL_CNT	3
944f3f1e74cS 
945f3f1e74cS /*
946f3f1e74cS  * Check if the ACL qualifies as a trivial ACL based on the native
947f3f1e74cS  * interpretation.
948f3f1e74cS  */
949f3f1e74cS static boolean_t
has_trivial_native_acl(int cmd,int cnt,const char * fname,int fd)950f3f1e74cS has_trivial_native_acl(int cmd, int cnt, const char *fname, int fd)
951f3f1e74cS {
952f3f1e74cS 	int i, err;
953f3f1e74cS 	sysret_t rval;
954f3f1e74cS 	ace_t buf[NATIVE_TRIVIAL_ACL_CNT];
955f3f1e74cS 
956f3f1e74cS 	if (fname != NULL)
957f3f1e74cS 		err = __systemcall(&rval, SYS_pathconf + 1024, fname,
958f3f1e74cS 		    _PC_ACL_ENABLED);
959f3f1e74cS 	else
960f3f1e74cS 		err = __systemcall(&rval, SYS_fpathconf + 1024, fd,
961f3f1e74cS 		    _PC_ACL_ENABLED);
962f3f1e74cS 	if (err != 0 || rval.sys_rval1 != _ACL_ACE_ENABLED)
963f3f1e74cS 		return (B_FALSE);
964f3f1e74cS 
965f3f1e74cS 	/*
966f3f1e74cS 	 * If we just got the ACL cnt, we don't need to get it again, its
967f3f1e74cS 	 * passed in as the cnt arg.
968f3f1e74cS 	 */
969f3f1e74cS 	if (cmd != ACE_GETACLCNT) {
970f3f1e74cS 		if (fname != NULL) {
971f3f1e74cS 			if (__systemcall(&rval, SYS_acl + 1024, fname,
972f3f1e74cS 			    ACE_GETACLCNT, 0, NULL) != 0)
973f3f1e74cS 				return (B_FALSE);
974f3f1e74cS 		} else {
975f3f1e74cS 			if (__systemcall(&rval, SYS_facl + 1024, fd,
976f3f1e74cS 			    ACE_GETACLCNT, 0, NULL) != 0)
977f3f1e74cS 				return (B_FALSE);
978f3f1e74cS 		}
979f3f1e74cS 		cnt = rval.sys_rval1;
980f3f1e74cS 	}
981f3f1e74cS 
982f3f1e74cS 	if (cnt != NATIVE_TRIVIAL_ACL_CNT)
983f3f1e74cS 		return (B_FALSE);
984f3f1e74cS 
985f3f1e74cS 	if (fname != NULL) {
986f3f1e74cS 		if (__systemcall(&rval, SYS_acl + 1024, fname, ACE_GETACL, cnt,
987f3f1e74cS 		    buf) != 0)
988f3f1e74cS 			return (B_FALSE);
989f3f1e74cS 	} else {
990f3f1e74cS 		if (__systemcall(&rval, SYS_facl + 1024, fd, ACE_GETACL, cnt,
991f3f1e74cS 		    buf) != 0)
992f3f1e74cS 			return (B_FALSE);
993f3f1e74cS 	}
994f3f1e74cS 
995f3f1e74cS 	/*
996f3f1e74cS 	 * The following is based on the logic from the native OS
997f3f1e74cS 	 * ace_trivial_common() to determine if the native ACL is trivial.
998f3f1e74cS 	 */
999f3f1e74cS 	for (i = 0; i < cnt; i++) {
1000f3f1e74cS 		switch (buf[i].a_flags & ACE_TYPE_FLAGS) {
1001f3f1e74cS 		case ACE_OWNER:
1002f3f1e74cS 		case ACE_GROUP|ACE_IDENTIFIER_GROUP:
1003f3f1e74cS 		case ACE_EVERYONE:
1004f3f1e74cS 			break;
1005f3f1e74cS 		default:
1006f3f1e74cS 			return (B_FALSE);
1007f3f1e74cS 		}
1008f3f1e74cS 
1009f3f1e74cS 		if (buf[i].a_flags & (ACE_FILE_INHERIT_ACE|
1010f3f1e74cS 		    ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
1011f3f1e74cS 		    ACE_INHERIT_ONLY_ACE))
1012f3f1e74cS 			return (B_FALSE);
1013f3f1e74cS 
1014f3f1e74cS 		/*
1015f3f1e74cS 		 * Special check for some special bits
1016f3f1e74cS 		 *
1017f3f1e74cS 		 * Don't allow anybody to deny reading basic
1018f3f1e74cS 		 * attributes or a files ACL.
1019f3f1e74cS 		 */
1020f3f1e74cS 		if (buf[i].a_access_mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&
1021f3f1e74cS 		    buf[i].a_type == ACE_ACCESS_DENIED_ACE_TYPE)
1022f3f1e74cS 			return (B_FALSE);
1023f3f1e74cS 
1024f3f1e74cS 		/*
1025f3f1e74cS 		 * Delete permissions are never set by default
1026f3f1e74cS 		 */
1027f3f1e74cS 		if (buf[i].a_access_mask & (ACE_DELETE|ACE_DELETE_CHILD))
1028f3f1e74cS 			return (B_FALSE);
1029f3f1e74cS 		/*
1030f3f1e74cS 		 * only allow owner@ to have
1031f3f1e74cS 		 * write_acl/write_owner/write_attributes/write_xattr/
1032f3f1e74cS 		 */
1033f3f1e74cS 		if (buf[i].a_type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
1034f3f1e74cS 		    (!(buf[i].a_flags & ACE_OWNER) && (buf[i].a_access_mask &
1035f3f1e74cS 		    (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
1036f3f1e74cS 		    ACE_WRITE_NAMED_ATTRS))))
1037f3f1e74cS 			return (B_FALSE);
1038f3f1e74cS 
1039f3f1e74cS 	}
1040f3f1e74cS 
1041f3f1e74cS 	return (B_TRUE);
1042f3f1e74cS }
1043f3f1e74cS 
1044f3f1e74cS /*
1045f3f1e74cS  * The following logic is based on the S10 adjust_ace_pair_common() code.
1046f3f1e74cS  */
1047f3f1e74cS static void
s10_adjust_ace_mask(void * pair,size_t access_off,size_t pairsize,mode_t mode)1048f3f1e74cS s10_adjust_ace_mask(void *pair, size_t access_off, size_t pairsize, mode_t mode)
1049f3f1e74cS {
1050f3f1e74cS 	char *datap = (char *)pair;
1051f3f1e74cS 	uint32_t *amask0 = (uint32_t *)(uintptr_t)(datap + access_off);
1052f3f1e74cS 	uint32_t *amask1 = (uint32_t *)(uintptr_t)(datap + pairsize +
1053f3f1e74cS 	    access_off);
1054f3f1e74cS 
1055f3f1e74cS 	if (mode & S_IROTH)
1056f3f1e74cS 		*amask1 |= ACE_READ_DATA;
1057f3f1e74cS 	else
1058f3f1e74cS 		*amask0 |= ACE_READ_DATA;
1059f3f1e74cS 	if (mode & S_IWOTH)
1060f3f1e74cS 		*amask1 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
1061f3f1e74cS 	else
1062f3f1e74cS 		*amask0 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
1063f3f1e74cS 	if (mode & S_IXOTH)
1064f3f1e74cS 		*amask1 |= ACE_EXECUTE;
1065f3f1e74cS 	else
1066f3f1e74cS 		*amask0 |= ACE_EXECUTE;
1067f3f1e74cS }
1068f3f1e74cS 
1069f3f1e74cS /*
1070f3f1e74cS  * Construct a trivial S10 style ACL.
1071f3f1e74cS  */
1072f3f1e74cS static int
make_trivial_s10_acl(const char * fname,int fd,ace_t * bp)1073f3f1e74cS make_trivial_s10_acl(const char *fname, int fd, ace_t *bp)
1074f3f1e74cS {
1075f3f1e74cS 	int err;
1076f3f1e74cS 	sysret_t rval;
1077f3f1e74cS 	struct stat64 buf;
1078f3f1e74cS 	ace_t trivial_s10_acl[] = {
1079f3f1e74cS 		{(uint_t)-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE},
1080f3f1e74cS 		{(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
1081f3f1e74cS 		    ACE_WRITE_NAMED_ATTRS, ACE_OWNER,
1082f3f1e74cS 		    ACE_ACCESS_ALLOWED_ACE_TYPE},
1083f3f1e74cS 		{(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
1084f3f1e74cS 		    ACE_ACCESS_DENIED_ACE_TYPE},
1085f3f1e74cS 		{(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
1086f3f1e74cS 		    ACE_ACCESS_ALLOWED_ACE_TYPE},
1087f3f1e74cS 		{(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
1088f3f1e74cS 		    ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE,
1089f3f1e74cS 		    ACE_ACCESS_DENIED_ACE_TYPE},
1090f3f1e74cS 		{(uint_t)-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|
1091f3f1e74cS 		    ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE, ACE_EVERYONE,
1092f3f1e74cS 		    ACE_ACCESS_ALLOWED_ACE_TYPE}
1093f3f1e74cS 	};
1094f3f1e74cS 
1095f3f1e74cS 	if (fname != NULL) {
1096f3f1e74cS 		if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, AT_FDCWD,
1097f3f1e74cS 		    fname, &buf, 0)) != 0)
1098f3f1e74cS 			return (err);
1099f3f1e74cS 	} else {
1100f3f1e74cS 		if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, fd,
1101f3f1e74cS 		    NULL, &buf, 0)) != 0)
1102f3f1e74cS 			return (err);
1103f3f1e74cS 	}
1104f3f1e74cS 
1105f3f1e74cS 	s10_adjust_ace_mask(&trivial_s10_acl[0], offsetof(ace_t, a_access_mask),
1106f3f1e74cS 	    sizeof (ace_t), (buf.st_mode & 0700) >> 6);
1107f3f1e74cS 	s10_adjust_ace_mask(&trivial_s10_acl[2], offsetof(ace_t, a_access_mask),
1108f3f1e74cS 	    sizeof (ace_t), (buf.st_mode & 0070) >> 3);
1109f3f1e74cS 	s10_adjust_ace_mask(&trivial_s10_acl[4], offsetof(ace_t, a_access_mask),
1110f3f1e74cS 	    sizeof (ace_t), buf.st_mode & 0007);
1111f3f1e74cS 
1112f3f1e74cS 	if (brand_uucopy(&trivial_s10_acl, bp, sizeof (trivial_s10_acl)) != 0)
1113f3f1e74cS 		return (EFAULT);
1114f3f1e74cS 
1115f3f1e74cS 	return (0);
1116f3f1e74cS }
1117f3f1e74cS 
1118f3f1e74cS /*
1119f3f1e74cS  * The definition of a trivial ace-style ACL (used by ZFS and NFSv4) has been
1120f3f1e74cS  * simplified since S10.  Instead of 6 entries on a trivial S10 ACE ACL we now
1121f3f1e74cS  * have 3 streamlined entries.  The new, simpler trivial style confuses S10
1122f3f1e74cS  * commands such as 'ls -v' or 'cp -p' which don't see the expected S10 trivial
1123f3f1e74cS  * ACL entries and thus assume that there is a complex ACL on the file.
1124f3f1e74cS  *
1125f3f1e74cS  * See: PSARC/2010/029 Improved ACL interoperability
1126f3f1e74cS  *
1127f3f1e74cS  * Note that the trival ACL detection code is implemented in acl_trival() in
1128f3f1e74cS  * lib/libsec/common/aclutils.c.  It always uses the acl() syscall (not the
1129f3f1e74cS  * facl syscall) to determine if an ACL is trivial.  However, we emulate both
1130f3f1e74cS  * acl() and facl() so that the two provide consistent results.
1131f3f1e74cS  *
1132f3f1e74cS  * We don't currently try to emulate setting of ACLs since the primary
1133f3f1e74cS  * consumer of this feature is SMB or NFSv4 servers, neither of which are
1134f3f1e74cS  * supported in solaris10-branded zones.  If ACLs are used they must be set on
1135f3f1e74cS  * files using the native OS interpretation.
1136f3f1e74cS  */
1137f3f1e74cS int
s10_acl(sysret_t * rval,const char * fname,int cmd,int nentries,void * aclbufp)1138f3f1e74cS s10_acl(sysret_t *rval, const char *fname, int cmd, int nentries, void *aclbufp)
1139f3f1e74cS {
1140f3f1e74cS 	int res;
1141f3f1e74cS 
1142f3f1e74cS 	res = __systemcall(rval, SYS_acl + 1024, fname, cmd, nentries, aclbufp);
1143f3f1e74cS 
1144f3f1e74cS 	switch (cmd) {
1145f3f1e74cS 	case ACE_GETACLCNT:
1146f3f1e74cS 		if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
1147f3f1e74cS 		    rval->sys_rval1, fname, 0)) {
1148f3f1e74cS 			rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1149f3f1e74cS 		}
1150f3f1e74cS 		break;
1151f3f1e74cS 	case ACE_GETACL:
1152f3f1e74cS 		if (res == 0 &&
1153f3f1e74cS 		    has_trivial_native_acl(ACE_GETACL, 0, fname, 0) &&
1154f3f1e74cS 		    nentries >= S10_TRIVIAL_ACL_CNT) {
1155f3f1e74cS 			res = make_trivial_s10_acl(fname, 0, aclbufp);
1156f3f1e74cS 			rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1157f3f1e74cS 		}
1158f3f1e74cS 		break;
1159f3f1e74cS 	}
1160f3f1e74cS 
1161f3f1e74cS 	return (res);
1162f3f1e74cS }
1163f3f1e74cS 
1164f3f1e74cS int
s10_facl(sysret_t * rval,int fdes,int cmd,int nentries,void * aclbufp)1165f3f1e74cS s10_facl(sysret_t *rval, int fdes, int cmd, int nentries, void *aclbufp)
1166f3f1e74cS {
1167f3f1e74cS 	int res;
1168f3f1e74cS 
1169f3f1e74cS 	res = __systemcall(rval, SYS_facl + 1024, fdes, cmd, nentries, aclbufp);
1170f3f1e74cS 
1171f3f1e74cS 	switch (cmd) {
1172f3f1e74cS 	case ACE_GETACLCNT:
1173f3f1e74cS 		if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
1174f3f1e74cS 		    rval->sys_rval1, NULL, fdes)) {
1175f3f1e74cS 			rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1176f3f1e74cS 		}
1177f3f1e74cS 		break;
1178f3f1e74cS 	case ACE_GETACL:
1179f3f1e74cS 		if (res == 0 &&
1180f3f1e74cS 		    has_trivial_native_acl(ACE_GETACL, 0, NULL, fdes) &&
1181f3f1e74cS 		    nentries >= S10_TRIVIAL_ACL_CNT) {
1182f3f1e74cS 			res = make_trivial_s10_acl(NULL, fdes, aclbufp);
1183f3f1e74cS 			rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1184f3f1e74cS 		}
1185f3f1e74cS 		break;
1186f3f1e74cS 	}
1187f3f1e74cS 
1188f3f1e74cS 	return (res);
1189f3f1e74cS }
1190f3f1e74cS 
1191e71ca95cSGerald Jelinek #define	S10_AC_PROC		(0x1 << 28)
1192e71ca95cSGerald Jelinek #define	S10_AC_TASK		(0x2 << 28)
1193e71ca95cSGerald Jelinek #define	S10_AC_FLOW		(0x4 << 28)
1194e71ca95cSGerald Jelinek #define	S10_AC_MODE(x)		((x) & 0xf0000000)
1195e71ca95cSGerald Jelinek #define	S10_AC_OPTION(x)	((x) & 0x0fffffff)
1196e71ca95cSGerald Jelinek 
1197e71ca95cSGerald Jelinek /*
1198e71ca95cSGerald Jelinek  * The mode shift, mode mask and option mask for acctctl have changed.  The
1199e71ca95cSGerald Jelinek  * mode is currently the top full byte and the option is the lower 3 full bytes.
1200e71ca95cSGerald Jelinek  */
1201e71ca95cSGerald Jelinek int
s10_acctctl(sysret_t * rval,int cmd,void * buf,size_t bufsz)1202e71ca95cSGerald Jelinek s10_acctctl(sysret_t *rval, int cmd, void *buf, size_t bufsz)
1203e71ca95cSGerald Jelinek {
1204e71ca95cSGerald Jelinek 	int mode = S10_AC_MODE(cmd);
1205e71ca95cSGerald Jelinek 	int option = S10_AC_OPTION(cmd);
1206e71ca95cSGerald Jelinek 
1207e71ca95cSGerald Jelinek 	switch (mode) {
1208e71ca95cSGerald Jelinek 	case S10_AC_PROC:
1209e71ca95cSGerald Jelinek 		mode = AC_PROC;
1210e71ca95cSGerald Jelinek 		break;
1211e71ca95cSGerald Jelinek 	case S10_AC_TASK:
1212e71ca95cSGerald Jelinek 		mode = AC_TASK;
1213e71ca95cSGerald Jelinek 		break;
1214e71ca95cSGerald Jelinek 	case S10_AC_FLOW:
1215e71ca95cSGerald Jelinek 		mode = AC_FLOW;
1216e71ca95cSGerald Jelinek 		break;
1217e71ca95cSGerald Jelinek 	default:
121880e2ca85S 		return (B_TRUSS_POINT_3(rval, SYS_acctctl, EINVAL, cmd, buf,
1219e71ca95cSGerald Jelinek 		    bufsz));
1220e71ca95cSGerald Jelinek 	}
1221e71ca95cSGerald Jelinek 
1222e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_acctctl + 1024, mode | option, buf,
1223e71ca95cSGerald Jelinek 	    bufsz));
1224e71ca95cSGerald Jelinek }
1225e71ca95cSGerald Jelinek 
1226e71ca95cSGerald Jelinek /*
1227e71ca95cSGerald Jelinek  * The Audit Policy parameters have changed due to:
1228e71ca95cSGerald Jelinek  *    6466722 audituser and AUDIT_USER are defined, unused, undocumented and
1229e71ca95cSGerald Jelinek  *            should be removed.
1230e71ca95cSGerald Jelinek  *
1231e71ca95cSGerald Jelinek  * In S10 we had the following flag:
1232e71ca95cSGerald Jelinek  *	#define AUDIT_USER 0x0040
1233e71ca95cSGerald Jelinek  * which doesn't exist in Solaris Next where the subsequent flags are shifted
1234e71ca95cSGerald Jelinek  * down.  For example, in S10 we had:
1235e71ca95cSGerald Jelinek  *	#define AUDIT_GROUP     0x0080
1236e71ca95cSGerald Jelinek  * but on Solaris Next we have:
1237e71ca95cSGerald Jelinek  *	#define AUDIT_GROUP     0x0040
1238e71ca95cSGerald Jelinek  * AUDIT_GROUP has the value AUDIT_USER had in S10 and all of the subsequent
1239e71ca95cSGerald Jelinek  * bits are also shifted one place.
1240e71ca95cSGerald Jelinek  *
1241e71ca95cSGerald Jelinek  * When we're getting or setting the Audit Policy parameters we need to
1242e71ca95cSGerald Jelinek  * shift the outgoing or incoming bits into their proper positions.  Since
1243e71ca95cSGerald Jelinek  * S10_AUDIT_USER was always unused, we always clear that bit on A_GETPOLICY.
1244e71ca95cSGerald Jelinek  *
1245e71ca95cSGerald Jelinek  * The command we care about, BSM_AUDITCTL, passes the most parameters (3),
1246e71ca95cSGerald Jelinek  * so declare this function to take up to 4 args and just pass them on.
1247e71ca95cSGerald Jelinek  * The number of parameters for s10_auditsys needs to be equal to the BSM_*
1248e71ca95cSGerald Jelinek  * subcommand that has the most parameters, since we want to pass all
1249e71ca95cSGerald Jelinek  * parameters through, regardless of which subcommands we interpose on.
1250e71ca95cSGerald Jelinek  *
1251e71ca95cSGerald Jelinek  * Note that the auditsys system call uses the SYSENT_AP macro wrapper instead
1252e71ca95cSGerald Jelinek  * of the more common SYSENT_CI macro.  This means the return value is a
1253e71ca95cSGerald Jelinek  * SE_64RVAL so the syscall table uses RV_64RVAL.
1254e71ca95cSGerald Jelinek  */
1255e71ca95cSGerald Jelinek 
1256e71ca95cSGerald Jelinek #define	S10_AUDIT_HMASK	0xffffffc0
1257e71ca95cSGerald Jelinek #define	S10_AUDIT_LMASK	0x3f
1258005d3febSMarek Pospisil #define	S10_AUC_NOSPACE	0x3
1259e71ca95cSGerald Jelinek 
1260e71ca95cSGerald Jelinek int
s10_auditsys(sysret_t * rval,int bsmcmd,intptr_t a0,intptr_t a1,intptr_t a2)1261e71ca95cSGerald Jelinek s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2)
1262e71ca95cSGerald Jelinek {
126396093503SMarek Pospisil 	int	    err;
126496093503SMarek Pospisil 	uint32_t    m;
1265e71ca95cSGerald Jelinek 
1266e71ca95cSGerald Jelinek 	if (bsmcmd != BSM_AUDITCTL)
1267e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1,
1268e71ca95cSGerald Jelinek 		    a2));
1269e71ca95cSGerald Jelinek 
1270e71ca95cSGerald Jelinek 	if ((int)a0 == A_GETPOLICY) {
1271e71ca95cSGerald Jelinek 		if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
1272e71ca95cSGerald Jelinek 		    &m, a2)) != 0)
1273e71ca95cSGerald Jelinek 			return (err);
1274e71ca95cSGerald Jelinek 		m = ((m & S10_AUDIT_HMASK) << 1) | (m & S10_AUDIT_LMASK);
127580e2ca85S 		if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
1276e71ca95cSGerald Jelinek 			return (EFAULT);
1277e71ca95cSGerald Jelinek 		return (0);
1278e71ca95cSGerald Jelinek 
1279e71ca95cSGerald Jelinek 	} else if ((int)a0 == A_SETPOLICY) {
128080e2ca85S 		if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
1281e71ca95cSGerald Jelinek 			return (EFAULT);
1282e71ca95cSGerald Jelinek 		m = ((m >> 1) & S10_AUDIT_HMASK) | (m & S10_AUDIT_LMASK);
1283e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
1284e71ca95cSGerald Jelinek 		    a2));
1285005d3febSMarek Pospisil 	} else if ((int)a0 == A_GETCOND) {
1286005d3febSMarek Pospisil 		if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
1287005d3febSMarek Pospisil 		    &m, a2)) != 0)
1288005d3febSMarek Pospisil 			return (err);
1289005d3febSMarek Pospisil 		if (m == AUC_NOSPACE)
1290005d3febSMarek Pospisil 			m = S10_AUC_NOSPACE;
129180e2ca85S 		if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
1292005d3febSMarek Pospisil 			return (EFAULT);
1293005d3febSMarek Pospisil 		return (0);
1294005d3febSMarek Pospisil 	} else if ((int)a0 == A_SETCOND) {
129580e2ca85S 		if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
1296005d3febSMarek Pospisil 			return (EFAULT);
1297005d3febSMarek Pospisil 		if (m == S10_AUC_NOSPACE)
1298005d3febSMarek Pospisil 			m = AUC_NOSPACE;
1299005d3febSMarek Pospisil 		return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
1300005d3febSMarek Pospisil 		    a2));
1301e71ca95cSGerald Jelinek 	}
1302e71ca95cSGerald Jelinek 
1303e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1, a2));
1304e71ca95cSGerald Jelinek }
1305e71ca95cSGerald Jelinek 
1306e71ca95cSGerald Jelinek /*
1307e71ca95cSGerald Jelinek  * Determine whether the executable passed to SYS_exec or SYS_execve is a
1308e71ca95cSGerald Jelinek  * native executable.  The s10_npreload.so invokes the B_S10_NATIVE brand
1309e71ca95cSGerald Jelinek  * operation which patches up the processes exec info to eliminate any trace
1310e71ca95cSGerald Jelinek  * of the wrapper.  That will make pgrep and other commands that examine
1311e71ca95cSGerald Jelinek  * process' executable names and command-line parameters work properly.
1312e71ca95cSGerald Jelinek  */
1313e71ca95cSGerald Jelinek static int
s10_exec_native(sysret_t * rval,const char * fname,const char ** argp,const char ** envp)1314e71ca95cSGerald Jelinek s10_exec_native(sysret_t *rval, const char *fname, const char **argp,
1315e71ca95cSGerald Jelinek     const char **envp)
1316e71ca95cSGerald Jelinek {
1317e71ca95cSGerald Jelinek 	const char *filename = fname;
1318e71ca95cSGerald Jelinek 	char path[64];
1319e71ca95cSGerald Jelinek 	int err;
1320e71ca95cSGerald Jelinek 
1321e71ca95cSGerald Jelinek 	/* Get a copy of the executable we're trying to run */
1322e71ca95cSGerald Jelinek 	path[0] = '\0';
132380e2ca85S 	(void) brand_uucopystr(filename, path, sizeof (path));
1324e71ca95cSGerald Jelinek 
1325e71ca95cSGerald Jelinek 	/* Check if we're trying to run a native binary */
1326e71ca95cSGerald Jelinek 	if (strncmp(path, "/.SUNWnative/usr/lib/brand/solaris10/s10_native",
1327e71ca95cSGerald Jelinek 	    sizeof (path)) != 0)
1328e71ca95cSGerald Jelinek 		return (0);
1329e71ca95cSGerald Jelinek 
1330e71ca95cSGerald Jelinek 	/* Skip the first element in the argv array */
1331e71ca95cSGerald Jelinek 	argp++;
1332e71ca95cSGerald Jelinek 
1333e71ca95cSGerald Jelinek 	/*
1334e71ca95cSGerald Jelinek 	 * The the path of the dynamic linker is the second parameter
1335e71ca95cSGerald Jelinek 	 * of s10_native_exec().
1336e71ca95cSGerald Jelinek 	 */
133780e2ca85S 	if (brand_uucopy(argp, &filename, sizeof (char *)) != 0)
1338e71ca95cSGerald Jelinek 		return (EFAULT);
1339e71ca95cSGerald Jelinek 
1340e71ca95cSGerald Jelinek 	/* If an exec call succeeds, it never returns */
1341e71ca95cSGerald Jelinek 	err = __systemcall(rval, SYS_brand + 1024, B_EXEC_NATIVE, filename,
1342e71ca95cSGerald Jelinek 	    argp, envp, NULL, NULL, NULL);
134380e2ca85S 	brand_assert(err != 0);
1344e71ca95cSGerald Jelinek 	return (err);
1345e71ca95cSGerald Jelinek }
1346e71ca95cSGerald Jelinek 
1347e71ca95cSGerald Jelinek /*
1348e71ca95cSGerald Jelinek  * Interpose on the SYS_exec syscall to detect native wrappers.
1349e71ca95cSGerald Jelinek  */
1350e71ca95cSGerald Jelinek int
s10_exec(sysret_t * rval,const char * fname,const char ** argp)1351e71ca95cSGerald Jelinek s10_exec(sysret_t *rval, const char *fname, const char **argp)
1352e71ca95cSGerald Jelinek {
1353e71ca95cSGerald Jelinek 	int err;
1354e71ca95cSGerald Jelinek 
1355e71ca95cSGerald Jelinek 	if ((err = s10_exec_native(rval, fname, argp, NULL)) != 0)
1356e71ca95cSGerald Jelinek 		return (err);
1357e71ca95cSGerald Jelinek 
1358e71ca95cSGerald Jelinek 	/* If an exec call succeeds, it never returns */
1359*2b395c3cSAndy Fiddaman 	err = __systemcall(rval, SYS_execve + 1024, fname, argp, NULL, 0);
136080e2ca85S 	brand_assert(err != 0);
1361e71ca95cSGerald Jelinek 	return (err);
1362e71ca95cSGerald Jelinek }
1363e71ca95cSGerald Jelinek 
1364e71ca95cSGerald Jelinek /*
1365e71ca95cSGerald Jelinek  * Interpose on the SYS_execve syscall to detect native wrappers.
1366e71ca95cSGerald Jelinek  */
1367e71ca95cSGerald Jelinek int
s10_execve(sysret_t * rval,const char * fname,const char ** argp,const char ** envp)1368e71ca95cSGerald Jelinek s10_execve(sysret_t *rval, const char *fname, const char **argp,
1369e71ca95cSGerald Jelinek     const char **envp)
1370e71ca95cSGerald Jelinek {
1371e71ca95cSGerald Jelinek 	int err;
1372e71ca95cSGerald Jelinek 
1373e71ca95cSGerald Jelinek 	if ((err = s10_exec_native(rval, fname, argp, envp)) != 0)
1374e71ca95cSGerald Jelinek 		return (err);
1375e71ca95cSGerald Jelinek 
1376e71ca95cSGerald Jelinek 	/* If an exec call succeeds, it never returns */
1377*2b395c3cSAndy Fiddaman 	err = __systemcall(rval, SYS_execve + 1024, fname, argp, envp, 0);
137880e2ca85S 	brand_assert(err != 0);
1379e71ca95cSGerald Jelinek 	return (err);
1380e71ca95cSGerald Jelinek }
1381e71ca95cSGerald Jelinek 
1382e71ca95cSGerald Jelinek /*
1383e71ca95cSGerald Jelinek  * S10's issetugid() syscall is now a subcode to privsys().
1384e71ca95cSGerald Jelinek  */
1385e71ca95cSGerald Jelinek static int
s10_issetugid(sysret_t * rval)1386e71ca95cSGerald Jelinek s10_issetugid(sysret_t *rval)
1387e71ca95cSGerald Jelinek {
1388e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_privsys + 1024, PRIVSYS_ISSETUGID,
1389e71ca95cSGerald Jelinek 	    0, 0, 0, 0, 0));
1390e71ca95cSGerald Jelinek }
1391e71ca95cSGerald Jelinek 
1392b49b27dcSTheo Schlossnagle /*
1393b49b27dcSTheo Schlossnagle  * S10's socket() syscall does not split type and flags
1394b49b27dcSTheo Schlossnagle  */
1395b49b27dcSTheo Schlossnagle static int
s10_so_socket(sysret_t * rval,int domain,int type,int protocol,char * devpath,int version)1396b49b27dcSTheo Schlossnagle s10_so_socket(sysret_t *rval, int domain, int type, int protocol,
1397b49b27dcSTheo Schlossnagle     char *devpath, int version)
1398b49b27dcSTheo Schlossnagle {
1399b49b27dcSTheo Schlossnagle 	if ((type & ~SOCK_TYPE_MASK) != 0) {
1400b49b27dcSTheo Schlossnagle 		errno = EINVAL;
1401b49b27dcSTheo Schlossnagle 		return (-1);
1402b49b27dcSTheo Schlossnagle 	}
1403b49b27dcSTheo Schlossnagle 	return (__systemcall(rval, SYS_so_socket + 1024, domain, type,
1404b49b27dcSTheo Schlossnagle 	    protocol, devpath, version));
1405b49b27dcSTheo Schlossnagle }
1406b49b27dcSTheo Schlossnagle 
1407b49b27dcSTheo Schlossnagle /*
1408b49b27dcSTheo Schlossnagle  * S10's pipe() syscall has a different calling convention
1409b49b27dcSTheo Schlossnagle  */
1410b49b27dcSTheo Schlossnagle static int
s10_pipe(sysret_t * rval)1411b49b27dcSTheo Schlossnagle s10_pipe(sysret_t *rval)
1412b49b27dcSTheo Schlossnagle {
1413b49b27dcSTheo Schlossnagle 	int fds[2], err;
1414b49b27dcSTheo Schlossnagle 	if ((err = __systemcall(rval, SYS_pipe + 1024, fds, 0)) != 0)
1415b49b27dcSTheo Schlossnagle 		return (err);
1416b49b27dcSTheo Schlossnagle 
1417b49b27dcSTheo Schlossnagle 	rval->sys_rval1 = fds[0];
1418b49b27dcSTheo Schlossnagle 	rval->sys_rval2 = fds[1];
1419b49b27dcSTheo Schlossnagle 	return (0);
1420b49b27dcSTheo Schlossnagle }
1421b49b27dcSTheo Schlossnagle 
1422b49b27dcSTheo Schlossnagle /*
1423b49b27dcSTheo Schlossnagle  * S10's accept() syscall takes three arguments
1424b49b27dcSTheo Schlossnagle  */
1425b49b27dcSTheo Schlossnagle static int
s10_accept(sysret_t * rval,int sock,struct sockaddr * addr,uint_t * addrlen,int version)1426b49b27dcSTheo Schlossnagle s10_accept(sysret_t *rval, int sock, struct sockaddr *addr, uint_t *addrlen,
1427b49b27dcSTheo Schlossnagle     int version)
1428b49b27dcSTheo Schlossnagle {
1429b49b27dcSTheo Schlossnagle 	return (__systemcall(rval, SYS_accept + 1024, sock, addr, addrlen,
1430b49b27dcSTheo Schlossnagle 	    version, 0));
1431b49b27dcSTheo Schlossnagle }
1432b49b27dcSTheo Schlossnagle 
1433e71ca95cSGerald Jelinek static long
s10_uname(sysret_t * rv,uintptr_t p1)1434e71ca95cSGerald Jelinek s10_uname(sysret_t *rv, uintptr_t p1)
1435e71ca95cSGerald Jelinek {
1436e71ca95cSGerald Jelinek 	struct utsname un, *unp = (struct utsname *)p1;
1437e71ca95cSGerald Jelinek 	int rev, err;
1438e71ca95cSGerald Jelinek 
1439e71ca95cSGerald Jelinek 	if ((err = __systemcall(rv, SYS_uname + 1024, &un)) != 0)
1440e71ca95cSGerald Jelinek 		return (err);
1441e71ca95cSGerald Jelinek 
1442e71ca95cSGerald Jelinek 	rev = atoi(&un.release[2]);
144380e2ca85S 	brand_assert(rev >= 11);
1444e71ca95cSGerald Jelinek 	bzero(un.release, _SYS_NMLN);
1445e71ca95cSGerald Jelinek 	(void) strlcpy(un.release, S10_UTS_RELEASE, _SYS_NMLN);
1446e71ca95cSGerald Jelinek 	bzero(un.version, _SYS_NMLN);
1447e71ca95cSGerald Jelinek 	(void) strlcpy(un.version, S10_UTS_VERSION, _SYS_NMLN);
1448e71ca95cSGerald Jelinek 
1449e71ca95cSGerald Jelinek 	/* copy out the modified uname info */
145080e2ca85S 	return (brand_uucopy(&un, unp, sizeof (un)));
1451e71ca95cSGerald Jelinek }
1452e71ca95cSGerald Jelinek 
1453bdf0047cSRoger A. Faulkner int
s10_sysconfig(sysret_t * rv,int which)1454bdf0047cSRoger A. Faulkner s10_sysconfig(sysret_t *rv, int which)
1455bdf0047cSRoger A. Faulkner {
1456bdf0047cSRoger A. Faulkner 	long value;
1457bdf0047cSRoger A. Faulkner 
1458bdf0047cSRoger A. Faulkner 	/*
1459bdf0047cSRoger A. Faulkner 	 * We must interpose on the sysconfig(2) requests
1460bdf0047cSRoger A. Faulkner 	 * that deal with the realtime signal number range.
1461bdf0047cSRoger A. Faulkner 	 * All others get passed to the native sysconfig(2).
1462bdf0047cSRoger A. Faulkner 	 */
1463bdf0047cSRoger A. Faulkner 	switch (which) {
1464bdf0047cSRoger A. Faulkner 	case _CONFIG_RTSIG_MAX:
1465bdf0047cSRoger A. Faulkner 		value = S10_SIGRTMAX - S10_SIGRTMIN + 1;
1466bdf0047cSRoger A. Faulkner 		break;
1467bdf0047cSRoger A. Faulkner 	case _CONFIG_SIGRT_MIN:
1468bdf0047cSRoger A. Faulkner 		value = S10_SIGRTMIN;
1469bdf0047cSRoger A. Faulkner 		break;
1470bdf0047cSRoger A. Faulkner 	case _CONFIG_SIGRT_MAX:
1471bdf0047cSRoger A. Faulkner 		value = S10_SIGRTMAX;
1472bdf0047cSRoger A. Faulkner 		break;
1473bdf0047cSRoger A. Faulkner 	default:
1474bdf0047cSRoger A. Faulkner 		return (__systemcall(rv, SYS_sysconfig + 1024, which));
1475bdf0047cSRoger A. Faulkner 	}
1476bdf0047cSRoger A. Faulkner 
147780e2ca85S 	(void) B_TRUSS_POINT_1(rv, SYS_sysconfig, 0, which);
1478bdf0047cSRoger A. Faulkner 	rv->sys_rval1 = value;
1479bdf0047cSRoger A. Faulkner 	rv->sys_rval2 = 0;
1480bdf0047cSRoger A. Faulkner 
1481bdf0047cSRoger A. Faulkner 	return (0);
1482bdf0047cSRoger A. Faulkner }
1483bdf0047cSRoger A. Faulkner 
1484e71ca95cSGerald Jelinek int
s10_sysinfo(sysret_t * rv,int command,char * buf,long count)1485e71ca95cSGerald Jelinek s10_sysinfo(sysret_t *rv, int command, char *buf, long count)
1486e71ca95cSGerald Jelinek {
1487e71ca95cSGerald Jelinek 	char *value;
1488e71ca95cSGerald Jelinek 	int len;
1489e71ca95cSGerald Jelinek 
1490e71ca95cSGerald Jelinek 	/*
1491e71ca95cSGerald Jelinek 	 * We must interpose on the sysinfo(2) commands SI_RELEASE and
1492e71ca95cSGerald Jelinek 	 * SI_VERSION; all others get passed to the native sysinfo(2)
1493e71ca95cSGerald Jelinek 	 * command.
1494e71ca95cSGerald Jelinek 	 */
1495e71ca95cSGerald Jelinek 	switch (command) {
1496e71ca95cSGerald Jelinek 		case SI_RELEASE:
1497e71ca95cSGerald Jelinek 			value = S10_UTS_RELEASE;
1498e71ca95cSGerald Jelinek 			break;
1499e71ca95cSGerald Jelinek 
1500e71ca95cSGerald Jelinek 		case SI_VERSION:
1501e71ca95cSGerald Jelinek 			value = S10_UTS_VERSION;
1502e71ca95cSGerald Jelinek 			break;
1503e71ca95cSGerald Jelinek 
1504e71ca95cSGerald Jelinek 		default:
1505e71ca95cSGerald Jelinek 			/*
1506e71ca95cSGerald Jelinek 			 * The default action is to pass the command to the
1507e71ca95cSGerald Jelinek 			 * native sysinfo(2) syscall.
1508e71ca95cSGerald Jelinek 			 */
1509e71ca95cSGerald Jelinek 			return (__systemcall(rv, SYS_systeminfo + 1024,
1510e71ca95cSGerald Jelinek 			    command, buf, count));
1511e71ca95cSGerald Jelinek 	}
1512e71ca95cSGerald Jelinek 
1513e71ca95cSGerald Jelinek 	len = strlen(value) + 1;
1514e71ca95cSGerald Jelinek 	if (count > 0) {
151580e2ca85S 		if (brand_uucopystr(value, buf, count) != 0)
1516e71ca95cSGerald Jelinek 			return (EFAULT);
1517e71ca95cSGerald Jelinek 
151880e2ca85S 		/*
151980e2ca85S 		 * Assure NULL termination of buf as brand_uucopystr() doesn't.
152080e2ca85S 		 */
152180e2ca85S 		if (len > count && brand_uucopy("\0", buf + (count - 1), 1)
152280e2ca85S 		    != 0)
1523e71ca95cSGerald Jelinek 			return (EFAULT);
1524e71ca95cSGerald Jelinek 	}
1525e71ca95cSGerald Jelinek 
1526e71ca95cSGerald Jelinek 	/*
1527e71ca95cSGerald Jelinek 	 * On success, sysinfo(2) returns the size of buffer required to hold
1528e71ca95cSGerald Jelinek 	 * the complete value plus its terminating NULL byte.
1529e71ca95cSGerald Jelinek 	 */
153080e2ca85S 	(void) B_TRUSS_POINT_3(rv, SYS_systeminfo, 0, command, buf, count);
1531e71ca95cSGerald Jelinek 	rv->sys_rval1 = len;
1532e71ca95cSGerald Jelinek 	rv->sys_rval2 = 0;
1533e71ca95cSGerald Jelinek 	return (0);
1534e71ca95cSGerald Jelinek }
1535e71ca95cSGerald Jelinek 
15368fd04b83SRoger A. Faulkner #if defined(__x86)
15378fd04b83SRoger A. Faulkner #if defined(__amd64)
1538e71ca95cSGerald Jelinek /*
1539e71ca95cSGerald Jelinek  * 64-bit x86 LWPs created by SYS_lwp_create start here if they need to set
1540e71ca95cSGerald Jelinek  * their %fs registers to the legacy Solaris 10 selector value.
1541e71ca95cSGerald Jelinek  *
1542e71ca95cSGerald Jelinek  * This function does three things:
1543e71ca95cSGerald Jelinek  *
1544e71ca95cSGerald Jelinek  *	1.  Trap to the kernel so that it can set %fs to the legacy Solaris 10
1545e71ca95cSGerald Jelinek  *	    selector value.
1546e71ca95cSGerald Jelinek  *	2.  Read the LWP's true entry point (the entry point supplied by libc
1547e71ca95cSGerald Jelinek  *	    when SYS_lwp_create was invoked) from %r14.
1548e71ca95cSGerald Jelinek  *	3.  Eliminate this function's stack frame and pass control to the LWP's
1549e71ca95cSGerald Jelinek  *	    true entry point.
1550e71ca95cSGerald Jelinek  *
1551e71ca95cSGerald Jelinek  * See the comment above s10_lwp_create_correct_fs() (see below) for the reason
1552e71ca95cSGerald Jelinek  * why this function exists.
1553e71ca95cSGerald Jelinek  */
1554e71ca95cSGerald Jelinek /*ARGSUSED*/
1555e71ca95cSGerald Jelinek static void
s10_lwp_create_entry_point(void * ulwp_structp)1556e71ca95cSGerald Jelinek s10_lwp_create_entry_point(void *ulwp_structp)
1557e71ca95cSGerald Jelinek {
1558e71ca95cSGerald Jelinek 	sysret_t rval;
1559e71ca95cSGerald Jelinek 
1560e71ca95cSGerald Jelinek 	/*
1561e71ca95cSGerald Jelinek 	 * The new LWP's %fs register is initially zero, but libc won't
1562e71ca95cSGerald Jelinek 	 * function correctly when %fs is zero.  Change the LWP's %fs register
1563e71ca95cSGerald Jelinek 	 * via SYS_brand.
1564e71ca95cSGerald Jelinek 	 */
1565e71ca95cSGerald Jelinek 	(void) __systemcall(&rval, SYS_brand + 1024, B_S10_FSREGCORRECTION);
1566e71ca95cSGerald Jelinek 
1567e71ca95cSGerald Jelinek 	/*
1568e71ca95cSGerald Jelinek 	 * Jump to the true entry point, which is stored in %r14.
1569e71ca95cSGerald Jelinek 	 * Remove our stack frame before jumping so that
1570e71ca95cSGerald Jelinek 	 * s10_lwp_create_entry_point() won't be seen in stack traces.
1571e71ca95cSGerald Jelinek 	 *
1572e71ca95cSGerald Jelinek 	 * NOTE: s10_lwp_create_entry_point() pushes %r12 onto its stack frame
1573e71ca95cSGerald Jelinek 	 * so that it can use it as a temporary register.  We don't restore %r12
1574e71ca95cSGerald Jelinek 	 * in this assembly block because we don't care about its value (and
1575e71ca95cSGerald Jelinek 	 * neither does _lwp_start()).  Besides, the System V ABI AMD64
1576e71ca95cSGerald Jelinek 	 * Actirecture Processor Supplement doesn't specify that %r12 should
1577e71ca95cSGerald Jelinek 	 * have a special value when LWPs start, so we can ignore its value when
1578e71ca95cSGerald Jelinek 	 * we jump to the true entry point.  Furthermore, %r12 is a callee-saved
1579e71ca95cSGerald Jelinek 	 * register, so the true entry point should push %r12 onto its stack
1580e71ca95cSGerald Jelinek 	 * before using the register.  We ignore %r14 after we read it for
1581e71ca95cSGerald Jelinek 	 * similar reasons.
1582e71ca95cSGerald Jelinek 	 *
1583e71ca95cSGerald Jelinek 	 * NOTE: The compiler will generate a function epilogue for this
1584e71ca95cSGerald Jelinek 	 * function despite the fact that the LWP will never execute it.
1585e71ca95cSGerald Jelinek 	 * We could hand-code this entire function in assembly to eliminate
1586e71ca95cSGerald Jelinek 	 * the epilogue, but the epilogue is only three or four instructions,
1587e71ca95cSGerald Jelinek 	 * so we wouldn't save much space.  Besides, why would we want
1588e71ca95cSGerald Jelinek 	 * to create yet another ugly, hard-to-maintain assembly function when
1589e71ca95cSGerald Jelinek 	 * we could write most of it in C?
1590e71ca95cSGerald Jelinek 	 */
1591e71ca95cSGerald Jelinek 	__asm__ __volatile__(
1592e71ca95cSGerald Jelinek 	    "movq %0, %%rdi\n\t"	/* pass ulwp_structp as arg1 */
1593e71ca95cSGerald Jelinek 	    "movq %%rbp, %%rsp\n\t"	/* eliminate the stack frame */
1594e71ca95cSGerald Jelinek 	    "popq %%rbp\n\t"
1595e71ca95cSGerald Jelinek 	    "jmp *%%r14\n\t"		/* jump to the true entry point */
1596e71ca95cSGerald Jelinek 	    : : "r" (ulwp_structp));
1597e71ca95cSGerald Jelinek 	/*NOTREACHED*/
1598e71ca95cSGerald Jelinek }
1599e71ca95cSGerald Jelinek 
1600e71ca95cSGerald Jelinek /*
1601e71ca95cSGerald Jelinek  * The S10 libc expects that %fs will be nonzero for new 64-bit x86 LWPs but the
1602e71ca95cSGerald Jelinek  * Nevada kernel clears %fs for such LWPs.  Unforunately, new LWPs do not issue
1603e71ca95cSGerald Jelinek  * SYS_lwp_private (see s10_lwp_private() below) after they are created, so
1604e71ca95cSGerald Jelinek  * we must ensure that new LWPs invoke a brand operation that sets %fs to a
1605e71ca95cSGerald Jelinek  * nonzero value immediately after their creation.
1606e71ca95cSGerald Jelinek  *
1607e71ca95cSGerald Jelinek  * The easiest way to do this is to make new LWPs start at a special function,
1608e71ca95cSGerald Jelinek  * s10_lwp_create_entry_point() (see its definition above), that invokes the
1609e71ca95cSGerald Jelinek  * brand operation that corrects %fs.  We'll store the entry points of new LWPs
1610e71ca95cSGerald Jelinek  * in their %r14 registers so that s10_lwp_create_entry_point() can find and
1611e71ca95cSGerald Jelinek  * call them after invoking the special brand operation.  %r14 is a callee-saved
1612e71ca95cSGerald Jelinek  * register; therefore, any functions invoked by s10_lwp_create_entry_point()
1613e71ca95cSGerald Jelinek  * and all functions dealing with signals (e.g., sigacthandler()) will preserve
1614e71ca95cSGerald Jelinek  * %r14 for s10_lwp_create_entry_point().
1615e71ca95cSGerald Jelinek  *
1616e71ca95cSGerald Jelinek  * The Nevada kernel can safely work with nonzero %fs values because the kernel
1617e71ca95cSGerald Jelinek  * configures per-thread %fs segment descriptors so that the legacy %fs selector
1618e71ca95cSGerald Jelinek  * value will still work.  See the comment in lwp_load() regarding %fs and
1619e71ca95cSGerald Jelinek  * %fsbase in 64-bit x86 processes.
1620e71ca95cSGerald Jelinek  *
1621e71ca95cSGerald Jelinek  * This emulation exists thanks to CRs 6467491 and 6501650.
1622e71ca95cSGerald Jelinek  */
1623e71ca95cSGerald Jelinek static int
s10_lwp_create_correct_fs(sysret_t * rval,ucontext_t * ucp,int flags,id_t * new_lwp)1624e71ca95cSGerald Jelinek s10_lwp_create_correct_fs(sysret_t *rval, ucontext_t *ucp, int flags,
1625e71ca95cSGerald Jelinek     id_t *new_lwp)
1626e71ca95cSGerald Jelinek {
1627e71ca95cSGerald Jelinek 	ucontext_t s10_uc;
1628e71ca95cSGerald Jelinek 
1629e71ca95cSGerald Jelinek 	/*
1630e71ca95cSGerald Jelinek 	 * Copy the supplied ucontext_t structure to the local stack
1631e71ca95cSGerald Jelinek 	 * frame and store the new LWP's entry point (the value of %rip
1632e71ca95cSGerald Jelinek 	 * stored in the ucontext_t) in the new LWP's %r14 register.
1633e71ca95cSGerald Jelinek 	 * Then make s10_lwp_create_entry_point() the new LWP's entry
1634e71ca95cSGerald Jelinek 	 * point.
1635e71ca95cSGerald Jelinek 	 */
163680e2ca85S 	if (brand_uucopy(ucp, &s10_uc, sizeof (s10_uc)) != 0)
1637e71ca95cSGerald Jelinek 		return (EFAULT);
16388fd04b83SRoger A. Faulkner 
1639e71ca95cSGerald Jelinek 	s10_uc.uc_mcontext.gregs[REG_R14] = s10_uc.uc_mcontext.gregs[REG_RIP];
1640e71ca95cSGerald Jelinek 	s10_uc.uc_mcontext.gregs[REG_RIP] = (greg_t)s10_lwp_create_entry_point;
1641e71ca95cSGerald Jelinek 
1642bdf0047cSRoger A. Faulkner 	/*  fix up the signal mask */
1643bdf0047cSRoger A. Faulkner 	if (s10_uc.uc_flags & UC_SIGMASK)
1644bdf0047cSRoger A. Faulkner 		(void) s10sigset_to_native(&s10_uc.uc_sigmask,
1645bdf0047cSRoger A. Faulkner 		    &s10_uc.uc_sigmask);
1646bdf0047cSRoger A. Faulkner 
1647e71ca95cSGerald Jelinek 	/*
1648e71ca95cSGerald Jelinek 	 * Issue SYS_lwp_create to create the new LWP.  We pass the
1649e71ca95cSGerald Jelinek 	 * modified ucontext_t to make sure that the new LWP starts at
1650e71ca95cSGerald Jelinek 	 * s10_lwp_create_entry_point().
1651e71ca95cSGerald Jelinek 	 */
1652e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_lwp_create + 1024, &s10_uc,
1653e71ca95cSGerald Jelinek 	    flags, new_lwp));
1654e71ca95cSGerald Jelinek }
1655e71ca95cSGerald Jelinek #endif	/* __amd64 */
1656e71ca95cSGerald Jelinek 
1657e71ca95cSGerald Jelinek /*
1658e71ca95cSGerald Jelinek  * SYS_lwp_private is issued by libc_init() to set %fsbase in 64-bit x86
1659e71ca95cSGerald Jelinek  * processes.  The Nevada kernel sets %fs to zero but the S10 libc expects
1660e71ca95cSGerald Jelinek  * %fs to be nonzero.  We'll pass the issued system call to the kernel untouched
1661e71ca95cSGerald Jelinek  * and invoke a brand operation to set %fs to the legacy S10 selector value.
1662e71ca95cSGerald Jelinek  *
1663e71ca95cSGerald Jelinek  * This emulation exists thanks to CRs 6467491 and 6501650.
1664e71ca95cSGerald Jelinek  */
1665e71ca95cSGerald Jelinek static int
s10_lwp_private(sysret_t * rval,int cmd,int which,uintptr_t base)1666e71ca95cSGerald Jelinek s10_lwp_private(sysret_t *rval, int cmd, int which, uintptr_t base)
1667e71ca95cSGerald Jelinek {
16688fd04b83SRoger A. Faulkner #if defined(__amd64)
1669e71ca95cSGerald Jelinek 	int err;
1670e71ca95cSGerald Jelinek 
1671e71ca95cSGerald Jelinek 	/*
1672e71ca95cSGerald Jelinek 	 * The current LWP's %fs register should be zero.  Determine whether the
1673e71ca95cSGerald Jelinek 	 * Solaris 10 libc with which we're working functions correctly when %fs
1674e71ca95cSGerald Jelinek 	 * is zero by calling thr_main() after issuing the SYS_lwp_private
1675e71ca95cSGerald Jelinek 	 * syscall.  If thr_main() barfs (returns -1), then change the LWP's %fs
167680e2ca85S 	 * register via SYS_brand and patch brand_sysent_table so that issuing
1677e71ca95cSGerald Jelinek 	 * SYS_lwp_create executes s10_lwp_create_correct_fs() rather than the
1678e71ca95cSGerald Jelinek 	 * default s10_lwp_create().  s10_lwp_create_correct_fs() will
1679e71ca95cSGerald Jelinek 	 * guarantee that new LWPs will have correct %fs values.
1680e71ca95cSGerald Jelinek 	 */
1681e71ca95cSGerald Jelinek 	if ((err = __systemcall(rval, SYS_lwp_private + 1024, cmd, which,
1682e71ca95cSGerald Jelinek 	    base)) != 0)
1683e71ca95cSGerald Jelinek 		return (err);
1684e71ca95cSGerald Jelinek 	if (thr_main() == -1) {
1685e71ca95cSGerald Jelinek 		/*
1686e71ca95cSGerald Jelinek 		 * SYS_lwp_private is only issued by libc_init(), which is
1687e71ca95cSGerald Jelinek 		 * executed when libc is first loaded by ld.so.1.  Thus we
1688e71ca95cSGerald Jelinek 		 * are guaranteed to be single-threaded at this point.  Even
1689e71ca95cSGerald Jelinek 		 * if we were multithreaded at this point, writing a 64-bit
169080e2ca85S 		 * value to the st_callc field of a brand_sysent_table
1691e71ca95cSGerald Jelinek 		 * entry is guaranteed to be atomic on 64-bit x86 chips
1692e71ca95cSGerald Jelinek 		 * as long as the field is not split across cache lines
1693e71ca95cSGerald Jelinek 		 * (It shouldn't be.).  See chapter 8, section 1.1 of
1694e71ca95cSGerald Jelinek 		 * "The Intel 64 and IA32 Architectures Software Developer's
1695e71ca95cSGerald Jelinek 		 * Manual," Volume 3A for more details.
1696e71ca95cSGerald Jelinek 		 */
169780e2ca85S 		brand_sysent_table[SYS_lwp_create].st_callc =
1698c3232c95SToomas Soome 		    (sysent_cb_t)(uintptr_t)s10_lwp_create_correct_fs;
1699e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_brand + 1024,
1700e71ca95cSGerald Jelinek 		    B_S10_FSREGCORRECTION));
1701e71ca95cSGerald Jelinek 	}
1702e71ca95cSGerald Jelinek 	return (0);
1703e71ca95cSGerald Jelinek #else	/* !__amd64 */
1704e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_lwp_private + 1024, cmd, which, base));
1705e71ca95cSGerald Jelinek #endif	/* !__amd64 */
1706e71ca95cSGerald Jelinek }
1707e71ca95cSGerald Jelinek #endif	/* __x86 */
1708e71ca95cSGerald Jelinek 
1709db94676fSRoger A. Faulkner /*
1710db94676fSRoger A. Faulkner  * The Opensolaris versions of lwp_mutex_timedlock() and lwp_mutex_trylock()
1711db94676fSRoger A. Faulkner  * add an extra argument to the interfaces, a uintptr_t value for the mutex's
1712db94676fSRoger A. Faulkner  * mutex_owner field.  The Solaris 10 libc assigns the mutex_owner field at
1713db94676fSRoger A. Faulkner  * user-level, so we just make the extra argument be zero in both syscalls.
1714db94676fSRoger A. Faulkner  */
1715db94676fSRoger A. Faulkner 
1716db94676fSRoger A. Faulkner static int
s10_lwp_mutex_timedlock(sysret_t * rval,lwp_mutex_t * lp,timespec_t * tsp)1717db94676fSRoger A. Faulkner s10_lwp_mutex_timedlock(sysret_t *rval, lwp_mutex_t *lp, timespec_t *tsp)
1718db94676fSRoger A. Faulkner {
1719db94676fSRoger A. Faulkner 	return (__systemcall(rval, SYS_lwp_mutex_timedlock + 1024, lp, tsp, 0));
1720db94676fSRoger A. Faulkner }
1721db94676fSRoger A. Faulkner 
1722db94676fSRoger A. Faulkner static int
s10_lwp_mutex_trylock(sysret_t * rval,lwp_mutex_t * lp)1723db94676fSRoger A. Faulkner s10_lwp_mutex_trylock(sysret_t *rval, lwp_mutex_t *lp)
1724db94676fSRoger A. Faulkner {
1725db94676fSRoger A. Faulkner 	return (__systemcall(rval, SYS_lwp_mutex_trylock + 1024, lp, 0));
1726db94676fSRoger A. Faulkner }
1727db94676fSRoger A. Faulkner 
1728e71ca95cSGerald Jelinek /*
1729e71ca95cSGerald Jelinek  * If the emul_global_zone flag is set then emulate some aspects of the
1730e71ca95cSGerald Jelinek  * zone system call.  In particular, emulate the global zone ID on the
1731e71ca95cSGerald Jelinek  * ZONE_LOOKUP subcommand and emulate some of the global zone attributes
1732e71ca95cSGerald Jelinek  * on the ZONE_GETATTR subcommand.  If the flag is not set or we're performing
1733e71ca95cSGerald Jelinek  * some other operation, simply pass the calls through.
1734e71ca95cSGerald Jelinek  */
1735e71ca95cSGerald Jelinek int
s10_zone(sysret_t * rval,int cmd,void * arg1,void * arg2,void * arg3,void * arg4)1736e71ca95cSGerald Jelinek s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3,
1737e71ca95cSGerald Jelinek     void *arg4)
1738e71ca95cSGerald Jelinek {
1739e71ca95cSGerald Jelinek 	char		*aval;
1740e71ca95cSGerald Jelinek 	int		len;
1741e71ca95cSGerald Jelinek 	zoneid_t	zid;
1742e71ca95cSGerald Jelinek 	int		attr;
1743e71ca95cSGerald Jelinek 	char		*buf;
1744e71ca95cSGerald Jelinek 	size_t		bufsize;
1745e71ca95cSGerald Jelinek 
1746e71ca95cSGerald Jelinek 	/*
1747e71ca95cSGerald Jelinek 	 * We only emulate the zone syscall for a subset of specific commands,
1748e71ca95cSGerald Jelinek 	 * otherwise we just pass the call through.
1749e71ca95cSGerald Jelinek 	 */
1750e71ca95cSGerald Jelinek 	if (!emul_global_zone)
1751e71ca95cSGerald Jelinek 		return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2,
1752e71ca95cSGerald Jelinek 		    arg3, arg4));
1753e71ca95cSGerald Jelinek 
1754e71ca95cSGerald Jelinek 	switch (cmd) {
1755e71ca95cSGerald Jelinek 	case ZONE_LOOKUP:
175680e2ca85S 		(void) B_TRUSS_POINT_1(rval, SYS_zone, 0, cmd);
1757e71ca95cSGerald Jelinek 		rval->sys_rval1 = GLOBAL_ZONEID;
1758e71ca95cSGerald Jelinek 		rval->sys_rval2 = 0;
1759e71ca95cSGerald Jelinek 		return (0);
1760e71ca95cSGerald Jelinek 
1761e71ca95cSGerald Jelinek 	case ZONE_GETATTR:
1762e71ca95cSGerald Jelinek 		zid = (zoneid_t)(uintptr_t)arg1;
1763e71ca95cSGerald Jelinek 		attr = (int)(uintptr_t)arg2;
1764e71ca95cSGerald Jelinek 		buf = (char *)arg3;
1765e71ca95cSGerald Jelinek 		bufsize = (size_t)arg4;
1766e71ca95cSGerald Jelinek 
1767e71ca95cSGerald Jelinek 		/*
1768e71ca95cSGerald Jelinek 		 * If the request is for the global zone then we're emulating
1769e71ca95cSGerald Jelinek 		 * that, otherwise pass this thru.
1770e71ca95cSGerald Jelinek 		 */
1771e71ca95cSGerald Jelinek 		if (zid != GLOBAL_ZONEID)
1772e71ca95cSGerald Jelinek 			goto passthru;
1773e71ca95cSGerald Jelinek 
1774e71ca95cSGerald Jelinek 		switch (attr) {
1775e71ca95cSGerald Jelinek 		case ZONE_ATTR_NAME:
1776e71ca95cSGerald Jelinek 			aval = GLOBAL_ZONENAME;
1777e71ca95cSGerald Jelinek 			break;
1778e71ca95cSGerald Jelinek 
1779e71ca95cSGerald Jelinek 		case ZONE_ATTR_BRAND:
1780e71ca95cSGerald Jelinek 			aval = NATIVE_BRAND_NAME;
1781e71ca95cSGerald Jelinek 			break;
1782e71ca95cSGerald Jelinek 		default:
1783e71ca95cSGerald Jelinek 			/*
1784e71ca95cSGerald Jelinek 			 * We only emulate a subset of the attrs, use the
1785e71ca95cSGerald Jelinek 			 * real zone id to pass thru the rest.
1786e71ca95cSGerald Jelinek 			 */
1787e71ca95cSGerald Jelinek 			arg1 = (void *)(uintptr_t)zoneid;
1788e71ca95cSGerald Jelinek 			goto passthru;
1789e71ca95cSGerald Jelinek 		}
1790e71ca95cSGerald Jelinek 
179180e2ca85S 		(void) B_TRUSS_POINT_5(rval, SYS_zone, 0, cmd, zid, attr,
1792e71ca95cSGerald Jelinek 		    buf, bufsize);
1793e71ca95cSGerald Jelinek 
1794e71ca95cSGerald Jelinek 		len = strlen(aval) + 1;
1795e71ca95cSGerald Jelinek 		if (len > bufsize)
1796e71ca95cSGerald Jelinek 			return (ENAMETOOLONG);
1797e71ca95cSGerald Jelinek 
1798e71ca95cSGerald Jelinek 		if (buf != NULL) {
1799e71ca95cSGerald Jelinek 			if (len == 1) {
180080e2ca85S 				if (brand_uucopy("\0", buf, 1) != 0)
1801e71ca95cSGerald Jelinek 					return (EFAULT);
1802e71ca95cSGerald Jelinek 			} else {
180380e2ca85S 				if (brand_uucopystr(aval, buf, len) != 0)
1804e71ca95cSGerald Jelinek 					return (EFAULT);
1805e71ca95cSGerald Jelinek 
1806e71ca95cSGerald Jelinek 				/*
1807e71ca95cSGerald Jelinek 				 * Assure NULL termination of "buf" as
180880e2ca85S 				 * brand_uucopystr() does NOT.
1809e71ca95cSGerald Jelinek 				 */
181080e2ca85S 				if (brand_uucopy("\0", buf + (len - 1), 1) != 0)
1811e71ca95cSGerald Jelinek 					return (EFAULT);
1812e71ca95cSGerald Jelinek 			}
1813e71ca95cSGerald Jelinek 		}
1814e71ca95cSGerald Jelinek 
1815e71ca95cSGerald Jelinek 		rval->sys_rval1 = len;
1816e71ca95cSGerald Jelinek 		rval->sys_rval2 = 0;
1817e71ca95cSGerald Jelinek 		return (0);
1818e71ca95cSGerald Jelinek 
1819e71ca95cSGerald Jelinek 	default:
1820e71ca95cSGerald Jelinek 		break;
1821e71ca95cSGerald Jelinek 	}
1822e71ca95cSGerald Jelinek 
1823e71ca95cSGerald Jelinek passthru:
1824e71ca95cSGerald Jelinek 	return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2, arg3,
1825e71ca95cSGerald Jelinek 	    arg4));
1826e71ca95cSGerald Jelinek }
1827e71ca95cSGerald Jelinek 
1828e71ca95cSGerald Jelinek /*ARGSUSED*/
1829e71ca95cSGerald Jelinek int
brand_init(int argc,char * argv[],char * envp[])183080e2ca85S brand_init(int argc, char *argv[], char *envp[])
1831e71ca95cSGerald Jelinek {
1832e71ca95cSGerald Jelinek 	sysret_t		rval;
183380e2ca85S 	ulong_t			ldentry;
183480e2ca85S 	int			err;
1835e71ca95cSGerald Jelinek 	char			*bname;
1836e71ca95cSGerald Jelinek 
183780e2ca85S 	brand_pre_init();
1838e71ca95cSGerald Jelinek 
1839e71ca95cSGerald Jelinek 	/*
1840e71ca95cSGerald Jelinek 	 * Cache the pid of the zone's init process and determine if
1841bbf21555SRichard Lowe 	 * we're init(8) for the zone.  Remember: we might be init
1842e71ca95cSGerald Jelinek 	 * now, but as soon as we fork(2) we won't be.
1843e71ca95cSGerald Jelinek 	 */
1844e71ca95cSGerald Jelinek 	(void) get_initpid_info();
1845e71ca95cSGerald Jelinek 
1846e71ca95cSGerald Jelinek 	/* get the current zoneid */
1847e71ca95cSGerald Jelinek 	err = __systemcall(&rval, SYS_zone, ZONE_LOOKUP, NULL);
184880e2ca85S 	brand_assert(err == 0);
1849e71ca95cSGerald Jelinek 	zoneid = (zoneid_t)rval.sys_rval1;
1850e71ca95cSGerald Jelinek 
1851ad601a05Sjv 	/* Get the zone's emulation bitmap. */
1852e71ca95cSGerald Jelinek 	if ((err = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
1853ad601a05Sjv 	    S10_EMUL_BITMAP, emul_bitmap, sizeof (emul_bitmap))) != 0) {
185480e2ca85S 		brand_abort(err, "The zone's patch level is unsupported");
1855e71ca95cSGerald Jelinek 		/*NOTREACHED*/
1856e71ca95cSGerald Jelinek 	}
1857e71ca95cSGerald Jelinek 
1858e71ca95cSGerald Jelinek 	bname = basename(argv[0]);
1859e71ca95cSGerald Jelinek 
1860e71ca95cSGerald Jelinek 	/*
1861e71ca95cSGerald Jelinek 	 * In general we want the S10 commands that are zone-aware to continue
1862e71ca95cSGerald Jelinek 	 * to behave as they normally do within a zone.  Since these commands
1863e71ca95cSGerald Jelinek 	 * are zone-aware, they should continue to "do the right thing".
1864e71ca95cSGerald Jelinek 	 * However, some zone-aware commands aren't going to work the way
1865e71ca95cSGerald Jelinek 	 * we expect them to inside the branded zone.  In particular, the pkg
1866e71ca95cSGerald Jelinek 	 * and patch commands will not properly manage all pkgs/patches
1867e71ca95cSGerald Jelinek 	 * unless the commands think they are running in the global zone.  For
1868e71ca95cSGerald Jelinek 	 * these commands we want to emulate the global zone.
1869e71ca95cSGerald Jelinek 	 *
1870e71ca95cSGerald Jelinek 	 * We don't do any emulation for pkgcond since it is typically used
1871e71ca95cSGerald Jelinek 	 * in pkg/patch postinstall scripts and we want those scripts to do
1872e71ca95cSGerald Jelinek 	 * the right thing inside a zone.
1873e71ca95cSGerald Jelinek 	 *
1874e71ca95cSGerald Jelinek 	 * One issue is the handling of hollow pkgs.  Since the pkgs are
1875e71ca95cSGerald Jelinek 	 * hollow, they won't use pkgcond in their postinstall scripts.  These
1876e71ca95cSGerald Jelinek 	 * pkgs typically are installing drivers so we handle that by
1877e71ca95cSGerald Jelinek 	 * replacing add_drv and rem_drv in the s10_boot script.
1878e71ca95cSGerald Jelinek 	 */
1879e71ca95cSGerald Jelinek 	if (strcmp("pkgadd", bname) == 0 || strcmp("pkgrm", bname) == 0 ||
1880e71ca95cSGerald Jelinek 	    strcmp("patchadd", bname) == 0 || strcmp("patchrm", bname) == 0)
1881e71ca95cSGerald Jelinek 		emul_global_zone = B_TRUE;
1882e71ca95cSGerald Jelinek 
188380e2ca85S 	ldentry = brand_post_init(S10_VERSION, argc, argv, envp);
1884e71ca95cSGerald Jelinek 
188580e2ca85S 	brand_runexe(argv, ldentry);
1886e71ca95cSGerald Jelinek 	/*NOTREACHED*/
188780e2ca85S 	brand_abort(0, "brand_runexe() returned");
1888e71ca95cSGerald Jelinek 	return (-1);
1889e71ca95cSGerald Jelinek }
1890e71ca95cSGerald Jelinek 
1891e71ca95cSGerald Jelinek /*
1892e71ca95cSGerald Jelinek  * This table must have at least NSYSCALL entries in it.
1893e71ca95cSGerald Jelinek  *
189480e2ca85S  * The second parameter of each entry in the brand_sysent_table
1895e71ca95cSGerald Jelinek  * contains the number of parameters and flags that describe the
1896e71ca95cSGerald Jelinek  * syscall return value encoding.  See the block comments at the
1897e71ca95cSGerald Jelinek  * top of this file for more information about the syscall return
1898e71ca95cSGerald Jelinek  * value flags and when they should be used.
1899e71ca95cSGerald Jelinek  */
190080e2ca85S brand_sysent_table_t brand_sysent_table[] = {
1901e71ca95cSGerald Jelinek #if defined(__sparc) && !defined(__sparcv9)
190280e2ca85S 	EMULATE(brand_indir, 9 | RV_64RVAL),	/*  0 */
19038fd04b83SRoger A. Faulkner #else
1904e71ca95cSGerald Jelinek 	NOSYS,					/*  0 */
19058fd04b83SRoger A. Faulkner #endif
1906e71ca95cSGerald Jelinek 	NOSYS,					/*   1 */
19078fd04b83SRoger A. Faulkner 	EMULATE(s10_forkall, 0 | RV_32RVAL2),	/*   2 */
1908e71ca95cSGerald Jelinek 	NOSYS,					/*   3 */
1909e71ca95cSGerald Jelinek 	NOSYS,					/*   4 */
19108fd04b83SRoger A. Faulkner 	EMULATE(s10_open, 3 | RV_DEFAULT),	/*   5 */
1911e71ca95cSGerald Jelinek 	NOSYS,					/*   6 */
19128fd04b83SRoger A. Faulkner 	EMULATE(s10_wait, 0 | RV_32RVAL2),	/*   7 */
19138fd04b83SRoger A. Faulkner 	EMULATE(s10_creat, 2 | RV_DEFAULT),	/*   8 */
1914794f0adbSRoger A. Faulkner 	EMULATE(s10_link, 2 | RV_DEFAULT),	/*   9 */
19158fd04b83SRoger A. Faulkner 	EMULATE(s10_unlink, 1 | RV_DEFAULT),	/*  10 */
1916e71ca95cSGerald Jelinek 	EMULATE(s10_exec, 2 | RV_DEFAULT),	/*  11 */
1917e71ca95cSGerald Jelinek 	NOSYS,					/*  12 */
1918e71ca95cSGerald Jelinek 	NOSYS,					/*  13 */
1919794f0adbSRoger A. Faulkner 	EMULATE(s10_mknod, 3 | RV_DEFAULT),	/*  14 */
1920794f0adbSRoger A. Faulkner 	EMULATE(s10_chmod, 2 | RV_DEFAULT),	/*  15 */
19218fd04b83SRoger A. Faulkner 	EMULATE(s10_chown, 3 | RV_DEFAULT),	/*  16 */
1922e71ca95cSGerald Jelinek 	NOSYS,					/*  17 */
19238fd04b83SRoger A. Faulkner 	EMULATE(s10_stat, 2 | RV_DEFAULT),	/*  18 */
1924e71ca95cSGerald Jelinek 	NOSYS,					/*  19 */
1925e71ca95cSGerald Jelinek 	NOSYS,					/*  20 */
1926e71ca95cSGerald Jelinek 	NOSYS,					/*  21 */
19278fd04b83SRoger A. Faulkner 	EMULATE(s10_umount, 1 | RV_DEFAULT),	/*  22 */
1928e71ca95cSGerald Jelinek 	NOSYS,					/*  23 */
1929e71ca95cSGerald Jelinek 	NOSYS,					/*  24 */
1930e71ca95cSGerald Jelinek 	NOSYS,					/*  25 */
1931e71ca95cSGerald Jelinek 	NOSYS,					/*  26 */
1932e71ca95cSGerald Jelinek 	NOSYS,					/*  27 */
19338fd04b83SRoger A. Faulkner 	EMULATE(s10_fstat, 2 | RV_DEFAULT),	/*  28 */
1934e71ca95cSGerald Jelinek 	NOSYS,					/*  29 */
19358fd04b83SRoger A. Faulkner 	EMULATE(s10_utime, 2 | RV_DEFAULT),	/*  30 */
1936e71ca95cSGerald Jelinek 	NOSYS,					/*  31 */
1937e71ca95cSGerald Jelinek 	NOSYS,					/*  32 */
19388fd04b83SRoger A. Faulkner 	EMULATE(s10_access, 2 | RV_DEFAULT),	/*  33 */
1939e71ca95cSGerald Jelinek 	NOSYS,					/*  34 */
1940e71ca95cSGerald Jelinek 	NOSYS,					/*  35 */
1941e71ca95cSGerald Jelinek 	NOSYS,					/*  36 */
1942bdf0047cSRoger A. Faulkner 	EMULATE(s10_kill, 2 | RV_DEFAULT),	/*  37 */
1943e71ca95cSGerald Jelinek 	NOSYS,					/*  38 */
1944e71ca95cSGerald Jelinek 	NOSYS,					/*  39 */
1945e71ca95cSGerald Jelinek 	NOSYS,					/*  40 */
19468fd04b83SRoger A. Faulkner 	EMULATE(s10_dup, 1 | RV_DEFAULT),	/*  41 */
1947b49b27dcSTheo Schlossnagle 	EMULATE(s10_pipe, 0 | RV_32RVAL2),	/*  42 */
1948e71ca95cSGerald Jelinek 	NOSYS,					/*  43 */
1949e71ca95cSGerald Jelinek 	NOSYS,					/*  44 */
1950e71ca95cSGerald Jelinek 	NOSYS,					/*  45 */
1951e71ca95cSGerald Jelinek 	NOSYS,					/*  46 */
1952e71ca95cSGerald Jelinek 	NOSYS,					/*  47 */
1953e71ca95cSGerald Jelinek 	NOSYS,					/*  48 */
1954e71ca95cSGerald Jelinek 	NOSYS,					/*  49 */
1955e71ca95cSGerald Jelinek 	NOSYS,					/*  50 */
1956e71ca95cSGerald Jelinek 	NOSYS,					/*  51 */
1957e71ca95cSGerald Jelinek 	NOSYS,					/*  52 */
1958e71ca95cSGerald Jelinek 	NOSYS,					/*  53 */
1959e71ca95cSGerald Jelinek 	EMULATE(s10_ioctl, 3 | RV_DEFAULT),	/*  54 */
1960e71ca95cSGerald Jelinek 	NOSYS,					/*  55 */
1961e71ca95cSGerald Jelinek 	NOSYS,					/*  56 */
1962e71ca95cSGerald Jelinek 	NOSYS,					/*  57 */
1963e71ca95cSGerald Jelinek 	NOSYS,					/*  58 */
1964e71ca95cSGerald Jelinek 	EMULATE(s10_execve, 3 | RV_DEFAULT),	/*  59 */
1965e71ca95cSGerald Jelinek 	NOSYS,					/*  60 */
1966e71ca95cSGerald Jelinek 	NOSYS,					/*  61 */
1967e71ca95cSGerald Jelinek 	NOSYS,					/*  62 */
1968e71ca95cSGerald Jelinek 	NOSYS,					/*  63 */
1969e71ca95cSGerald Jelinek 	NOSYS,					/*  64 */
1970e71ca95cSGerald Jelinek 	NOSYS,					/*  65 */
1971e71ca95cSGerald Jelinek 	NOSYS,					/*  66 */
1972e71ca95cSGerald Jelinek 	NOSYS,					/*  67 */
1973e71ca95cSGerald Jelinek 	NOSYS,					/*  68 */
1974e71ca95cSGerald Jelinek 	NOSYS,					/*  69 */
1975e71ca95cSGerald Jelinek 	NOSYS,					/*  70 */
1976e71ca95cSGerald Jelinek 	EMULATE(s10_acctctl, 3 | RV_DEFAULT),	/*  71 */
1977e71ca95cSGerald Jelinek 	NOSYS,					/*  72 */
1978e71ca95cSGerald Jelinek 	NOSYS,					/*  73 */
1979e71ca95cSGerald Jelinek 	NOSYS,					/*  74 */
1980e71ca95cSGerald Jelinek 	EMULATE(s10_issetugid, 0 | RV_DEFAULT),	/*  75 */
19818fd04b83SRoger A. Faulkner 	EMULATE(s10_fsat, 6 | RV_DEFAULT),	/*  76 */
1982e71ca95cSGerald Jelinek 	NOSYS,					/*  77 */
1983e71ca95cSGerald Jelinek 	NOSYS,					/*  78 */
19848fd04b83SRoger A. Faulkner 	EMULATE(s10_rmdir, 1 | RV_DEFAULT),	/*  79 */
1985794f0adbSRoger A. Faulkner 	EMULATE(s10_mkdir, 2 | RV_DEFAULT),	/*  80 */
19868b4cf837Sjv 	EMULATE(s10_getdents, 3 | RV_DEFAULT),	/*  81 */
1987e71ca95cSGerald Jelinek 	NOSYS,					/*  82 */
1988e71ca95cSGerald Jelinek 	NOSYS,					/*  83 */
1989e71ca95cSGerald Jelinek 	NOSYS,					/*  84 */
1990e71ca95cSGerald Jelinek 	NOSYS,					/*  85 */
1991e71ca95cSGerald Jelinek 	NOSYS,					/*  86 */
19928fd04b83SRoger A. Faulkner 	EMULATE(s10_poll, 3 | RV_DEFAULT),	/*  87 */
19938fd04b83SRoger A. Faulkner 	EMULATE(s10_lstat, 2 | RV_DEFAULT),	/*  88 */
1994794f0adbSRoger A. Faulkner 	EMULATE(s10_symlink, 2 | RV_DEFAULT),	/*  89 */
1995794f0adbSRoger A. Faulkner 	EMULATE(s10_readlink, 3 | RV_DEFAULT),	/*  90 */
1996e71ca95cSGerald Jelinek 	NOSYS,					/*  91 */
1997e71ca95cSGerald Jelinek 	NOSYS,					/*  92 */
1998794f0adbSRoger A. Faulkner 	EMULATE(s10_fchmod, 2 | RV_DEFAULT),	/*  93 */
19998fd04b83SRoger A. Faulkner 	EMULATE(s10_fchown, 3 | RV_DEFAULT),	/*  94 */
2000bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigprocmask, 3 | RV_DEFAULT), /*  95 */
2001bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigsuspend, 1 | RV_DEFAULT), /*  96 */
2002e71ca95cSGerald Jelinek 	NOSYS,					/*  97 */
2003bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigaction, 3 | RV_DEFAULT),	/*  98 */
2004bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigpending, 2 | RV_DEFAULT), /*  99 */
20058f798d3aSRoger A. Faulkner 	NOSYS,					/* 100 */
2006e71ca95cSGerald Jelinek 	NOSYS,					/* 101 */
2007e71ca95cSGerald Jelinek 	NOSYS,					/* 102 */
2008e71ca95cSGerald Jelinek 	NOSYS,					/* 103 */
2009e71ca95cSGerald Jelinek 	NOSYS,					/* 104 */
2010e71ca95cSGerald Jelinek 	NOSYS,					/* 105 */
2011e71ca95cSGerald Jelinek 	NOSYS,					/* 106 */
2012bdf0047cSRoger A. Faulkner 	EMULATE(s10_waitid, 4 | RV_DEFAULT),	/* 107 */
2013bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigsendsys, 2 | RV_DEFAULT), /* 108 */
2014e71ca95cSGerald Jelinek 	NOSYS,					/* 109 */
2015e71ca95cSGerald Jelinek 	NOSYS,					/* 110 */
2016e71ca95cSGerald Jelinek 	NOSYS,					/* 111 */
2017e71ca95cSGerald Jelinek 	NOSYS,					/* 112 */
2018e71ca95cSGerald Jelinek 	NOSYS,					/* 113 */
2019e71ca95cSGerald Jelinek 	NOSYS,					/* 114 */
2020e71ca95cSGerald Jelinek 	NOSYS,					/* 115 */
2021e71ca95cSGerald Jelinek 	NOSYS,					/* 116 */
2022e71ca95cSGerald Jelinek 	NOSYS,					/* 117 */
2023e71ca95cSGerald Jelinek 	NOSYS,					/* 118 */
2024e71ca95cSGerald Jelinek 	NOSYS,					/* 119 */
2025e71ca95cSGerald Jelinek 	NOSYS,					/* 120 */
2026e71ca95cSGerald Jelinek 	NOSYS,					/* 121 */
2027e71ca95cSGerald Jelinek 	NOSYS,					/* 122 */
20288fd04b83SRoger A. Faulkner #if defined(__x86)
20298fd04b83SRoger A. Faulkner 	EMULATE(s10_xstat, 3 | RV_DEFAULT),	/* 123 */
20308fd04b83SRoger A. Faulkner 	EMULATE(s10_lxstat, 3 | RV_DEFAULT),	/* 124 */
20318fd04b83SRoger A. Faulkner 	EMULATE(s10_fxstat, 3 | RV_DEFAULT),	/* 125 */
20328fd04b83SRoger A. Faulkner 	EMULATE(s10_xmknod, 4 | RV_DEFAULT),	/* 126 */
20338fd04b83SRoger A. Faulkner #else
2034e71ca95cSGerald Jelinek 	NOSYS,					/* 123 */
2035e71ca95cSGerald Jelinek 	NOSYS,					/* 124 */
2036e71ca95cSGerald Jelinek 	NOSYS,					/* 125 */
2037e71ca95cSGerald Jelinek 	NOSYS,					/* 126 */
20388fd04b83SRoger A. Faulkner #endif
2039e71ca95cSGerald Jelinek 	NOSYS,					/* 127 */
2040e71ca95cSGerald Jelinek 	NOSYS,					/* 128 */
2041e71ca95cSGerald Jelinek 	NOSYS,					/* 129 */
20428fd04b83SRoger A. Faulkner 	EMULATE(s10_lchown, 3 | RV_DEFAULT),	/* 130 */
2043e71ca95cSGerald Jelinek 	NOSYS,					/* 131 */
2044e71ca95cSGerald Jelinek 	NOSYS,					/* 132 */
2045e71ca95cSGerald Jelinek 	NOSYS,					/* 133 */
20468fd04b83SRoger A. Faulkner 	EMULATE(s10_rename, 2 | RV_DEFAULT),	/* 134 */
2047e71ca95cSGerald Jelinek 	EMULATE(s10_uname, 1 | RV_DEFAULT),	/* 135 */
2048e71ca95cSGerald Jelinek 	NOSYS,					/* 136 */
2049bdf0047cSRoger A. Faulkner 	EMULATE(s10_sysconfig, 1 | RV_DEFAULT),	/* 137 */
2050e71ca95cSGerald Jelinek 	NOSYS,					/* 138 */
2051e71ca95cSGerald Jelinek 	EMULATE(s10_sysinfo, 3 | RV_DEFAULT),	/* 139 */
2052e71ca95cSGerald Jelinek 	NOSYS,					/* 140 */
2053e71ca95cSGerald Jelinek 	NOSYS,					/* 141 */
2054e71ca95cSGerald Jelinek 	NOSYS,					/* 142 */
20558fd04b83SRoger A. Faulkner 	EMULATE(s10_fork1, 0 | RV_32RVAL2),	/* 143 */
2056bdf0047cSRoger A. Faulkner 	EMULATE(s10_sigtimedwait, 3 | RV_DEFAULT), /* 144 */
2057e71ca95cSGerald Jelinek 	NOSYS,					/* 145 */
2058e71ca95cSGerald Jelinek 	NOSYS,					/* 146 */
20598fd04b83SRoger A. Faulkner 	EMULATE(s10_lwp_sema_wait, 1 | RV_DEFAULT), /* 147 */
2060e71ca95cSGerald Jelinek 	NOSYS,					/* 148 */
2061e71ca95cSGerald Jelinek 	NOSYS,					/* 149 */
2062e71ca95cSGerald Jelinek 	NOSYS,					/* 150 */
2063e71ca95cSGerald Jelinek 	NOSYS,					/* 151 */
2064e71ca95cSGerald Jelinek 	NOSYS,					/* 152 */
2065e71ca95cSGerald Jelinek 	NOSYS,					/* 153 */
20668fd04b83SRoger A. Faulkner 	EMULATE(s10_utimes, 2 | RV_DEFAULT),	/* 154 */
2067e71ca95cSGerald Jelinek 	NOSYS,					/* 155 */
2068e71ca95cSGerald Jelinek 	NOSYS,					/* 156 */
2069e71ca95cSGerald Jelinek 	NOSYS,					/* 157 */
2070e71ca95cSGerald Jelinek 	NOSYS,					/* 158 */
2071e71ca95cSGerald Jelinek 	EMULATE(s10_lwp_create, 3 | RV_DEFAULT), /* 159 */
2072e71ca95cSGerald Jelinek 	NOSYS,					/* 160 */
2073e71ca95cSGerald Jelinek 	NOSYS,					/* 161 */
2074e71ca95cSGerald Jelinek 	NOSYS,					/* 162 */
2075bdf0047cSRoger A. Faulkner 	EMULATE(s10_lwp_kill, 2 | RV_DEFAULT),	/* 163 */
2076e71ca95cSGerald Jelinek 	NOSYS,					/* 164 */
2077bdf0047cSRoger A. Faulkner 	EMULATE(s10_lwp_sigmask, 3 | RV_32RVAL2), /* 165 */
20788fd04b83SRoger A. Faulkner #if defined(__x86)
2079e71ca95cSGerald Jelinek 	EMULATE(s10_lwp_private, 3 | RV_DEFAULT), /* 166 */
20808fd04b83SRoger A. Faulkner #else
2081e71ca95cSGerald Jelinek 	NOSYS,					/* 166 */
20828fd04b83SRoger A. Faulkner #endif
2083e71ca95cSGerald Jelinek 	NOSYS,					/* 167 */
2084e71ca95cSGerald Jelinek 	NOSYS,					/* 168 */
20858fd04b83SRoger A. Faulkner 	EMULATE(s10_lwp_mutex_lock, 1 | RV_DEFAULT), /* 169 */
2086e71ca95cSGerald Jelinek 	NOSYS,					/* 170 */
2087e71ca95cSGerald Jelinek 	NOSYS,					/* 171 */
2088e71ca95cSGerald Jelinek 	NOSYS,					/* 172 */
2089e71ca95cSGerald Jelinek 	NOSYS,					/* 173 */
2090e71ca95cSGerald Jelinek 	EMULATE(s10_pwrite, 4 | RV_DEFAULT),	/* 174 */
2091e71ca95cSGerald Jelinek 	NOSYS,					/* 175 */
2092e71ca95cSGerald Jelinek 	NOSYS,					/* 176 */
2093e71ca95cSGerald Jelinek 	NOSYS,					/* 177 */
2094e71ca95cSGerald Jelinek 	NOSYS,					/* 178 */
2095e71ca95cSGerald Jelinek 	NOSYS,					/* 179 */
2096e71ca95cSGerald Jelinek 	NOSYS,					/* 180 */
2097e71ca95cSGerald Jelinek 	NOSYS,					/* 181 */
2098e71ca95cSGerald Jelinek 	NOSYS,					/* 182 */
2099e71ca95cSGerald Jelinek 	NOSYS,					/* 183 */
2100e71ca95cSGerald Jelinek 	NOSYS,					/* 184 */
2101f3f1e74cS 	EMULATE(s10_acl, 4 | RV_DEFAULT),	/* 185 */
2102e71ca95cSGerald Jelinek 	EMULATE(s10_auditsys, 4 | RV_64RVAL),	/* 186 */
2103e71ca95cSGerald Jelinek 	NOSYS,					/* 187 */
2104e71ca95cSGerald Jelinek 	NOSYS,					/* 188 */
2105e71ca95cSGerald Jelinek 	NOSYS,					/* 189 */
2106e71ca95cSGerald Jelinek 	EMULATE(s10_sigqueue, 4 | RV_DEFAULT),	/* 190 */
2107e71ca95cSGerald Jelinek 	NOSYS,					/* 191 */
2108e71ca95cSGerald Jelinek 	NOSYS,					/* 192 */
2109e71ca95cSGerald Jelinek 	NOSYS,					/* 193 */
2110e71ca95cSGerald Jelinek 	NOSYS,					/* 194 */
2111e71ca95cSGerald Jelinek 	NOSYS,					/* 195 */
2112e71ca95cSGerald Jelinek 	NOSYS,					/* 196 */
2113e71ca95cSGerald Jelinek 	NOSYS,					/* 197 */
2114e71ca95cSGerald Jelinek 	NOSYS,					/* 198 */
2115e71ca95cSGerald Jelinek 	NOSYS,					/* 199 */
2116f3f1e74cS 	EMULATE(s10_facl, 4 | RV_DEFAULT),	/* 200 */
2117e71ca95cSGerald Jelinek 	NOSYS,					/* 201 */
2118e71ca95cSGerald Jelinek 	NOSYS,					/* 202 */
2119e71ca95cSGerald Jelinek 	NOSYS,					/* 203 */
2120e71ca95cSGerald Jelinek 	NOSYS,					/* 204 */
2121bdf0047cSRoger A. Faulkner 	EMULATE(s10_signotify, 3 | RV_DEFAULT),	/* 205 */
2122e71ca95cSGerald Jelinek 	NOSYS,					/* 206 */
2123e71ca95cSGerald Jelinek 	NOSYS,					/* 207 */
2124e71ca95cSGerald Jelinek 	NOSYS,					/* 208 */
2125e71ca95cSGerald Jelinek 	NOSYS,					/* 209 */
21268fd04b83SRoger A. Faulkner 	EMULATE(s10_lwp_mutex_timedlock, 2 | RV_DEFAULT), /* 210 */
2127e71ca95cSGerald Jelinek 	NOSYS,					/* 211 */
2128e71ca95cSGerald Jelinek 	NOSYS,					/* 212 */
21298fd04b83SRoger A. Faulkner #if defined(_LP64)
2130e71ca95cSGerald Jelinek 	NOSYS,					/* 213 */
21318fd04b83SRoger A. Faulkner #else
21328b4cf837Sjv 	EMULATE(s10_getdents64, 3 | RV_DEFAULT), /* 213 */
21338fd04b83SRoger A. Faulkner #endif
2134e71ca95cSGerald Jelinek 	NOSYS,					/* 214 */
21358fd04b83SRoger A. Faulkner #if defined(_LP64)
2136e71ca95cSGerald Jelinek 	NOSYS,					/* 215 */
2137e71ca95cSGerald Jelinek 	NOSYS,					/* 216 */
2138e71ca95cSGerald Jelinek 	NOSYS,					/* 217 */
21398fd04b83SRoger A. Faulkner #else
21408fd04b83SRoger A. Faulkner 	EMULATE(s10_stat64, 2 | RV_DEFAULT),	/* 215 */
21418fd04b83SRoger A. Faulkner 	EMULATE(s10_lstat64, 2 | RV_DEFAULT),	/* 216 */
21428fd04b83SRoger A. Faulkner 	EMULATE(s10_fstat64, 2 | RV_DEFAULT),	/* 217 */
21438fd04b83SRoger A. Faulkner #endif
2144e71ca95cSGerald Jelinek 	NOSYS,					/* 218 */
2145e71ca95cSGerald Jelinek 	NOSYS,					/* 219 */
2146e71ca95cSGerald Jelinek 	NOSYS,					/* 220 */
2147e71ca95cSGerald Jelinek 	NOSYS,					/* 221 */
2148e71ca95cSGerald Jelinek 	NOSYS,					/* 222 */
21498fd04b83SRoger A. Faulkner #if defined(_LP64)
2150e71ca95cSGerald Jelinek 	NOSYS,					/* 223 */
2151e71ca95cSGerald Jelinek 	NOSYS,					/* 224 */
2152e71ca95cSGerald Jelinek 	NOSYS,					/* 225 */
21538fd04b83SRoger A. Faulkner #else
21548fd04b83SRoger A. Faulkner 	EMULATE(s10_pwrite64, 5 | RV_DEFAULT),	/* 223 */
21558fd04b83SRoger A. Faulkner 	EMULATE(s10_creat64, 2 | RV_DEFAULT),	/* 224 */
21568fd04b83SRoger A. Faulkner 	EMULATE(s10_open64, 3 | RV_DEFAULT),	/* 225 */
21578fd04b83SRoger A. Faulkner #endif
2158e71ca95cSGerald Jelinek 	NOSYS,					/* 226 */
2159e71ca95cSGerald Jelinek 	EMULATE(s10_zone, 5 | RV_DEFAULT),	/* 227 */
2160e71ca95cSGerald Jelinek 	NOSYS,					/* 228 */
2161e71ca95cSGerald Jelinek 	NOSYS,					/* 229 */
2162b49b27dcSTheo Schlossnagle 	EMULATE(s10_so_socket, 5 | RV_DEFAULT),	/* 230 */
2163e71ca95cSGerald Jelinek 	NOSYS,					/* 231 */
2164e71ca95cSGerald Jelinek 	NOSYS,					/* 232 */
2165e71ca95cSGerald Jelinek 	NOSYS,					/* 233 */
2166b49b27dcSTheo Schlossnagle 	EMULATE(s10_accept, 4 | RV_DEFAULT),	/* 234 */
2167e71ca95cSGerald Jelinek 	NOSYS,					/* 235 */
2168e71ca95cSGerald Jelinek 	NOSYS,					/* 236 */
2169e71ca95cSGerald Jelinek 	NOSYS,					/* 237 */
2170e71ca95cSGerald Jelinek 	NOSYS,					/* 238 */
2171e71ca95cSGerald Jelinek 	NOSYS,					/* 239 */
2172e71ca95cSGerald Jelinek 	NOSYS,					/* 240 */
2173e71ca95cSGerald Jelinek 	NOSYS,					/* 241 */
2174e71ca95cSGerald Jelinek 	NOSYS,					/* 242 */
2175e71ca95cSGerald Jelinek 	NOSYS,					/* 243 */
2176e71ca95cSGerald Jelinek 	NOSYS,					/* 244 */
2177e71ca95cSGerald Jelinek 	NOSYS,					/* 245 */
2178e71ca95cSGerald Jelinek 	NOSYS,					/* 246 */
2179e71ca95cSGerald Jelinek 	NOSYS,					/* 247 */
2180e71ca95cSGerald Jelinek 	NOSYS,					/* 248 */
2181e71ca95cSGerald Jelinek 	NOSYS,					/* 249 */
2182e71ca95cSGerald Jelinek 	NOSYS,					/* 250 */
21838fd04b83SRoger A. Faulkner 	EMULATE(s10_lwp_mutex_trylock, 1 | RV_DEFAULT), /* 251 */
2184e71ca95cSGerald Jelinek 	NOSYS,					/* 252 */
2185e71ca95cSGerald Jelinek 	NOSYS,					/* 253 */
2186e71ca95cSGerald Jelinek 	NOSYS,					/* 254 */
2187e71ca95cSGerald Jelinek 	NOSYS					/* 255 */
2188e71ca95cSGerald Jelinek };
2189