Print this page
6136 sysmacros.h unnecessarily polutes the namespace
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c
+++ new/usr/src/lib/brand/solaris10/s10_brand/common/s10_brand.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
24 24 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 25 */
26 26
27 27 #include <errno.h>
28 28 #include <fcntl.h>
29 29 #include <dirent.h>
30 30 #include <stddef.h>
31 31 #include <stdio.h>
32 32 #include <stdlib.h>
33 33 #include <strings.h>
34 34 #include <unistd.h>
35 35 #include <thread.h>
36 36 #include <sys/auxv.h>
37 37 #include <sys/brand.h>
38 38 #include <sys/inttypes.h>
39 39 #include <sys/lwp.h>
40 40 #include <sys/syscall.h>
41 41 #include <sys/systm.h>
42 42 #include <sys/utsname.h>
43 43 #include <sys/sysconfig.h>
44 44 #include <sys/systeminfo.h>
45 45 #include <sys/zone.h>
46 46 #include <sys/stat.h>
47 47 #include <sys/mntent.h>
48 48 #include <sys/ctfs.h>
49 49 #include <sys/priv.h>
50 50 #include <sys/acctctl.h>
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
51 51 #include <libgen.h>
52 52 #include <bsm/audit.h>
53 53 #include <sys/crypto/ioctl.h>
54 54 #include <sys/fs/zfs.h>
55 55 #include <sys/zfs_ioctl.h>
56 56 #include <sys/ucontext.h>
57 57 #include <sys/mntio.h>
58 58 #include <sys/mnttab.h>
59 59 #include <sys/attr.h>
60 60 #include <sys/lofi.h>
61 +#include <sys/mkdev.h>
61 62 #include <atomic.h>
62 63 #include <sys/acl.h>
63 64 #include <sys/socket.h>
64 65
65 66 #include <s10_brand.h>
66 67 #include <brand_misc.h>
67 68 #include <s10_misc.h>
68 69 #include <s10_signal.h>
69 70
70 71 /*
71 72 * See usr/src/lib/brand/shared/brand/common/brand_util.c for general
72 73 * emulation notes.
73 74 */
74 75
75 76 static zoneid_t zoneid;
76 77 static boolean_t emul_global_zone = B_FALSE;
77 78 static s10_emul_bitmap_t emul_bitmap;
78 79 pid_t zone_init_pid;
79 80
80 81 /*
81 82 * S10_FEATURE_IS_PRESENT is a macro that helps facilitate conditional
82 83 * emulation. For each constant N defined in the s10_emulated_features
83 84 * enumeration in usr/src/uts/common/brand/solaris10/s10_brand.h,
84 85 * S10_FEATURE_IS_PRESENT(N) is true iff the feature/backport represented by N
85 86 * is present in the Solaris 10 image hosted within the zone. In other words,
86 87 * S10_FEATURE_IS_PRESENT(N) is true iff the file /usr/lib/brand/solaris10/M,
87 88 * where M is the enum value of N, was present in the zone when the zone booted.
88 89 *
89 90 *
90 91 * *** Sample Usage
91 92 *
92 93 * Suppose that you need to backport a fix to Solaris 10 and there is
93 94 * emulation in place for the fix. Suppose further that the emulation won't be
94 95 * needed if the fix is backported (i.e., if the fix is present in the hosted
95 96 * Solaris 10 environment, then the brand won't need the emulation). Then if
96 97 * you add a constant named "S10_FEATURE_X" to the end of the
97 98 * s10_emulated_features enumeration that represents the backported fix and
98 99 * S10_FEATURE_X evaluates to four, then you should create a file named
99 100 * /usr/lib/brand/solaris10/4 as part of your backport. Additionally, you
100 101 * should retain the aforementioned emulation but modify it so that it's
101 102 * performed only when S10_FEATURE_IS_PRESENT(S10_FEATURE_X) is false. Thus the
102 103 * emulation function should look something like the following:
103 104 *
104 105 * static int
105 106 * my_emul_function(sysret_t *rv, ...)
106 107 * {
107 108 * if (S10_FEATURE_IS_PRESENT(S10_FEATURE_X)) {
108 109 * // Don't emulate
109 110 * return (__systemcall(rv, ...));
110 111 * } else {
111 112 * // Emulate whatever needs to be emulated when the
112 113 * // backport isn't present in the Solaris 10 image.
113 114 * }
114 115 * }
115 116 */
116 117 #define S10_FEATURE_IS_PRESENT(s10_emulated_features_constant) \
117 118 ((emul_bitmap[(s10_emulated_features_constant) >> 3] & \
118 119 (1 << ((s10_emulated_features_constant) & 0x7))) != 0)
119 120
120 121 brand_sysent_table_t brand_sysent_table[];
121 122
122 123 #define S10_UTS_RELEASE "5.10"
123 124 #define S10_UTS_VERSION "Generic_Virtual"
124 125
125 126 /*
126 127 * If the ioctl fd's major doesn't match "major", then pass through the
127 128 * ioctl, since it is not the expected device. major should be a
128 129 * pointer to a static dev_t initialized to -1, and devname should be
129 130 * the path of the device.
130 131 *
131 132 * Returns 1 if the ioctl was handled (in which case *err contains the
132 133 * error code), or 0 if it still needs handling.
133 134 */
134 135 static int
135 136 passthru_otherdev_ioctl(dev_t *majordev, const char *devname, int *err,
136 137 sysret_t *rval, int fdes, int cmd, intptr_t arg)
137 138 {
138 139 struct stat sbuf;
139 140
140 141 if (*majordev == (dev_t)-1) {
141 142 if ((*err = __systemcall(rval, SYS_fstatat + 1024,
142 143 AT_FDCWD, devname, &sbuf, 0) != 0) != 0)
143 144 goto doioctl;
144 145
145 146 *majordev = major(sbuf.st_rdev);
146 147 }
147 148
148 149 if ((*err = __systemcall(rval, SYS_fstatat + 1024, fdes,
149 150 NULL, &sbuf, 0)) != 0)
150 151 goto doioctl;
151 152
152 153 if (major(sbuf.st_rdev) == *majordev)
153 154 return (0);
154 155
155 156 doioctl:
156 157 *err = (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
157 158 return (1);
158 159 }
159 160
160 161 /*
161 162 * Figures out the PID of init for the zone. Also returns a boolean
162 163 * indicating whether this process currently has that pid: if so,
163 164 * then at this moment, we are init.
164 165 */
165 166 static boolean_t
166 167 get_initpid_info(void)
167 168 {
168 169 pid_t pid;
169 170 sysret_t rval;
170 171 int err;
171 172
172 173 /*
173 174 * Determine the current process PID and the PID of the zone's init.
174 175 * We use care not to call getpid() here, because we're not supposed
175 176 * to call getpid() until after the program is fully linked-- the
176 177 * first call to getpid() is a signal from the linker to debuggers
177 178 * that linking has been completed.
178 179 */
179 180 if ((err = __systemcall(&rval, SYS_brand,
180 181 B_S10_PIDINFO, &pid, &zone_init_pid)) != 0) {
181 182 brand_abort(err, "Failed to get init's pid");
182 183 }
183 184
184 185 /*
185 186 * Note that we need to be cautious with the pid we get back--
186 187 * it should not be stashed and used in place of getpid(), since
187 188 * we might fork(2). So we keep zone_init_pid and toss the pid
188 189 * we otherwise got.
189 190 */
190 191 if (pid == zone_init_pid)
191 192 return (B_TRUE);
192 193
193 194 return (B_FALSE);
194 195 }
195 196
196 197 /* Free the thread-local storage provided by mntfs_get_mntentbuf(). */
197 198 static void
198 199 mntfs_free_mntentbuf(void *arg)
199 200 {
200 201 struct mntentbuf *embufp = arg;
201 202
202 203 if (embufp == NULL)
203 204 return;
204 205 if (embufp->mbuf_emp)
205 206 free(embufp->mbuf_emp);
206 207 if (embufp->mbuf_buf)
207 208 free(embufp->mbuf_buf);
208 209 bzero(embufp, sizeof (struct mntentbuf));
209 210 free(embufp);
210 211 }
211 212
212 213 /* Provide the thread-local storage required by mntfs_ioctl(). */
213 214 static struct mntentbuf *
214 215 mntfs_get_mntentbuf(size_t size)
215 216 {
216 217 static mutex_t keylock;
217 218 static thread_key_t key;
218 219 static int once_per_keyname = 0;
219 220 void *tsd = NULL;
220 221 struct mntentbuf *embufp;
221 222
222 223 /* Create the key. */
223 224 if (!once_per_keyname) {
224 225 (void) mutex_lock(&keylock);
225 226 if (!once_per_keyname) {
226 227 if (thr_keycreate(&key, mntfs_free_mntentbuf)) {
227 228 (void) mutex_unlock(&keylock);
228 229 return (NULL);
229 230 } else {
230 231 once_per_keyname++;
231 232 }
232 233 }
233 234 (void) mutex_unlock(&keylock);
234 235 }
235 236
236 237 /*
237 238 * The thread-specific datum for this key is the address of a struct
238 239 * mntentbuf. If this is the first time here then we allocate the struct
239 240 * and its contents, and associate its address with the thread; if there
240 241 * are any problems then we abort.
241 242 */
242 243 if (thr_getspecific(key, &tsd))
243 244 return (NULL);
244 245 if (tsd == NULL) {
245 246 if (!(embufp = calloc(1, sizeof (struct mntentbuf))) ||
246 247 !(embufp->mbuf_emp = malloc(sizeof (struct extmnttab))) ||
247 248 thr_setspecific(key, embufp)) {
248 249 mntfs_free_mntentbuf(embufp);
249 250 return (NULL);
250 251 }
251 252 } else {
252 253 embufp = tsd;
253 254 }
254 255
255 256 /* Return the buffer, resizing it if necessary. */
256 257 if (size > embufp->mbuf_bufsize) {
257 258 if (embufp->mbuf_buf)
258 259 free(embufp->mbuf_buf);
259 260 if ((embufp->mbuf_buf = malloc(size)) == NULL) {
260 261 embufp->mbuf_bufsize = 0;
261 262 return (NULL);
262 263 } else {
263 264 embufp->mbuf_bufsize = size;
264 265 }
265 266 }
266 267 return (embufp);
267 268 }
268 269
269 270 /*
270 271 * The MNTIOC_GETMNTENT command in this release differs from that in early
271 272 * versions of Solaris 10.
272 273 *
273 274 * Previously, the command would copy a pointer to a struct extmnttab to an
274 275 * address provided as an argument. The pointer would be somewhere within a
275 276 * mapping already present within the user's address space. In addition, the
276 277 * text to which the struct's members pointed would also be within a
277 278 * pre-existing mapping. Now, the user is required to allocate memory for both
278 279 * the struct and the text buffer, and to pass the address of each within a
279 280 * struct mntentbuf. In order to conceal these details from a Solaris 10 client
280 281 * we allocate some thread-local storage in which to create the necessary data
281 282 * structures; this is static, thread-safe memory that will be cleaned up
282 283 * without the caller's intervention.
283 284 *
284 285 * MNTIOC_GETEXTMNTENT and MNTIOC_GETMNTANY are new in this release; they should
285 286 * not work for older clients.
286 287 */
287 288 int
288 289 mntfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
289 290 {
290 291 int err;
291 292 struct stat statbuf;
292 293 struct mntentbuf *embufp;
293 294 static size_t bufsize = MNT_LINE_MAX;
294 295
295 296 /* Do not emulate mntfs commands from up-to-date clients. */
296 297 if (S10_FEATURE_IS_PRESENT(S10_FEATURE_ALTERED_MNTFS_IOCTL))
297 298 return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
298 299
299 300 /* Do not emulate mntfs commands directed at other file systems. */
300 301 if ((err = __systemcall(rval, SYS_fstatat + 1024,
301 302 fdes, NULL, &statbuf, 0)) != 0)
302 303 return (err);
303 304 if (strcmp(statbuf.st_fstype, MNTTYPE_MNTFS) != 0)
304 305 return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
305 306
306 307 if (cmd == MNTIOC_GETEXTMNTENT || cmd == MNTIOC_GETMNTANY)
307 308 return (EINVAL);
308 309
309 310 if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
310 311 return (ENOMEM);
311 312
312 313 /*
313 314 * MNTIOC_GETEXTMNTENT advances the file pointer once it has
314 315 * successfully copied out the result to the address provided. We
315 316 * therefore need to check the user-supplied address now since the
316 317 * one we'll be providing is guaranteed to work.
317 318 */
318 319 if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
319 320 return (EFAULT);
320 321
321 322 /*
322 323 * Keep retrying for as long as we fail for want of a large enough
323 324 * buffer.
324 325 */
325 326 for (;;) {
326 327 if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes,
327 328 MNTIOC_GETEXTMNTENT, embufp)) != 0)
328 329 return (err);
329 330
330 331 if (rval->sys_rval1 == MNTFS_TOOLONG) {
331 332 /* The buffer wasn't large enough. */
332 333 (void) atomic_swap_ulong((unsigned long *)&bufsize,
333 334 2 * embufp->mbuf_bufsize);
334 335 if ((embufp = mntfs_get_mntentbuf(bufsize)) == NULL)
335 336 return (ENOMEM);
336 337 } else {
337 338 break;
338 339 }
339 340 }
340 341
341 342 if (brand_uucopy(&embufp->mbuf_emp, (void *)arg, sizeof (void *)) != 0)
342 343 return (EFAULT);
343 344
344 345 return (0);
345 346 }
346 347
347 348 /*
348 349 * Assign the structure member value from the s (source) structure to the
349 350 * d (dest) structure.
350 351 */
351 352 #define struct_assign(d, s, val) (((d).val) = ((s).val))
352 353
353 354 /*
354 355 * The CRYPTO_GET_FUNCTION_LIST parameter structure crypto_function_list_t
355 356 * changed between S10 and Nevada, so we have to emulate the old S10
356 357 * crypto_function_list_t structure when interposing on the ioctl syscall.
357 358 */
358 359 typedef struct s10_crypto_function_list {
359 360 boolean_t fl_digest_init;
360 361 boolean_t fl_digest;
361 362 boolean_t fl_digest_update;
362 363 boolean_t fl_digest_key;
363 364 boolean_t fl_digest_final;
364 365
365 366 boolean_t fl_encrypt_init;
366 367 boolean_t fl_encrypt;
367 368 boolean_t fl_encrypt_update;
368 369 boolean_t fl_encrypt_final;
369 370
370 371 boolean_t fl_decrypt_init;
371 372 boolean_t fl_decrypt;
372 373 boolean_t fl_decrypt_update;
373 374 boolean_t fl_decrypt_final;
374 375
375 376 boolean_t fl_mac_init;
376 377 boolean_t fl_mac;
377 378 boolean_t fl_mac_update;
378 379 boolean_t fl_mac_final;
379 380
380 381 boolean_t fl_sign_init;
381 382 boolean_t fl_sign;
382 383 boolean_t fl_sign_update;
383 384 boolean_t fl_sign_final;
384 385 boolean_t fl_sign_recover_init;
385 386 boolean_t fl_sign_recover;
386 387
387 388 boolean_t fl_verify_init;
388 389 boolean_t fl_verify;
389 390 boolean_t fl_verify_update;
390 391 boolean_t fl_verify_final;
391 392 boolean_t fl_verify_recover_init;
392 393 boolean_t fl_verify_recover;
393 394
394 395 boolean_t fl_digest_encrypt_update;
395 396 boolean_t fl_decrypt_digest_update;
396 397 boolean_t fl_sign_encrypt_update;
397 398 boolean_t fl_decrypt_verify_update;
398 399
399 400 boolean_t fl_seed_random;
400 401 boolean_t fl_generate_random;
401 402
402 403 boolean_t fl_session_open;
403 404 boolean_t fl_session_close;
404 405 boolean_t fl_session_login;
405 406 boolean_t fl_session_logout;
406 407
407 408 boolean_t fl_object_create;
408 409 boolean_t fl_object_copy;
409 410 boolean_t fl_object_destroy;
410 411 boolean_t fl_object_get_size;
411 412 boolean_t fl_object_get_attribute_value;
412 413 boolean_t fl_object_set_attribute_value;
413 414 boolean_t fl_object_find_init;
414 415 boolean_t fl_object_find;
415 416 boolean_t fl_object_find_final;
416 417
417 418 boolean_t fl_key_generate;
418 419 boolean_t fl_key_generate_pair;
419 420 boolean_t fl_key_wrap;
420 421 boolean_t fl_key_unwrap;
421 422 boolean_t fl_key_derive;
422 423
423 424 boolean_t fl_init_token;
424 425 boolean_t fl_init_pin;
425 426 boolean_t fl_set_pin;
426 427
427 428 boolean_t prov_is_hash_limited;
428 429 uint32_t prov_hash_threshold;
429 430 uint32_t prov_hash_limit;
430 431 } s10_crypto_function_list_t;
431 432
432 433 typedef struct s10_crypto_get_function_list {
433 434 uint_t fl_return_value;
434 435 crypto_provider_id_t fl_provider_id;
435 436 s10_crypto_function_list_t fl_list;
436 437 } s10_crypto_get_function_list_t;
437 438
438 439 /*
439 440 * The structure returned by the CRYPTO_GET_FUNCTION_LIST ioctl on /dev/crypto
440 441 * increased in size due to:
441 442 * 6482533 Threshold for HW offload via PKCS11 interface
442 443 * between S10 and Nevada. This is a relatively simple process of filling
443 444 * in the S10 structure fields with the Nevada data.
444 445 *
445 446 * We stat the device to make sure that the ioctl is meant for /dev/crypto.
446 447 *
447 448 */
448 449 static int
449 450 crypto_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
450 451 {
451 452 int err;
452 453 s10_crypto_get_function_list_t s10_param;
453 454 crypto_get_function_list_t native_param;
454 455 static dev_t crypto_dev = (dev_t)-1;
455 456
456 457 if (passthru_otherdev_ioctl(&crypto_dev, "/dev/crypto", &err,
457 458 rval, fdes, cmd, arg) == 1)
458 459 return (err);
459 460
460 461 if (brand_uucopy((const void *)arg, &s10_param, sizeof (s10_param))
461 462 != 0)
462 463 return (EFAULT);
463 464 struct_assign(native_param, s10_param, fl_provider_id);
464 465 if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd,
465 466 &native_param)) != 0)
466 467 return (err);
467 468
468 469 struct_assign(s10_param, native_param, fl_return_value);
469 470 struct_assign(s10_param, native_param, fl_provider_id);
470 471
471 472 struct_assign(s10_param, native_param, fl_list.fl_digest_init);
472 473 struct_assign(s10_param, native_param, fl_list.fl_digest);
473 474 struct_assign(s10_param, native_param, fl_list.fl_digest_update);
474 475 struct_assign(s10_param, native_param, fl_list.fl_digest_key);
475 476 struct_assign(s10_param, native_param, fl_list.fl_digest_final);
476 477
477 478 struct_assign(s10_param, native_param, fl_list.fl_encrypt_init);
478 479 struct_assign(s10_param, native_param, fl_list.fl_encrypt);
479 480 struct_assign(s10_param, native_param, fl_list.fl_encrypt_update);
480 481 struct_assign(s10_param, native_param, fl_list.fl_encrypt_final);
481 482
482 483 struct_assign(s10_param, native_param, fl_list.fl_decrypt_init);
483 484 struct_assign(s10_param, native_param, fl_list.fl_decrypt);
484 485 struct_assign(s10_param, native_param, fl_list.fl_decrypt_update);
485 486 struct_assign(s10_param, native_param, fl_list.fl_decrypt_final);
486 487
487 488 struct_assign(s10_param, native_param, fl_list.fl_mac_init);
488 489 struct_assign(s10_param, native_param, fl_list.fl_mac);
489 490 struct_assign(s10_param, native_param, fl_list.fl_mac_update);
490 491 struct_assign(s10_param, native_param, fl_list.fl_mac_final);
491 492
492 493 struct_assign(s10_param, native_param, fl_list.fl_sign_init);
493 494 struct_assign(s10_param, native_param, fl_list.fl_sign);
494 495 struct_assign(s10_param, native_param, fl_list.fl_sign_update);
495 496 struct_assign(s10_param, native_param, fl_list.fl_sign_final);
496 497 struct_assign(s10_param, native_param, fl_list.fl_sign_recover_init);
497 498 struct_assign(s10_param, native_param, fl_list.fl_sign_recover);
498 499
499 500 struct_assign(s10_param, native_param, fl_list.fl_verify_init);
500 501 struct_assign(s10_param, native_param, fl_list.fl_verify);
501 502 struct_assign(s10_param, native_param, fl_list.fl_verify_update);
502 503 struct_assign(s10_param, native_param, fl_list.fl_verify_final);
503 504 struct_assign(s10_param, native_param, fl_list.fl_verify_recover_init);
504 505 struct_assign(s10_param, native_param, fl_list.fl_verify_recover);
505 506
506 507 struct_assign(s10_param, native_param,
507 508 fl_list.fl_digest_encrypt_update);
508 509 struct_assign(s10_param, native_param,
509 510 fl_list.fl_decrypt_digest_update);
510 511 struct_assign(s10_param, native_param, fl_list.fl_sign_encrypt_update);
511 512 struct_assign(s10_param, native_param,
512 513 fl_list.fl_decrypt_verify_update);
513 514
514 515 struct_assign(s10_param, native_param, fl_list.fl_seed_random);
515 516 struct_assign(s10_param, native_param, fl_list.fl_generate_random);
516 517
517 518 struct_assign(s10_param, native_param, fl_list.fl_session_open);
518 519 struct_assign(s10_param, native_param, fl_list.fl_session_close);
519 520 struct_assign(s10_param, native_param, fl_list.fl_session_login);
520 521 struct_assign(s10_param, native_param, fl_list.fl_session_logout);
521 522
522 523 struct_assign(s10_param, native_param, fl_list.fl_object_create);
523 524 struct_assign(s10_param, native_param, fl_list.fl_object_copy);
524 525 struct_assign(s10_param, native_param, fl_list.fl_object_destroy);
525 526 struct_assign(s10_param, native_param, fl_list.fl_object_get_size);
526 527 struct_assign(s10_param, native_param,
527 528 fl_list.fl_object_get_attribute_value);
528 529 struct_assign(s10_param, native_param,
529 530 fl_list.fl_object_set_attribute_value);
530 531 struct_assign(s10_param, native_param, fl_list.fl_object_find_init);
531 532 struct_assign(s10_param, native_param, fl_list.fl_object_find);
532 533 struct_assign(s10_param, native_param, fl_list.fl_object_find_final);
533 534
534 535 struct_assign(s10_param, native_param, fl_list.fl_key_generate);
535 536 struct_assign(s10_param, native_param, fl_list.fl_key_generate_pair);
536 537 struct_assign(s10_param, native_param, fl_list.fl_key_wrap);
537 538 struct_assign(s10_param, native_param, fl_list.fl_key_unwrap);
538 539 struct_assign(s10_param, native_param, fl_list.fl_key_derive);
539 540
540 541 struct_assign(s10_param, native_param, fl_list.fl_init_token);
541 542 struct_assign(s10_param, native_param, fl_list.fl_init_pin);
542 543 struct_assign(s10_param, native_param, fl_list.fl_set_pin);
543 544
544 545 struct_assign(s10_param, native_param, fl_list.prov_is_hash_limited);
545 546 struct_assign(s10_param, native_param, fl_list.prov_hash_threshold);
546 547 struct_assign(s10_param, native_param, fl_list.prov_hash_limit);
547 548
548 549 return (brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param)));
549 550 }
550 551
551 552 /*
552 553 * The process contract CT_TGET and CT_TSET parameter structure ct_param_t
553 554 * changed between S10 and Nevada, so we have to emulate the old S10
554 555 * ct_param_t structure when interposing on the ioctl syscall.
555 556 */
556 557 typedef struct s10_ct_param {
557 558 uint32_t ctpm_id;
558 559 uint32_t ctpm_pad;
559 560 uint64_t ctpm_value;
560 561 } s10_ct_param_t;
561 562
562 563 /*
563 564 * We have to emulate process contract ioctls for init(1M) because the
564 565 * ioctl parameter structure changed between S10 and Nevada. This is
565 566 * a relatively simple process of filling Nevada structure fields,
566 567 * shuffling values, and initiating a native system call.
567 568 *
568 569 * For now, we'll assume that all consumers of CT_TGET and CT_TSET will
569 570 * need emulation. We'll issue a stat to make sure that the ioctl
570 571 * is meant for the contract file system.
571 572 *
572 573 */
573 574 static int
574 575 ctfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
575 576 {
576 577 int err;
577 578 s10_ct_param_t s10param;
578 579 ct_param_t param;
579 580 struct stat statbuf;
580 581
581 582 if ((err = __systemcall(rval, SYS_fstatat + 1024,
582 583 fdes, NULL, &statbuf, 0)) != 0)
583 584 return (err);
584 585 if (strcmp(statbuf.st_fstype, MNTTYPE_CTFS) != 0)
585 586 return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
586 587
587 588 if (brand_uucopy((const void *)arg, &s10param, sizeof (s10param)) != 0)
588 589 return (EFAULT);
589 590 param.ctpm_id = s10param.ctpm_id;
590 591 param.ctpm_size = sizeof (uint64_t);
591 592 param.ctpm_value = &s10param.ctpm_value;
592 593 if ((err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, ¶m))
593 594 != 0)
594 595 return (err);
595 596
596 597 if (cmd == CT_TGET)
597 598 return (brand_uucopy(&s10param, (void *)arg,
598 599 sizeof (s10param)));
599 600
600 601 return (0);
601 602 }
602 603
603 604 /*
604 605 * ZFS ioctls have changed in each Solaris 10 (S10) release as well as in
605 606 * Solaris Next. The brand wraps ZFS commands so that the native commands
606 607 * are used, but we want to be sure no command sneaks in that uses ZFS
607 608 * without our knowledge. We'll abort the process if we see a ZFS ioctl.
608 609 */
609 610 static int
610 611 zfs_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
611 612 {
612 613 static dev_t zfs_dev = (dev_t)-1;
613 614 int err;
614 615
615 616 if (passthru_otherdev_ioctl(&zfs_dev, ZFS_DEV, &err,
616 617 rval, fdes, cmd, arg) == 1)
617 618 return (err);
618 619
619 620 brand_abort(0, "ZFS ioctl!");
620 621 /*NOTREACHED*/
621 622 return (0);
622 623 }
623 624
624 625 struct s10_lofi_ioctl {
625 626 uint32_t li_minor;
626 627 boolean_t li_force;
627 628 char li_filename[MAXPATHLEN + 1];
628 629 };
629 630
630 631 static int
631 632 lofi_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
632 633 {
633 634 static dev_t lofi_dev = (dev_t)-1;
634 635 struct s10_lofi_ioctl s10_param;
635 636 struct lofi_ioctl native_param;
636 637 int err;
637 638
638 639 if (passthru_otherdev_ioctl(&lofi_dev, "/dev/lofictl", &err,
639 640 rval, fdes, cmd, arg) == 1)
640 641 return (err);
641 642
642 643 if (brand_uucopy((const void *)arg, &s10_param,
643 644 sizeof (s10_param)) != 0)
644 645 return (EFAULT);
645 646
646 647 /*
647 648 * Somewhat weirdly, EIO is what the S10 lofi driver would
648 649 * return for unrecognised cmds.
649 650 */
650 651 if (cmd >= LOFI_CHECK_COMPRESSED)
651 652 return (EIO);
652 653
653 654 bzero(&native_param, sizeof (native_param));
654 655
655 656 struct_assign(native_param, s10_param, li_minor);
656 657 struct_assign(native_param, s10_param, li_force);
657 658
658 659 /*
659 660 * Careful here, this has changed from [MAXPATHLEN + 1] to
660 661 * [MAXPATHLEN].
661 662 */
662 663 bcopy(s10_param.li_filename, native_param.li_filename,
663 664 sizeof (native_param.li_filename));
664 665 native_param.li_filename[MAXPATHLEN - 1] = '\0';
665 666
666 667 err = __systemcall(rval, SYS_ioctl + 1024, fdes, cmd, &native_param);
667 668
668 669 struct_assign(s10_param, native_param, li_minor);
669 670 /* li_force is input-only */
670 671
671 672 bcopy(native_param.li_filename, s10_param.li_filename,
672 673 sizeof (native_param.li_filename));
673 674
674 675 (void) brand_uucopy(&s10_param, (void *)arg, sizeof (s10_param));
675 676 return (err);
676 677 }
677 678
678 679 int
679 680 s10_ioctl(sysret_t *rval, int fdes, int cmd, intptr_t arg)
680 681 {
681 682 switch (cmd) {
682 683 case CRYPTO_GET_FUNCTION_LIST:
683 684 return (crypto_ioctl(rval, fdes, cmd, arg));
684 685 case CT_TGET:
685 686 /*FALLTHRU*/
686 687 case CT_TSET:
687 688 return (ctfs_ioctl(rval, fdes, cmd, arg));
688 689 case MNTIOC_GETMNTENT:
689 690 /*FALLTHRU*/
690 691 case MNTIOC_GETEXTMNTENT:
691 692 /*FALLTHRU*/
692 693 case MNTIOC_GETMNTANY:
693 694 return (mntfs_ioctl(rval, fdes, cmd, arg));
694 695 }
695 696
696 697 switch (cmd & ~0xff) {
697 698 case ZFS_IOC:
698 699 return (zfs_ioctl(rval, fdes, cmd, arg));
699 700
700 701 case LOFI_IOC_BASE:
701 702 return (lofi_ioctl(rval, fdes, cmd, arg));
702 703
703 704 default:
704 705 break;
705 706 }
706 707
707 708 return (__systemcall(rval, SYS_ioctl + 1024, fdes, cmd, arg));
708 709 }
709 710
710 711 /*
711 712 * Unfortunately, pwrite()'s behavior differs between S10 and Nevada when
712 713 * applied to files opened with O_APPEND. The offset argument is ignored and
713 714 * the buffer is appended to the target file in S10, whereas the current file
714 715 * position is ignored in Nevada (i.e., pwrite() acts as though the target file
715 716 * wasn't opened with O_APPEND). This is a result of the fix for CR 6655660
716 717 * (pwrite() must ignore the O_APPEND/FAPPEND flag).
717 718 *
718 719 * We emulate the old S10 pwrite() behavior by checking whether the target file
719 720 * was opened with O_APPEND. If it was, then invoke the write() system call
720 721 * instead of pwrite(); otherwise, invoke the pwrite() system call as usual.
721 722 */
722 723 static int
723 724 s10_pwrite(sysret_t *rval, int fd, const void *bufferp, size_t num_bytes,
724 725 off_t offset)
725 726 {
726 727 int err;
727 728
728 729 if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL)) != 0)
729 730 return (err);
730 731 if (rval->sys_rval1 & O_APPEND)
731 732 return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
732 733 num_bytes));
733 734 return (__systemcall(rval, SYS_pwrite + 1024, fd, bufferp, num_bytes,
734 735 offset));
735 736 }
736 737
737 738 #if !defined(_LP64)
738 739 /*
739 740 * This is the large file version of the pwrite() system call for 32-bit
740 741 * processes. This exists for the same reason that s10_pwrite() exists; see
741 742 * the comment above s10_pwrite().
742 743 */
743 744 static int
744 745 s10_pwrite64(sysret_t *rval, int fd, const void *bufferp, size32_t num_bytes,
745 746 uint32_t offset_1, uint32_t offset_2)
746 747 {
747 748 int err;
748 749
749 750 if ((err = __systemcall(rval, SYS_fcntl + 1024, fd, F_GETFL)) != 0)
750 751 return (err);
751 752 if (rval->sys_rval1 & O_APPEND)
752 753 return (__systemcall(rval, SYS_write + 1024, fd, bufferp,
753 754 num_bytes));
754 755 return (__systemcall(rval, SYS_pwrite64 + 1024, fd, bufferp,
755 756 num_bytes, offset_1, offset_2));
756 757 }
757 758 #endif /* !_LP64 */
758 759
759 760 /*
760 761 * These are convenience macros that s10_getdents_common() uses. Both treat
761 762 * their arguments, which should be character pointers, as dirent pointers or
762 763 * dirent64 pointers and yield their d_name and d_reclen fields. These
763 764 * macros shouldn't be used outside of s10_getdents_common().
764 765 */
765 766 #define dirent_name(charptr) ((charptr) + name_offset)
766 767 #define dirent_reclen(charptr) \
767 768 (*(unsigned short *)(uintptr_t)((charptr) + reclen_offset))
768 769
769 770 /*
770 771 * This function contains code that is common to both s10_getdents() and
771 772 * s10_getdents64(). See the comment above s10_getdents() for details.
772 773 *
773 774 * rval, fd, buf, and nbyte should be passed unmodified from s10_getdents()
774 775 * and s10_getdents64(). getdents_syscall_id should be either SYS_getdents
775 776 * or SYS_getdents64. name_offset should be the the byte offset of
776 777 * the d_name field in the dirent structures passed to the kernel via the
777 778 * syscall represented by getdents_syscall_id. reclen_offset should be
778 779 * the byte offset of the d_reclen field in the aforementioned dirent
779 780 * structures.
780 781 */
781 782 static int
782 783 s10_getdents_common(sysret_t *rval, int fd, char *buf, size_t nbyte,
783 784 int getdents_syscall_id, size_t name_offset, size_t reclen_offset)
784 785 {
785 786 int err;
786 787 size_t buf_size;
787 788 char *local_buf;
788 789 char *buf_current;
789 790
790 791 /*
791 792 * Use a special brand operation, B_S10_ISFDXATTRDIR, to determine
792 793 * whether the specified file descriptor refers to an extended file
793 794 * attribute directory. If it doesn't, then SYS_getdents won't
794 795 * reveal extended file attributes, in which case we can simply
795 796 * hand the syscall to the native kernel.
796 797 */
797 798 if ((err = __systemcall(rval, SYS_brand + 1024, B_S10_ISFDXATTRDIR,
798 799 fd)) != 0)
799 800 return (err);
800 801 if (rval->sys_rval1 == 0)
801 802 return (__systemcall(rval, getdents_syscall_id + 1024, fd, buf,
802 803 nbyte));
803 804
804 805 /*
805 806 * The file descriptor refers to an extended file attributes directory.
806 807 * We need to create a dirent buffer that's as large as buf into which
807 808 * the native SYS_getdents will store the special extended file
808 809 * attribute directory's entries. We can't dereference buf because
809 810 * it might be an invalid pointer!
810 811 */
811 812 if (nbyte > MAXGETDENTS_SIZE)
812 813 nbyte = MAXGETDENTS_SIZE;
813 814 local_buf = (char *)malloc(nbyte);
814 815 if (local_buf == NULL) {
815 816 /*
816 817 * getdents(2) doesn't return an error code indicating a memory
817 818 * allocation error and it doesn't make sense to return any of
818 819 * its documented error codes for a malloc(3C) failure. We'll
819 820 * use ENOMEM even though getdents(2) doesn't use it because it
820 821 * best describes the failure.
821 822 */
822 823 (void) B_TRUSS_POINT_3(rval, getdents_syscall_id, ENOMEM, fd,
823 824 buf, nbyte);
824 825 rval->sys_rval1 = -1;
825 826 rval->sys_rval2 = 0;
826 827 return (EIO);
827 828 }
828 829
829 830 /*
830 831 * Issue a native SYS_getdents syscall but use our local dirent buffer
831 832 * instead of buf. This will allow us to examine the returned dirent
832 833 * structures immediately and copy them to buf later. That way the
833 834 * calling process won't be able to see the dirent structures until
834 835 * we finish examining them.
835 836 */
836 837 if ((err = __systemcall(rval, getdents_syscall_id + 1024, fd, local_buf,
837 838 nbyte)) != 0) {
838 839 free(local_buf);
839 840 return (err);
840 841 }
841 842 buf_size = rval->sys_rval1;
842 843 if (buf_size == 0) {
843 844 free(local_buf);
844 845 return (0);
845 846 }
846 847
847 848 /*
848 849 * Look for SUNWattr_ro (VIEW_READONLY) and SUNWattr_rw
849 850 * (VIEW_READWRITE) in the directory entries and remove them
850 851 * from the dirent buffer.
851 852 */
852 853 for (buf_current = local_buf;
853 854 (size_t)(buf_current - local_buf) < buf_size; /* cstyle */) {
854 855 if (strcmp(dirent_name(buf_current), VIEW_READONLY) != 0 &&
855 856 strcmp(dirent_name(buf_current), VIEW_READWRITE) != 0) {
856 857 /*
857 858 * The dirent refers to an attribute that should
858 859 * be visible to Solaris 10 processes. Keep it
859 860 * and examine the next entry in the buffer.
860 861 */
861 862 buf_current += dirent_reclen(buf_current);
862 863 } else {
863 864 /*
864 865 * We found either SUNWattr_ro (VIEW_READONLY)
865 866 * or SUNWattr_rw (VIEW_READWRITE). Remove it
866 867 * from the dirent buffer by decrementing
867 868 * buf_size by the size of the entry and
868 869 * overwriting the entry with the remaining
869 870 * entries.
870 871 */
871 872 buf_size -= dirent_reclen(buf_current);
872 873 (void) memmove(buf_current, buf_current +
873 874 dirent_reclen(buf_current), buf_size -
874 875 (size_t)(buf_current - local_buf));
875 876 }
876 877 }
877 878
878 879 /*
879 880 * Copy local_buf into buf so that the calling process can see
880 881 * the results.
881 882 */
882 883 if ((err = brand_uucopy(local_buf, buf, buf_size)) != 0) {
883 884 free(local_buf);
884 885 rval->sys_rval1 = -1;
885 886 rval->sys_rval2 = 0;
886 887 return (err);
887 888 }
888 889 rval->sys_rval1 = buf_size;
889 890 free(local_buf);
890 891 return (0);
891 892 }
892 893
893 894 /*
894 895 * Solaris Next added two special extended file attributes, SUNWattr_ro and
895 896 * SUNWattr_rw, which are called "extended system attributes". They have
896 897 * special semantics (e.g., a process cannot unlink SUNWattr_ro) and should
897 898 * not appear in solaris10-branded zones because no Solaris 10 applications,
898 899 * including system commands such as tar(1), are coded to correctly handle these
899 900 * special attributes.
900 901 *
901 902 * This emulation function solves the aforementioned problem by emulating
902 903 * the getdents(2) syscall and filtering both system attributes out of resulting
903 904 * directory entry lists. The emulation function only filters results when
904 905 * the given file descriptor refers to an extended file attribute directory.
905 906 * Filtering getdents(2) results is expensive because it requires dynamic
906 907 * memory allocation; however, the performance cost is tolerable because
907 908 * we don't expect Solaris 10 processes to frequently examine extended file
908 909 * attribute directories.
909 910 *
910 911 * The brand's emulation library needs two getdents(2) emulation functions
911 912 * because getdents(2) comes in two flavors: non-largefile-aware getdents(2)
912 913 * and largefile-aware getdents64(2). s10_getdents() handles the non-largefile-
913 914 * aware case for 32-bit processes and all getdents(2) syscalls for 64-bit
914 915 * processes (64-bit processes use largefile-aware interfaces by default).
915 916 * See s10_getdents64() below for the largefile-aware getdents64(2) emulation
916 917 * function for 32-bit processes.
917 918 */
918 919 static int
919 920 s10_getdents(sysret_t *rval, int fd, struct dirent *buf, size_t nbyte)
920 921 {
921 922 return (s10_getdents_common(rval, fd, (char *)buf, nbyte, SYS_getdents,
922 923 offsetof(struct dirent, d_name),
923 924 offsetof(struct dirent, d_reclen)));
924 925 }
925 926
926 927 #ifndef _LP64
927 928 /*
928 929 * This is the largefile-aware version of getdents(2) for 32-bit processes.
929 930 * This exists for the same reason that s10_getdents() exists. See the comment
930 931 * above s10_getdents().
931 932 */
932 933 static int
933 934 s10_getdents64(sysret_t *rval, int fd, struct dirent64 *buf, size_t nbyte)
934 935 {
935 936 return (s10_getdents_common(rval, fd, (char *)buf, nbyte,
936 937 SYS_getdents64, offsetof(struct dirent64, d_name),
937 938 offsetof(struct dirent64, d_reclen)));
938 939 }
939 940 #endif /* !_LP64 */
940 941
941 942 #define S10_TRIVIAL_ACL_CNT 6
942 943 #define NATIVE_TRIVIAL_ACL_CNT 3
943 944
944 945 /*
945 946 * Check if the ACL qualifies as a trivial ACL based on the native
946 947 * interpretation.
947 948 */
948 949 static boolean_t
949 950 has_trivial_native_acl(int cmd, int cnt, const char *fname, int fd)
950 951 {
951 952 int i, err;
952 953 sysret_t rval;
953 954 ace_t buf[NATIVE_TRIVIAL_ACL_CNT];
954 955
955 956 if (fname != NULL)
956 957 err = __systemcall(&rval, SYS_pathconf + 1024, fname,
957 958 _PC_ACL_ENABLED);
958 959 else
959 960 err = __systemcall(&rval, SYS_fpathconf + 1024, fd,
960 961 _PC_ACL_ENABLED);
961 962 if (err != 0 || rval.sys_rval1 != _ACL_ACE_ENABLED)
962 963 return (B_FALSE);
963 964
964 965 /*
965 966 * If we just got the ACL cnt, we don't need to get it again, its
966 967 * passed in as the cnt arg.
967 968 */
968 969 if (cmd != ACE_GETACLCNT) {
969 970 if (fname != NULL) {
970 971 if (__systemcall(&rval, SYS_acl + 1024, fname,
971 972 ACE_GETACLCNT, 0, NULL) != 0)
972 973 return (B_FALSE);
973 974 } else {
974 975 if (__systemcall(&rval, SYS_facl + 1024, fd,
975 976 ACE_GETACLCNT, 0, NULL) != 0)
976 977 return (B_FALSE);
977 978 }
978 979 cnt = rval.sys_rval1;
979 980 }
980 981
981 982 if (cnt != NATIVE_TRIVIAL_ACL_CNT)
982 983 return (B_FALSE);
983 984
984 985 if (fname != NULL) {
985 986 if (__systemcall(&rval, SYS_acl + 1024, fname, ACE_GETACL, cnt,
986 987 buf) != 0)
987 988 return (B_FALSE);
988 989 } else {
989 990 if (__systemcall(&rval, SYS_facl + 1024, fd, ACE_GETACL, cnt,
990 991 buf) != 0)
991 992 return (B_FALSE);
992 993 }
993 994
994 995 /*
995 996 * The following is based on the logic from the native OS
996 997 * ace_trivial_common() to determine if the native ACL is trivial.
997 998 */
998 999 for (i = 0; i < cnt; i++) {
999 1000 switch (buf[i].a_flags & ACE_TYPE_FLAGS) {
1000 1001 case ACE_OWNER:
1001 1002 case ACE_GROUP|ACE_IDENTIFIER_GROUP:
1002 1003 case ACE_EVERYONE:
1003 1004 break;
1004 1005 default:
1005 1006 return (B_FALSE);
1006 1007 }
1007 1008
1008 1009 if (buf[i].a_flags & (ACE_FILE_INHERIT_ACE|
1009 1010 ACE_DIRECTORY_INHERIT_ACE|ACE_NO_PROPAGATE_INHERIT_ACE|
1010 1011 ACE_INHERIT_ONLY_ACE))
1011 1012 return (B_FALSE);
1012 1013
1013 1014 /*
1014 1015 * Special check for some special bits
1015 1016 *
1016 1017 * Don't allow anybody to deny reading basic
1017 1018 * attributes or a files ACL.
1018 1019 */
1019 1020 if (buf[i].a_access_mask & (ACE_READ_ACL|ACE_READ_ATTRIBUTES) &&
1020 1021 buf[i].a_type == ACE_ACCESS_DENIED_ACE_TYPE)
1021 1022 return (B_FALSE);
1022 1023
1023 1024 /*
1024 1025 * Delete permissions are never set by default
1025 1026 */
1026 1027 if (buf[i].a_access_mask & (ACE_DELETE|ACE_DELETE_CHILD))
1027 1028 return (B_FALSE);
1028 1029 /*
1029 1030 * only allow owner@ to have
1030 1031 * write_acl/write_owner/write_attributes/write_xattr/
1031 1032 */
1032 1033 if (buf[i].a_type == ACE_ACCESS_ALLOWED_ACE_TYPE &&
1033 1034 (!(buf[i].a_flags & ACE_OWNER) && (buf[i].a_access_mask &
1034 1035 (ACE_WRITE_OWNER|ACE_WRITE_ACL| ACE_WRITE_ATTRIBUTES|
1035 1036 ACE_WRITE_NAMED_ATTRS))))
1036 1037 return (B_FALSE);
1037 1038
1038 1039 }
1039 1040
1040 1041 return (B_TRUE);
1041 1042 }
1042 1043
1043 1044 /*
1044 1045 * The following logic is based on the S10 adjust_ace_pair_common() code.
1045 1046 */
1046 1047 static void
1047 1048 s10_adjust_ace_mask(void *pair, size_t access_off, size_t pairsize, mode_t mode)
1048 1049 {
1049 1050 char *datap = (char *)pair;
1050 1051 uint32_t *amask0 = (uint32_t *)(uintptr_t)(datap + access_off);
1051 1052 uint32_t *amask1 = (uint32_t *)(uintptr_t)(datap + pairsize +
1052 1053 access_off);
1053 1054
1054 1055 if (mode & S_IROTH)
1055 1056 *amask1 |= ACE_READ_DATA;
1056 1057 else
1057 1058 *amask0 |= ACE_READ_DATA;
1058 1059 if (mode & S_IWOTH)
1059 1060 *amask1 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
1060 1061 else
1061 1062 *amask0 |= ACE_WRITE_DATA|ACE_APPEND_DATA;
1062 1063 if (mode & S_IXOTH)
1063 1064 *amask1 |= ACE_EXECUTE;
1064 1065 else
1065 1066 *amask0 |= ACE_EXECUTE;
1066 1067 }
1067 1068
1068 1069 /*
1069 1070 * Construct a trivial S10 style ACL.
1070 1071 */
1071 1072 static int
1072 1073 make_trivial_s10_acl(const char *fname, int fd, ace_t *bp)
1073 1074 {
1074 1075 int err;
1075 1076 sysret_t rval;
1076 1077 struct stat64 buf;
1077 1078 ace_t trivial_s10_acl[] = {
1078 1079 {(uint_t)-1, 0, ACE_OWNER, ACE_ACCESS_DENIED_ACE_TYPE},
1079 1080 {(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
1080 1081 ACE_WRITE_NAMED_ATTRS, ACE_OWNER,
1081 1082 ACE_ACCESS_ALLOWED_ACE_TYPE},
1082 1083 {(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
1083 1084 ACE_ACCESS_DENIED_ACE_TYPE},
1084 1085 {(uint_t)-1, 0, ACE_GROUP|ACE_IDENTIFIER_GROUP,
1085 1086 ACE_ACCESS_ALLOWED_ACE_TYPE},
1086 1087 {(uint_t)-1, ACE_WRITE_ACL|ACE_WRITE_OWNER|ACE_WRITE_ATTRIBUTES|
1087 1088 ACE_WRITE_NAMED_ATTRS, ACE_EVERYONE,
1088 1089 ACE_ACCESS_DENIED_ACE_TYPE},
1089 1090 {(uint_t)-1, ACE_READ_ACL|ACE_READ_ATTRIBUTES|
1090 1091 ACE_READ_NAMED_ATTRS|ACE_SYNCHRONIZE, ACE_EVERYONE,
1091 1092 ACE_ACCESS_ALLOWED_ACE_TYPE}
1092 1093 };
1093 1094
1094 1095 if (fname != NULL) {
1095 1096 if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, AT_FDCWD,
1096 1097 fname, &buf, 0)) != 0)
1097 1098 return (err);
1098 1099 } else {
1099 1100 if ((err = __systemcall(&rval, SYS_fstatat64 + 1024, fd,
1100 1101 NULL, &buf, 0)) != 0)
1101 1102 return (err);
1102 1103 }
1103 1104
1104 1105 s10_adjust_ace_mask(&trivial_s10_acl[0], offsetof(ace_t, a_access_mask),
1105 1106 sizeof (ace_t), (buf.st_mode & 0700) >> 6);
1106 1107 s10_adjust_ace_mask(&trivial_s10_acl[2], offsetof(ace_t, a_access_mask),
1107 1108 sizeof (ace_t), (buf.st_mode & 0070) >> 3);
1108 1109 s10_adjust_ace_mask(&trivial_s10_acl[4], offsetof(ace_t, a_access_mask),
1109 1110 sizeof (ace_t), buf.st_mode & 0007);
1110 1111
1111 1112 if (brand_uucopy(&trivial_s10_acl, bp, sizeof (trivial_s10_acl)) != 0)
1112 1113 return (EFAULT);
1113 1114
1114 1115 return (0);
1115 1116 }
1116 1117
1117 1118 /*
1118 1119 * The definition of a trivial ace-style ACL (used by ZFS and NFSv4) has been
1119 1120 * simplified since S10. Instead of 6 entries on a trivial S10 ACE ACL we now
1120 1121 * have 3 streamlined entries. The new, simpler trivial style confuses S10
1121 1122 * commands such as 'ls -v' or 'cp -p' which don't see the expected S10 trivial
1122 1123 * ACL entries and thus assume that there is a complex ACL on the file.
1123 1124 *
1124 1125 * See: PSARC/2010/029 Improved ACL interoperability
1125 1126 *
1126 1127 * Note that the trival ACL detection code is implemented in acl_trival() in
1127 1128 * lib/libsec/common/aclutils.c. It always uses the acl() syscall (not the
1128 1129 * facl syscall) to determine if an ACL is trivial. However, we emulate both
1129 1130 * acl() and facl() so that the two provide consistent results.
1130 1131 *
1131 1132 * We don't currently try to emulate setting of ACLs since the primary
1132 1133 * consumer of this feature is SMB or NFSv4 servers, neither of which are
1133 1134 * supported in solaris10-branded zones. If ACLs are used they must be set on
1134 1135 * files using the native OS interpretation.
1135 1136 */
1136 1137 int
1137 1138 s10_acl(sysret_t *rval, const char *fname, int cmd, int nentries, void *aclbufp)
1138 1139 {
1139 1140 int res;
1140 1141
1141 1142 res = __systemcall(rval, SYS_acl + 1024, fname, cmd, nentries, aclbufp);
1142 1143
1143 1144 switch (cmd) {
1144 1145 case ACE_GETACLCNT:
1145 1146 if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
1146 1147 rval->sys_rval1, fname, 0)) {
1147 1148 rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1148 1149 }
1149 1150 break;
1150 1151 case ACE_GETACL:
1151 1152 if (res == 0 &&
1152 1153 has_trivial_native_acl(ACE_GETACL, 0, fname, 0) &&
1153 1154 nentries >= S10_TRIVIAL_ACL_CNT) {
1154 1155 res = make_trivial_s10_acl(fname, 0, aclbufp);
1155 1156 rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1156 1157 }
1157 1158 break;
1158 1159 }
1159 1160
1160 1161 return (res);
1161 1162 }
1162 1163
1163 1164 int
1164 1165 s10_facl(sysret_t *rval, int fdes, int cmd, int nentries, void *aclbufp)
1165 1166 {
1166 1167 int res;
1167 1168
1168 1169 res = __systemcall(rval, SYS_facl + 1024, fdes, cmd, nentries, aclbufp);
1169 1170
1170 1171 switch (cmd) {
1171 1172 case ACE_GETACLCNT:
1172 1173 if (res == 0 && has_trivial_native_acl(ACE_GETACLCNT,
1173 1174 rval->sys_rval1, NULL, fdes)) {
1174 1175 rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1175 1176 }
1176 1177 break;
1177 1178 case ACE_GETACL:
1178 1179 if (res == 0 &&
1179 1180 has_trivial_native_acl(ACE_GETACL, 0, NULL, fdes) &&
1180 1181 nentries >= S10_TRIVIAL_ACL_CNT) {
1181 1182 res = make_trivial_s10_acl(NULL, fdes, aclbufp);
1182 1183 rval->sys_rval1 = S10_TRIVIAL_ACL_CNT;
1183 1184 }
1184 1185 break;
1185 1186 }
1186 1187
1187 1188 return (res);
1188 1189 }
1189 1190
1190 1191 #define S10_AC_PROC (0x1 << 28)
1191 1192 #define S10_AC_TASK (0x2 << 28)
1192 1193 #define S10_AC_FLOW (0x4 << 28)
1193 1194 #define S10_AC_MODE(x) ((x) & 0xf0000000)
1194 1195 #define S10_AC_OPTION(x) ((x) & 0x0fffffff)
1195 1196
1196 1197 /*
1197 1198 * The mode shift, mode mask and option mask for acctctl have changed. The
1198 1199 * mode is currently the top full byte and the option is the lower 3 full bytes.
1199 1200 */
1200 1201 int
1201 1202 s10_acctctl(sysret_t *rval, int cmd, void *buf, size_t bufsz)
1202 1203 {
1203 1204 int mode = S10_AC_MODE(cmd);
1204 1205 int option = S10_AC_OPTION(cmd);
1205 1206
1206 1207 switch (mode) {
1207 1208 case S10_AC_PROC:
1208 1209 mode = AC_PROC;
1209 1210 break;
1210 1211 case S10_AC_TASK:
1211 1212 mode = AC_TASK;
1212 1213 break;
1213 1214 case S10_AC_FLOW:
1214 1215 mode = AC_FLOW;
1215 1216 break;
1216 1217 default:
1217 1218 return (B_TRUSS_POINT_3(rval, SYS_acctctl, EINVAL, cmd, buf,
1218 1219 bufsz));
1219 1220 }
1220 1221
1221 1222 return (__systemcall(rval, SYS_acctctl + 1024, mode | option, buf,
1222 1223 bufsz));
1223 1224 }
1224 1225
1225 1226 /*
1226 1227 * The Audit Policy parameters have changed due to:
1227 1228 * 6466722 audituser and AUDIT_USER are defined, unused, undocumented and
1228 1229 * should be removed.
1229 1230 *
1230 1231 * In S10 we had the following flag:
1231 1232 * #define AUDIT_USER 0x0040
1232 1233 * which doesn't exist in Solaris Next where the subsequent flags are shifted
1233 1234 * down. For example, in S10 we had:
1234 1235 * #define AUDIT_GROUP 0x0080
1235 1236 * but on Solaris Next we have:
1236 1237 * #define AUDIT_GROUP 0x0040
1237 1238 * AUDIT_GROUP has the value AUDIT_USER had in S10 and all of the subsequent
1238 1239 * bits are also shifted one place.
1239 1240 *
1240 1241 * When we're getting or setting the Audit Policy parameters we need to
1241 1242 * shift the outgoing or incoming bits into their proper positions. Since
1242 1243 * S10_AUDIT_USER was always unused, we always clear that bit on A_GETPOLICY.
1243 1244 *
1244 1245 * The command we care about, BSM_AUDITCTL, passes the most parameters (3),
1245 1246 * so declare this function to take up to 4 args and just pass them on.
1246 1247 * The number of parameters for s10_auditsys needs to be equal to the BSM_*
1247 1248 * subcommand that has the most parameters, since we want to pass all
1248 1249 * parameters through, regardless of which subcommands we interpose on.
1249 1250 *
1250 1251 * Note that the auditsys system call uses the SYSENT_AP macro wrapper instead
1251 1252 * of the more common SYSENT_CI macro. This means the return value is a
1252 1253 * SE_64RVAL so the syscall table uses RV_64RVAL.
1253 1254 */
1254 1255
1255 1256 #define S10_AUDIT_HMASK 0xffffffc0
1256 1257 #define S10_AUDIT_LMASK 0x3f
1257 1258 #define S10_AUC_NOSPACE 0x3
1258 1259
1259 1260 int
1260 1261 s10_auditsys(sysret_t *rval, int bsmcmd, intptr_t a0, intptr_t a1, intptr_t a2)
1261 1262 {
1262 1263 int err;
1263 1264 uint32_t m;
1264 1265
1265 1266 if (bsmcmd != BSM_AUDITCTL)
1266 1267 return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1,
1267 1268 a2));
1268 1269
1269 1270 if ((int)a0 == A_GETPOLICY) {
1270 1271 if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
1271 1272 &m, a2)) != 0)
1272 1273 return (err);
1273 1274 m = ((m & S10_AUDIT_HMASK) << 1) | (m & S10_AUDIT_LMASK);
1274 1275 if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
1275 1276 return (EFAULT);
1276 1277 return (0);
1277 1278
1278 1279 } else if ((int)a0 == A_SETPOLICY) {
1279 1280 if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
1280 1281 return (EFAULT);
1281 1282 m = ((m >> 1) & S10_AUDIT_HMASK) | (m & S10_AUDIT_LMASK);
1282 1283 return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
1283 1284 a2));
1284 1285 } else if ((int)a0 == A_GETCOND) {
1285 1286 if ((err = __systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0,
1286 1287 &m, a2)) != 0)
1287 1288 return (err);
1288 1289 if (m == AUC_NOSPACE)
1289 1290 m = S10_AUC_NOSPACE;
1290 1291 if (brand_uucopy(&m, (void *)a1, sizeof (m)) != 0)
1291 1292 return (EFAULT);
1292 1293 return (0);
1293 1294 } else if ((int)a0 == A_SETCOND) {
1294 1295 if (brand_uucopy((const void *)a1, &m, sizeof (m)) != 0)
1295 1296 return (EFAULT);
1296 1297 if (m == S10_AUC_NOSPACE)
1297 1298 m = AUC_NOSPACE;
1298 1299 return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, &m,
1299 1300 a2));
1300 1301 }
1301 1302
1302 1303 return (__systemcall(rval, SYS_auditsys + 1024, bsmcmd, a0, a1, a2));
1303 1304 }
1304 1305
1305 1306 /*
1306 1307 * Determine whether the executable passed to SYS_exec or SYS_execve is a
1307 1308 * native executable. The s10_npreload.so invokes the B_S10_NATIVE brand
1308 1309 * operation which patches up the processes exec info to eliminate any trace
1309 1310 * of the wrapper. That will make pgrep and other commands that examine
1310 1311 * process' executable names and command-line parameters work properly.
1311 1312 */
1312 1313 static int
1313 1314 s10_exec_native(sysret_t *rval, const char *fname, const char **argp,
1314 1315 const char **envp)
1315 1316 {
1316 1317 const char *filename = fname;
1317 1318 char path[64];
1318 1319 int err;
1319 1320
1320 1321 /* Get a copy of the executable we're trying to run */
1321 1322 path[0] = '\0';
1322 1323 (void) brand_uucopystr(filename, path, sizeof (path));
1323 1324
1324 1325 /* Check if we're trying to run a native binary */
1325 1326 if (strncmp(path, "/.SUNWnative/usr/lib/brand/solaris10/s10_native",
1326 1327 sizeof (path)) != 0)
1327 1328 return (0);
1328 1329
1329 1330 /* Skip the first element in the argv array */
1330 1331 argp++;
1331 1332
1332 1333 /*
1333 1334 * The the path of the dynamic linker is the second parameter
1334 1335 * of s10_native_exec().
1335 1336 */
1336 1337 if (brand_uucopy(argp, &filename, sizeof (char *)) != 0)
1337 1338 return (EFAULT);
1338 1339
1339 1340 /* If an exec call succeeds, it never returns */
1340 1341 err = __systemcall(rval, SYS_brand + 1024, B_EXEC_NATIVE, filename,
1341 1342 argp, envp, NULL, NULL, NULL);
1342 1343 brand_assert(err != 0);
1343 1344 return (err);
1344 1345 }
1345 1346
1346 1347 /*
1347 1348 * Interpose on the SYS_exec syscall to detect native wrappers.
1348 1349 */
1349 1350 int
1350 1351 s10_exec(sysret_t *rval, const char *fname, const char **argp)
1351 1352 {
1352 1353 int err;
1353 1354
1354 1355 if ((err = s10_exec_native(rval, fname, argp, NULL)) != 0)
1355 1356 return (err);
1356 1357
1357 1358 /* If an exec call succeeds, it never returns */
1358 1359 err = __systemcall(rval, SYS_execve + 1024, fname, argp, NULL);
1359 1360 brand_assert(err != 0);
1360 1361 return (err);
1361 1362 }
1362 1363
1363 1364 /*
1364 1365 * Interpose on the SYS_execve syscall to detect native wrappers.
1365 1366 */
1366 1367 int
1367 1368 s10_execve(sysret_t *rval, const char *fname, const char **argp,
1368 1369 const char **envp)
1369 1370 {
1370 1371 int err;
1371 1372
1372 1373 if ((err = s10_exec_native(rval, fname, argp, envp)) != 0)
1373 1374 return (err);
1374 1375
1375 1376 /* If an exec call succeeds, it never returns */
1376 1377 err = __systemcall(rval, SYS_execve + 1024, fname, argp, envp);
1377 1378 brand_assert(err != 0);
1378 1379 return (err);
1379 1380 }
1380 1381
1381 1382 /*
1382 1383 * S10's issetugid() syscall is now a subcode to privsys().
1383 1384 */
1384 1385 static int
1385 1386 s10_issetugid(sysret_t *rval)
1386 1387 {
1387 1388 return (__systemcall(rval, SYS_privsys + 1024, PRIVSYS_ISSETUGID,
1388 1389 0, 0, 0, 0, 0));
1389 1390 }
1390 1391
1391 1392 /*
1392 1393 * S10's socket() syscall does not split type and flags
1393 1394 */
1394 1395 static int
1395 1396 s10_so_socket(sysret_t *rval, int domain, int type, int protocol,
1396 1397 char *devpath, int version)
1397 1398 {
1398 1399 if ((type & ~SOCK_TYPE_MASK) != 0) {
1399 1400 errno = EINVAL;
1400 1401 return (-1);
1401 1402 }
1402 1403 return (__systemcall(rval, SYS_so_socket + 1024, domain, type,
1403 1404 protocol, devpath, version));
1404 1405 }
1405 1406
1406 1407 /*
1407 1408 * S10's pipe() syscall has a different calling convention
1408 1409 */
1409 1410 static int
1410 1411 s10_pipe(sysret_t *rval)
1411 1412 {
1412 1413 int fds[2], err;
1413 1414 if ((err = __systemcall(rval, SYS_pipe + 1024, fds, 0)) != 0)
1414 1415 return (err);
1415 1416
1416 1417 rval->sys_rval1 = fds[0];
1417 1418 rval->sys_rval2 = fds[1];
1418 1419 return (0);
1419 1420 }
1420 1421
1421 1422 /*
1422 1423 * S10's accept() syscall takes three arguments
1423 1424 */
1424 1425 static int
1425 1426 s10_accept(sysret_t *rval, int sock, struct sockaddr *addr, uint_t *addrlen,
1426 1427 int version)
1427 1428 {
1428 1429 return (__systemcall(rval, SYS_accept + 1024, sock, addr, addrlen,
1429 1430 version, 0));
1430 1431 }
1431 1432
1432 1433 static long
1433 1434 s10_uname(sysret_t *rv, uintptr_t p1)
1434 1435 {
1435 1436 struct utsname un, *unp = (struct utsname *)p1;
1436 1437 int rev, err;
1437 1438
1438 1439 if ((err = __systemcall(rv, SYS_uname + 1024, &un)) != 0)
1439 1440 return (err);
1440 1441
1441 1442 rev = atoi(&un.release[2]);
1442 1443 brand_assert(rev >= 11);
1443 1444 bzero(un.release, _SYS_NMLN);
1444 1445 (void) strlcpy(un.release, S10_UTS_RELEASE, _SYS_NMLN);
1445 1446 bzero(un.version, _SYS_NMLN);
1446 1447 (void) strlcpy(un.version, S10_UTS_VERSION, _SYS_NMLN);
1447 1448
1448 1449 /* copy out the modified uname info */
1449 1450 return (brand_uucopy(&un, unp, sizeof (un)));
1450 1451 }
1451 1452
1452 1453 int
1453 1454 s10_sysconfig(sysret_t *rv, int which)
1454 1455 {
1455 1456 long value;
1456 1457
1457 1458 /*
1458 1459 * We must interpose on the sysconfig(2) requests
1459 1460 * that deal with the realtime signal number range.
1460 1461 * All others get passed to the native sysconfig(2).
1461 1462 */
1462 1463 switch (which) {
1463 1464 case _CONFIG_RTSIG_MAX:
1464 1465 value = S10_SIGRTMAX - S10_SIGRTMIN + 1;
1465 1466 break;
1466 1467 case _CONFIG_SIGRT_MIN:
1467 1468 value = S10_SIGRTMIN;
1468 1469 break;
1469 1470 case _CONFIG_SIGRT_MAX:
1470 1471 value = S10_SIGRTMAX;
1471 1472 break;
1472 1473 default:
1473 1474 return (__systemcall(rv, SYS_sysconfig + 1024, which));
1474 1475 }
1475 1476
1476 1477 (void) B_TRUSS_POINT_1(rv, SYS_sysconfig, 0, which);
1477 1478 rv->sys_rval1 = value;
1478 1479 rv->sys_rval2 = 0;
1479 1480
1480 1481 return (0);
1481 1482 }
1482 1483
1483 1484 int
1484 1485 s10_sysinfo(sysret_t *rv, int command, char *buf, long count)
1485 1486 {
1486 1487 char *value;
1487 1488 int len;
1488 1489
1489 1490 /*
1490 1491 * We must interpose on the sysinfo(2) commands SI_RELEASE and
1491 1492 * SI_VERSION; all others get passed to the native sysinfo(2)
1492 1493 * command.
1493 1494 */
1494 1495 switch (command) {
1495 1496 case SI_RELEASE:
1496 1497 value = S10_UTS_RELEASE;
1497 1498 break;
1498 1499
1499 1500 case SI_VERSION:
1500 1501 value = S10_UTS_VERSION;
1501 1502 break;
1502 1503
1503 1504 default:
1504 1505 /*
1505 1506 * The default action is to pass the command to the
1506 1507 * native sysinfo(2) syscall.
1507 1508 */
1508 1509 return (__systemcall(rv, SYS_systeminfo + 1024,
1509 1510 command, buf, count));
1510 1511 }
1511 1512
1512 1513 len = strlen(value) + 1;
1513 1514 if (count > 0) {
1514 1515 if (brand_uucopystr(value, buf, count) != 0)
1515 1516 return (EFAULT);
1516 1517
1517 1518 /*
1518 1519 * Assure NULL termination of buf as brand_uucopystr() doesn't.
1519 1520 */
1520 1521 if (len > count && brand_uucopy("\0", buf + (count - 1), 1)
1521 1522 != 0)
1522 1523 return (EFAULT);
1523 1524 }
1524 1525
1525 1526 /*
1526 1527 * On success, sysinfo(2) returns the size of buffer required to hold
1527 1528 * the complete value plus its terminating NULL byte.
1528 1529 */
1529 1530 (void) B_TRUSS_POINT_3(rv, SYS_systeminfo, 0, command, buf, count);
1530 1531 rv->sys_rval1 = len;
1531 1532 rv->sys_rval2 = 0;
1532 1533 return (0);
1533 1534 }
1534 1535
1535 1536 #if defined(__x86)
1536 1537 #if defined(__amd64)
1537 1538 /*
1538 1539 * 64-bit x86 LWPs created by SYS_lwp_create start here if they need to set
1539 1540 * their %fs registers to the legacy Solaris 10 selector value.
1540 1541 *
1541 1542 * This function does three things:
1542 1543 *
1543 1544 * 1. Trap to the kernel so that it can set %fs to the legacy Solaris 10
1544 1545 * selector value.
1545 1546 * 2. Read the LWP's true entry point (the entry point supplied by libc
1546 1547 * when SYS_lwp_create was invoked) from %r14.
1547 1548 * 3. Eliminate this function's stack frame and pass control to the LWP's
1548 1549 * true entry point.
1549 1550 *
1550 1551 * See the comment above s10_lwp_create_correct_fs() (see below) for the reason
1551 1552 * why this function exists.
1552 1553 */
1553 1554 /*ARGSUSED*/
1554 1555 static void
1555 1556 s10_lwp_create_entry_point(void *ulwp_structp)
1556 1557 {
1557 1558 sysret_t rval;
1558 1559
1559 1560 /*
1560 1561 * The new LWP's %fs register is initially zero, but libc won't
1561 1562 * function correctly when %fs is zero. Change the LWP's %fs register
1562 1563 * via SYS_brand.
1563 1564 */
1564 1565 (void) __systemcall(&rval, SYS_brand + 1024, B_S10_FSREGCORRECTION);
1565 1566
1566 1567 /*
1567 1568 * Jump to the true entry point, which is stored in %r14.
1568 1569 * Remove our stack frame before jumping so that
1569 1570 * s10_lwp_create_entry_point() won't be seen in stack traces.
1570 1571 *
1571 1572 * NOTE: s10_lwp_create_entry_point() pushes %r12 onto its stack frame
1572 1573 * so that it can use it as a temporary register. We don't restore %r12
1573 1574 * in this assembly block because we don't care about its value (and
1574 1575 * neither does _lwp_start()). Besides, the System V ABI AMD64
1575 1576 * Actirecture Processor Supplement doesn't specify that %r12 should
1576 1577 * have a special value when LWPs start, so we can ignore its value when
1577 1578 * we jump to the true entry point. Furthermore, %r12 is a callee-saved
1578 1579 * register, so the true entry point should push %r12 onto its stack
1579 1580 * before using the register. We ignore %r14 after we read it for
1580 1581 * similar reasons.
1581 1582 *
1582 1583 * NOTE: The compiler will generate a function epilogue for this
1583 1584 * function despite the fact that the LWP will never execute it.
1584 1585 * We could hand-code this entire function in assembly to eliminate
1585 1586 * the epilogue, but the epilogue is only three or four instructions,
1586 1587 * so we wouldn't save much space. Besides, why would we want
1587 1588 * to create yet another ugly, hard-to-maintain assembly function when
1588 1589 * we could write most of it in C?
1589 1590 */
1590 1591 __asm__ __volatile__(
1591 1592 "movq %0, %%rdi\n\t" /* pass ulwp_structp as arg1 */
1592 1593 "movq %%rbp, %%rsp\n\t" /* eliminate the stack frame */
1593 1594 "popq %%rbp\n\t"
1594 1595 "jmp *%%r14\n\t" /* jump to the true entry point */
1595 1596 : : "r" (ulwp_structp));
1596 1597 /*NOTREACHED*/
1597 1598 }
1598 1599
1599 1600 /*
1600 1601 * The S10 libc expects that %fs will be nonzero for new 64-bit x86 LWPs but the
1601 1602 * Nevada kernel clears %fs for such LWPs. Unforunately, new LWPs do not issue
1602 1603 * SYS_lwp_private (see s10_lwp_private() below) after they are created, so
1603 1604 * we must ensure that new LWPs invoke a brand operation that sets %fs to a
1604 1605 * nonzero value immediately after their creation.
1605 1606 *
1606 1607 * The easiest way to do this is to make new LWPs start at a special function,
1607 1608 * s10_lwp_create_entry_point() (see its definition above), that invokes the
1608 1609 * brand operation that corrects %fs. We'll store the entry points of new LWPs
1609 1610 * in their %r14 registers so that s10_lwp_create_entry_point() can find and
1610 1611 * call them after invoking the special brand operation. %r14 is a callee-saved
1611 1612 * register; therefore, any functions invoked by s10_lwp_create_entry_point()
1612 1613 * and all functions dealing with signals (e.g., sigacthandler()) will preserve
1613 1614 * %r14 for s10_lwp_create_entry_point().
1614 1615 *
1615 1616 * The Nevada kernel can safely work with nonzero %fs values because the kernel
1616 1617 * configures per-thread %fs segment descriptors so that the legacy %fs selector
1617 1618 * value will still work. See the comment in lwp_load() regarding %fs and
1618 1619 * %fsbase in 64-bit x86 processes.
1619 1620 *
1620 1621 * This emulation exists thanks to CRs 6467491 and 6501650.
1621 1622 */
1622 1623 static int
1623 1624 s10_lwp_create_correct_fs(sysret_t *rval, ucontext_t *ucp, int flags,
1624 1625 id_t *new_lwp)
1625 1626 {
1626 1627 ucontext_t s10_uc;
1627 1628
1628 1629 /*
1629 1630 * Copy the supplied ucontext_t structure to the local stack
1630 1631 * frame and store the new LWP's entry point (the value of %rip
1631 1632 * stored in the ucontext_t) in the new LWP's %r14 register.
1632 1633 * Then make s10_lwp_create_entry_point() the new LWP's entry
1633 1634 * point.
1634 1635 */
1635 1636 if (brand_uucopy(ucp, &s10_uc, sizeof (s10_uc)) != 0)
1636 1637 return (EFAULT);
1637 1638
1638 1639 s10_uc.uc_mcontext.gregs[REG_R14] = s10_uc.uc_mcontext.gregs[REG_RIP];
1639 1640 s10_uc.uc_mcontext.gregs[REG_RIP] = (greg_t)s10_lwp_create_entry_point;
1640 1641
1641 1642 /* fix up the signal mask */
1642 1643 if (s10_uc.uc_flags & UC_SIGMASK)
1643 1644 (void) s10sigset_to_native(&s10_uc.uc_sigmask,
1644 1645 &s10_uc.uc_sigmask);
1645 1646
1646 1647 /*
1647 1648 * Issue SYS_lwp_create to create the new LWP. We pass the
1648 1649 * modified ucontext_t to make sure that the new LWP starts at
1649 1650 * s10_lwp_create_entry_point().
1650 1651 */
1651 1652 return (__systemcall(rval, SYS_lwp_create + 1024, &s10_uc,
1652 1653 flags, new_lwp));
1653 1654 }
1654 1655 #endif /* __amd64 */
1655 1656
1656 1657 /*
1657 1658 * SYS_lwp_private is issued by libc_init() to set %fsbase in 64-bit x86
1658 1659 * processes. The Nevada kernel sets %fs to zero but the S10 libc expects
1659 1660 * %fs to be nonzero. We'll pass the issued system call to the kernel untouched
1660 1661 * and invoke a brand operation to set %fs to the legacy S10 selector value.
1661 1662 *
1662 1663 * This emulation exists thanks to CRs 6467491 and 6501650.
1663 1664 */
1664 1665 static int
1665 1666 s10_lwp_private(sysret_t *rval, int cmd, int which, uintptr_t base)
1666 1667 {
1667 1668 #if defined(__amd64)
1668 1669 int err;
1669 1670
1670 1671 /*
1671 1672 * The current LWP's %fs register should be zero. Determine whether the
1672 1673 * Solaris 10 libc with which we're working functions correctly when %fs
1673 1674 * is zero by calling thr_main() after issuing the SYS_lwp_private
1674 1675 * syscall. If thr_main() barfs (returns -1), then change the LWP's %fs
1675 1676 * register via SYS_brand and patch brand_sysent_table so that issuing
1676 1677 * SYS_lwp_create executes s10_lwp_create_correct_fs() rather than the
1677 1678 * default s10_lwp_create(). s10_lwp_create_correct_fs() will
1678 1679 * guarantee that new LWPs will have correct %fs values.
1679 1680 */
1680 1681 if ((err = __systemcall(rval, SYS_lwp_private + 1024, cmd, which,
1681 1682 base)) != 0)
1682 1683 return (err);
1683 1684 if (thr_main() == -1) {
1684 1685 /*
1685 1686 * SYS_lwp_private is only issued by libc_init(), which is
1686 1687 * executed when libc is first loaded by ld.so.1. Thus we
1687 1688 * are guaranteed to be single-threaded at this point. Even
1688 1689 * if we were multithreaded at this point, writing a 64-bit
1689 1690 * value to the st_callc field of a brand_sysent_table
1690 1691 * entry is guaranteed to be atomic on 64-bit x86 chips
1691 1692 * as long as the field is not split across cache lines
1692 1693 * (It shouldn't be.). See chapter 8, section 1.1 of
1693 1694 * "The Intel 64 and IA32 Architectures Software Developer's
1694 1695 * Manual," Volume 3A for more details.
1695 1696 */
1696 1697 brand_sysent_table[SYS_lwp_create].st_callc =
1697 1698 (sysent_cb_t)s10_lwp_create_correct_fs;
1698 1699 return (__systemcall(rval, SYS_brand + 1024,
1699 1700 B_S10_FSREGCORRECTION));
1700 1701 }
1701 1702 return (0);
1702 1703 #else /* !__amd64 */
1703 1704 return (__systemcall(rval, SYS_lwp_private + 1024, cmd, which, base));
1704 1705 #endif /* !__amd64 */
1705 1706 }
1706 1707 #endif /* __x86 */
1707 1708
1708 1709 /*
1709 1710 * The Opensolaris versions of lwp_mutex_timedlock() and lwp_mutex_trylock()
1710 1711 * add an extra argument to the interfaces, a uintptr_t value for the mutex's
1711 1712 * mutex_owner field. The Solaris 10 libc assigns the mutex_owner field at
1712 1713 * user-level, so we just make the extra argument be zero in both syscalls.
1713 1714 */
1714 1715
1715 1716 static int
1716 1717 s10_lwp_mutex_timedlock(sysret_t *rval, lwp_mutex_t *lp, timespec_t *tsp)
1717 1718 {
1718 1719 return (__systemcall(rval, SYS_lwp_mutex_timedlock + 1024, lp, tsp, 0));
1719 1720 }
1720 1721
1721 1722 static int
1722 1723 s10_lwp_mutex_trylock(sysret_t *rval, lwp_mutex_t *lp)
1723 1724 {
1724 1725 return (__systemcall(rval, SYS_lwp_mutex_trylock + 1024, lp, 0));
1725 1726 }
1726 1727
1727 1728 /*
1728 1729 * If the emul_global_zone flag is set then emulate some aspects of the
1729 1730 * zone system call. In particular, emulate the global zone ID on the
1730 1731 * ZONE_LOOKUP subcommand and emulate some of the global zone attributes
1731 1732 * on the ZONE_GETATTR subcommand. If the flag is not set or we're performing
1732 1733 * some other operation, simply pass the calls through.
1733 1734 */
1734 1735 int
1735 1736 s10_zone(sysret_t *rval, int cmd, void *arg1, void *arg2, void *arg3,
1736 1737 void *arg4)
1737 1738 {
1738 1739 char *aval;
1739 1740 int len;
1740 1741 zoneid_t zid;
1741 1742 int attr;
1742 1743 char *buf;
1743 1744 size_t bufsize;
1744 1745
1745 1746 /*
1746 1747 * We only emulate the zone syscall for a subset of specific commands,
1747 1748 * otherwise we just pass the call through.
1748 1749 */
1749 1750 if (!emul_global_zone)
1750 1751 return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2,
1751 1752 arg3, arg4));
1752 1753
1753 1754 switch (cmd) {
1754 1755 case ZONE_LOOKUP:
1755 1756 (void) B_TRUSS_POINT_1(rval, SYS_zone, 0, cmd);
1756 1757 rval->sys_rval1 = GLOBAL_ZONEID;
1757 1758 rval->sys_rval2 = 0;
1758 1759 return (0);
1759 1760
1760 1761 case ZONE_GETATTR:
1761 1762 zid = (zoneid_t)(uintptr_t)arg1;
1762 1763 attr = (int)(uintptr_t)arg2;
1763 1764 buf = (char *)arg3;
1764 1765 bufsize = (size_t)arg4;
1765 1766
1766 1767 /*
1767 1768 * If the request is for the global zone then we're emulating
1768 1769 * that, otherwise pass this thru.
1769 1770 */
1770 1771 if (zid != GLOBAL_ZONEID)
1771 1772 goto passthru;
1772 1773
1773 1774 switch (attr) {
1774 1775 case ZONE_ATTR_NAME:
1775 1776 aval = GLOBAL_ZONENAME;
1776 1777 break;
1777 1778
1778 1779 case ZONE_ATTR_BRAND:
1779 1780 aval = NATIVE_BRAND_NAME;
1780 1781 break;
1781 1782 default:
1782 1783 /*
1783 1784 * We only emulate a subset of the attrs, use the
1784 1785 * real zone id to pass thru the rest.
1785 1786 */
1786 1787 arg1 = (void *)(uintptr_t)zoneid;
1787 1788 goto passthru;
1788 1789 }
1789 1790
1790 1791 (void) B_TRUSS_POINT_5(rval, SYS_zone, 0, cmd, zid, attr,
1791 1792 buf, bufsize);
1792 1793
1793 1794 len = strlen(aval) + 1;
1794 1795 if (len > bufsize)
1795 1796 return (ENAMETOOLONG);
1796 1797
1797 1798 if (buf != NULL) {
1798 1799 if (len == 1) {
1799 1800 if (brand_uucopy("\0", buf, 1) != 0)
1800 1801 return (EFAULT);
1801 1802 } else {
1802 1803 if (brand_uucopystr(aval, buf, len) != 0)
1803 1804 return (EFAULT);
1804 1805
1805 1806 /*
1806 1807 * Assure NULL termination of "buf" as
1807 1808 * brand_uucopystr() does NOT.
1808 1809 */
1809 1810 if (brand_uucopy("\0", buf + (len - 1), 1) != 0)
1810 1811 return (EFAULT);
1811 1812 }
1812 1813 }
1813 1814
1814 1815 rval->sys_rval1 = len;
1815 1816 rval->sys_rval2 = 0;
1816 1817 return (0);
1817 1818
1818 1819 default:
1819 1820 break;
1820 1821 }
1821 1822
1822 1823 passthru:
1823 1824 return (__systemcall(rval, SYS_zone + 1024, cmd, arg1, arg2, arg3,
1824 1825 arg4));
1825 1826 }
1826 1827
1827 1828 /*ARGSUSED*/
1828 1829 int
1829 1830 brand_init(int argc, char *argv[], char *envp[])
1830 1831 {
1831 1832 sysret_t rval;
1832 1833 ulong_t ldentry;
1833 1834 int err;
1834 1835 char *bname;
1835 1836
1836 1837 brand_pre_init();
1837 1838
1838 1839 /*
1839 1840 * Cache the pid of the zone's init process and determine if
1840 1841 * we're init(1m) for the zone. Remember: we might be init
1841 1842 * now, but as soon as we fork(2) we won't be.
1842 1843 */
1843 1844 (void) get_initpid_info();
1844 1845
1845 1846 /* get the current zoneid */
1846 1847 err = __systemcall(&rval, SYS_zone, ZONE_LOOKUP, NULL);
1847 1848 brand_assert(err == 0);
1848 1849 zoneid = (zoneid_t)rval.sys_rval1;
1849 1850
1850 1851 /* Get the zone's emulation bitmap. */
1851 1852 if ((err = __systemcall(&rval, SYS_zone, ZONE_GETATTR, zoneid,
1852 1853 S10_EMUL_BITMAP, emul_bitmap, sizeof (emul_bitmap))) != 0) {
1853 1854 brand_abort(err, "The zone's patch level is unsupported");
1854 1855 /*NOTREACHED*/
1855 1856 }
1856 1857
1857 1858 bname = basename(argv[0]);
1858 1859
1859 1860 /*
1860 1861 * In general we want the S10 commands that are zone-aware to continue
1861 1862 * to behave as they normally do within a zone. Since these commands
1862 1863 * are zone-aware, they should continue to "do the right thing".
1863 1864 * However, some zone-aware commands aren't going to work the way
1864 1865 * we expect them to inside the branded zone. In particular, the pkg
1865 1866 * and patch commands will not properly manage all pkgs/patches
1866 1867 * unless the commands think they are running in the global zone. For
1867 1868 * these commands we want to emulate the global zone.
1868 1869 *
1869 1870 * We don't do any emulation for pkgcond since it is typically used
1870 1871 * in pkg/patch postinstall scripts and we want those scripts to do
1871 1872 * the right thing inside a zone.
1872 1873 *
1873 1874 * One issue is the handling of hollow pkgs. Since the pkgs are
1874 1875 * hollow, they won't use pkgcond in their postinstall scripts. These
1875 1876 * pkgs typically are installing drivers so we handle that by
1876 1877 * replacing add_drv and rem_drv in the s10_boot script.
1877 1878 */
1878 1879 if (strcmp("pkgadd", bname) == 0 || strcmp("pkgrm", bname) == 0 ||
1879 1880 strcmp("patchadd", bname) == 0 || strcmp("patchrm", bname) == 0)
1880 1881 emul_global_zone = B_TRUE;
1881 1882
1882 1883 ldentry = brand_post_init(S10_VERSION, argc, argv, envp);
1883 1884
1884 1885 brand_runexe(argv, ldentry);
1885 1886 /*NOTREACHED*/
1886 1887 brand_abort(0, "brand_runexe() returned");
1887 1888 return (-1);
1888 1889 }
1889 1890
1890 1891 /*
1891 1892 * This table must have at least NSYSCALL entries in it.
1892 1893 *
1893 1894 * The second parameter of each entry in the brand_sysent_table
1894 1895 * contains the number of parameters and flags that describe the
1895 1896 * syscall return value encoding. See the block comments at the
1896 1897 * top of this file for more information about the syscall return
1897 1898 * value flags and when they should be used.
1898 1899 */
1899 1900 brand_sysent_table_t brand_sysent_table[] = {
1900 1901 #if defined(__sparc) && !defined(__sparcv9)
1901 1902 EMULATE(brand_indir, 9 | RV_64RVAL), /* 0 */
1902 1903 #else
1903 1904 NOSYS, /* 0 */
1904 1905 #endif
1905 1906 NOSYS, /* 1 */
1906 1907 EMULATE(s10_forkall, 0 | RV_32RVAL2), /* 2 */
1907 1908 NOSYS, /* 3 */
1908 1909 NOSYS, /* 4 */
1909 1910 EMULATE(s10_open, 3 | RV_DEFAULT), /* 5 */
1910 1911 NOSYS, /* 6 */
1911 1912 EMULATE(s10_wait, 0 | RV_32RVAL2), /* 7 */
1912 1913 EMULATE(s10_creat, 2 | RV_DEFAULT), /* 8 */
1913 1914 EMULATE(s10_link, 2 | RV_DEFAULT), /* 9 */
1914 1915 EMULATE(s10_unlink, 1 | RV_DEFAULT), /* 10 */
1915 1916 EMULATE(s10_exec, 2 | RV_DEFAULT), /* 11 */
1916 1917 NOSYS, /* 12 */
1917 1918 NOSYS, /* 13 */
1918 1919 EMULATE(s10_mknod, 3 | RV_DEFAULT), /* 14 */
1919 1920 EMULATE(s10_chmod, 2 | RV_DEFAULT), /* 15 */
1920 1921 EMULATE(s10_chown, 3 | RV_DEFAULT), /* 16 */
1921 1922 NOSYS, /* 17 */
1922 1923 EMULATE(s10_stat, 2 | RV_DEFAULT), /* 18 */
1923 1924 NOSYS, /* 19 */
1924 1925 NOSYS, /* 20 */
1925 1926 NOSYS, /* 21 */
1926 1927 EMULATE(s10_umount, 1 | RV_DEFAULT), /* 22 */
1927 1928 NOSYS, /* 23 */
1928 1929 NOSYS, /* 24 */
1929 1930 NOSYS, /* 25 */
1930 1931 NOSYS, /* 26 */
1931 1932 NOSYS, /* 27 */
1932 1933 EMULATE(s10_fstat, 2 | RV_DEFAULT), /* 28 */
1933 1934 NOSYS, /* 29 */
1934 1935 EMULATE(s10_utime, 2 | RV_DEFAULT), /* 30 */
1935 1936 NOSYS, /* 31 */
1936 1937 NOSYS, /* 32 */
1937 1938 EMULATE(s10_access, 2 | RV_DEFAULT), /* 33 */
1938 1939 NOSYS, /* 34 */
1939 1940 NOSYS, /* 35 */
1940 1941 NOSYS, /* 36 */
1941 1942 EMULATE(s10_kill, 2 | RV_DEFAULT), /* 37 */
1942 1943 NOSYS, /* 38 */
1943 1944 NOSYS, /* 39 */
1944 1945 NOSYS, /* 40 */
1945 1946 EMULATE(s10_dup, 1 | RV_DEFAULT), /* 41 */
1946 1947 EMULATE(s10_pipe, 0 | RV_32RVAL2), /* 42 */
1947 1948 NOSYS, /* 43 */
1948 1949 NOSYS, /* 44 */
1949 1950 NOSYS, /* 45 */
1950 1951 NOSYS, /* 46 */
1951 1952 NOSYS, /* 47 */
1952 1953 NOSYS, /* 48 */
1953 1954 NOSYS, /* 49 */
1954 1955 NOSYS, /* 50 */
1955 1956 NOSYS, /* 51 */
1956 1957 NOSYS, /* 52 */
1957 1958 NOSYS, /* 53 */
1958 1959 EMULATE(s10_ioctl, 3 | RV_DEFAULT), /* 54 */
1959 1960 NOSYS, /* 55 */
1960 1961 NOSYS, /* 56 */
1961 1962 NOSYS, /* 57 */
1962 1963 NOSYS, /* 58 */
1963 1964 EMULATE(s10_execve, 3 | RV_DEFAULT), /* 59 */
1964 1965 NOSYS, /* 60 */
1965 1966 NOSYS, /* 61 */
1966 1967 NOSYS, /* 62 */
1967 1968 NOSYS, /* 63 */
1968 1969 NOSYS, /* 64 */
1969 1970 NOSYS, /* 65 */
1970 1971 NOSYS, /* 66 */
1971 1972 NOSYS, /* 67 */
1972 1973 NOSYS, /* 68 */
1973 1974 NOSYS, /* 69 */
1974 1975 NOSYS, /* 70 */
1975 1976 EMULATE(s10_acctctl, 3 | RV_DEFAULT), /* 71 */
1976 1977 NOSYS, /* 72 */
1977 1978 NOSYS, /* 73 */
1978 1979 NOSYS, /* 74 */
1979 1980 EMULATE(s10_issetugid, 0 | RV_DEFAULT), /* 75 */
1980 1981 EMULATE(s10_fsat, 6 | RV_DEFAULT), /* 76 */
1981 1982 NOSYS, /* 77 */
1982 1983 NOSYS, /* 78 */
1983 1984 EMULATE(s10_rmdir, 1 | RV_DEFAULT), /* 79 */
1984 1985 EMULATE(s10_mkdir, 2 | RV_DEFAULT), /* 80 */
1985 1986 EMULATE(s10_getdents, 3 | RV_DEFAULT), /* 81 */
1986 1987 NOSYS, /* 82 */
1987 1988 NOSYS, /* 83 */
1988 1989 NOSYS, /* 84 */
1989 1990 NOSYS, /* 85 */
1990 1991 NOSYS, /* 86 */
1991 1992 EMULATE(s10_poll, 3 | RV_DEFAULT), /* 87 */
1992 1993 EMULATE(s10_lstat, 2 | RV_DEFAULT), /* 88 */
1993 1994 EMULATE(s10_symlink, 2 | RV_DEFAULT), /* 89 */
1994 1995 EMULATE(s10_readlink, 3 | RV_DEFAULT), /* 90 */
1995 1996 NOSYS, /* 91 */
1996 1997 NOSYS, /* 92 */
1997 1998 EMULATE(s10_fchmod, 2 | RV_DEFAULT), /* 93 */
1998 1999 EMULATE(s10_fchown, 3 | RV_DEFAULT), /* 94 */
1999 2000 EMULATE(s10_sigprocmask, 3 | RV_DEFAULT), /* 95 */
2000 2001 EMULATE(s10_sigsuspend, 1 | RV_DEFAULT), /* 96 */
2001 2002 NOSYS, /* 97 */
2002 2003 EMULATE(s10_sigaction, 3 | RV_DEFAULT), /* 98 */
2003 2004 EMULATE(s10_sigpending, 2 | RV_DEFAULT), /* 99 */
2004 2005 NOSYS, /* 100 */
2005 2006 NOSYS, /* 101 */
2006 2007 NOSYS, /* 102 */
2007 2008 NOSYS, /* 103 */
2008 2009 NOSYS, /* 104 */
2009 2010 NOSYS, /* 105 */
2010 2011 NOSYS, /* 106 */
2011 2012 EMULATE(s10_waitid, 4 | RV_DEFAULT), /* 107 */
2012 2013 EMULATE(s10_sigsendsys, 2 | RV_DEFAULT), /* 108 */
2013 2014 NOSYS, /* 109 */
2014 2015 NOSYS, /* 110 */
2015 2016 NOSYS, /* 111 */
2016 2017 NOSYS, /* 112 */
2017 2018 NOSYS, /* 113 */
2018 2019 NOSYS, /* 114 */
2019 2020 NOSYS, /* 115 */
2020 2021 NOSYS, /* 116 */
2021 2022 NOSYS, /* 117 */
2022 2023 NOSYS, /* 118 */
2023 2024 NOSYS, /* 119 */
2024 2025 NOSYS, /* 120 */
2025 2026 NOSYS, /* 121 */
2026 2027 NOSYS, /* 122 */
2027 2028 #if defined(__x86)
2028 2029 EMULATE(s10_xstat, 3 | RV_DEFAULT), /* 123 */
2029 2030 EMULATE(s10_lxstat, 3 | RV_DEFAULT), /* 124 */
2030 2031 EMULATE(s10_fxstat, 3 | RV_DEFAULT), /* 125 */
2031 2032 EMULATE(s10_xmknod, 4 | RV_DEFAULT), /* 126 */
2032 2033 #else
2033 2034 NOSYS, /* 123 */
2034 2035 NOSYS, /* 124 */
2035 2036 NOSYS, /* 125 */
2036 2037 NOSYS, /* 126 */
2037 2038 #endif
2038 2039 NOSYS, /* 127 */
2039 2040 NOSYS, /* 128 */
2040 2041 NOSYS, /* 129 */
2041 2042 EMULATE(s10_lchown, 3 | RV_DEFAULT), /* 130 */
2042 2043 NOSYS, /* 131 */
2043 2044 NOSYS, /* 132 */
2044 2045 NOSYS, /* 133 */
2045 2046 EMULATE(s10_rename, 2 | RV_DEFAULT), /* 134 */
2046 2047 EMULATE(s10_uname, 1 | RV_DEFAULT), /* 135 */
2047 2048 NOSYS, /* 136 */
2048 2049 EMULATE(s10_sysconfig, 1 | RV_DEFAULT), /* 137 */
2049 2050 NOSYS, /* 138 */
2050 2051 EMULATE(s10_sysinfo, 3 | RV_DEFAULT), /* 139 */
2051 2052 NOSYS, /* 140 */
2052 2053 NOSYS, /* 141 */
2053 2054 NOSYS, /* 142 */
2054 2055 EMULATE(s10_fork1, 0 | RV_32RVAL2), /* 143 */
2055 2056 EMULATE(s10_sigtimedwait, 3 | RV_DEFAULT), /* 144 */
2056 2057 NOSYS, /* 145 */
2057 2058 NOSYS, /* 146 */
2058 2059 EMULATE(s10_lwp_sema_wait, 1 | RV_DEFAULT), /* 147 */
2059 2060 NOSYS, /* 148 */
2060 2061 NOSYS, /* 149 */
2061 2062 NOSYS, /* 150 */
2062 2063 NOSYS, /* 151 */
2063 2064 NOSYS, /* 152 */
2064 2065 NOSYS, /* 153 */
2065 2066 EMULATE(s10_utimes, 2 | RV_DEFAULT), /* 154 */
2066 2067 NOSYS, /* 155 */
2067 2068 NOSYS, /* 156 */
2068 2069 NOSYS, /* 157 */
2069 2070 NOSYS, /* 158 */
2070 2071 EMULATE(s10_lwp_create, 3 | RV_DEFAULT), /* 159 */
2071 2072 NOSYS, /* 160 */
2072 2073 NOSYS, /* 161 */
2073 2074 NOSYS, /* 162 */
2074 2075 EMULATE(s10_lwp_kill, 2 | RV_DEFAULT), /* 163 */
2075 2076 NOSYS, /* 164 */
2076 2077 EMULATE(s10_lwp_sigmask, 3 | RV_32RVAL2), /* 165 */
2077 2078 #if defined(__x86)
2078 2079 EMULATE(s10_lwp_private, 3 | RV_DEFAULT), /* 166 */
2079 2080 #else
2080 2081 NOSYS, /* 166 */
2081 2082 #endif
2082 2083 NOSYS, /* 167 */
2083 2084 NOSYS, /* 168 */
2084 2085 EMULATE(s10_lwp_mutex_lock, 1 | RV_DEFAULT), /* 169 */
2085 2086 NOSYS, /* 170 */
2086 2087 NOSYS, /* 171 */
2087 2088 NOSYS, /* 172 */
2088 2089 NOSYS, /* 173 */
2089 2090 EMULATE(s10_pwrite, 4 | RV_DEFAULT), /* 174 */
2090 2091 NOSYS, /* 175 */
2091 2092 NOSYS, /* 176 */
2092 2093 NOSYS, /* 177 */
2093 2094 NOSYS, /* 178 */
2094 2095 NOSYS, /* 179 */
2095 2096 NOSYS, /* 180 */
2096 2097 NOSYS, /* 181 */
2097 2098 NOSYS, /* 182 */
2098 2099 NOSYS, /* 183 */
2099 2100 NOSYS, /* 184 */
2100 2101 EMULATE(s10_acl, 4 | RV_DEFAULT), /* 185 */
2101 2102 EMULATE(s10_auditsys, 4 | RV_64RVAL), /* 186 */
2102 2103 NOSYS, /* 187 */
2103 2104 NOSYS, /* 188 */
2104 2105 NOSYS, /* 189 */
2105 2106 EMULATE(s10_sigqueue, 4 | RV_DEFAULT), /* 190 */
2106 2107 NOSYS, /* 191 */
2107 2108 NOSYS, /* 192 */
2108 2109 NOSYS, /* 193 */
2109 2110 NOSYS, /* 194 */
2110 2111 NOSYS, /* 195 */
2111 2112 NOSYS, /* 196 */
2112 2113 NOSYS, /* 197 */
2113 2114 NOSYS, /* 198 */
2114 2115 NOSYS, /* 199 */
2115 2116 EMULATE(s10_facl, 4 | RV_DEFAULT), /* 200 */
2116 2117 NOSYS, /* 201 */
2117 2118 NOSYS, /* 202 */
2118 2119 NOSYS, /* 203 */
2119 2120 NOSYS, /* 204 */
2120 2121 EMULATE(s10_signotify, 3 | RV_DEFAULT), /* 205 */
2121 2122 NOSYS, /* 206 */
2122 2123 NOSYS, /* 207 */
2123 2124 NOSYS, /* 208 */
2124 2125 NOSYS, /* 209 */
2125 2126 EMULATE(s10_lwp_mutex_timedlock, 2 | RV_DEFAULT), /* 210 */
2126 2127 NOSYS, /* 211 */
2127 2128 NOSYS, /* 212 */
2128 2129 #if defined(_LP64)
2129 2130 NOSYS, /* 213 */
2130 2131 #else
2131 2132 EMULATE(s10_getdents64, 3 | RV_DEFAULT), /* 213 */
2132 2133 #endif
2133 2134 NOSYS, /* 214 */
2134 2135 #if defined(_LP64)
2135 2136 NOSYS, /* 215 */
2136 2137 NOSYS, /* 216 */
2137 2138 NOSYS, /* 217 */
2138 2139 #else
2139 2140 EMULATE(s10_stat64, 2 | RV_DEFAULT), /* 215 */
2140 2141 EMULATE(s10_lstat64, 2 | RV_DEFAULT), /* 216 */
2141 2142 EMULATE(s10_fstat64, 2 | RV_DEFAULT), /* 217 */
2142 2143 #endif
2143 2144 NOSYS, /* 218 */
2144 2145 NOSYS, /* 219 */
2145 2146 NOSYS, /* 220 */
2146 2147 NOSYS, /* 221 */
2147 2148 NOSYS, /* 222 */
2148 2149 #if defined(_LP64)
2149 2150 NOSYS, /* 223 */
2150 2151 NOSYS, /* 224 */
2151 2152 NOSYS, /* 225 */
2152 2153 #else
2153 2154 EMULATE(s10_pwrite64, 5 | RV_DEFAULT), /* 223 */
2154 2155 EMULATE(s10_creat64, 2 | RV_DEFAULT), /* 224 */
2155 2156 EMULATE(s10_open64, 3 | RV_DEFAULT), /* 225 */
2156 2157 #endif
2157 2158 NOSYS, /* 226 */
2158 2159 EMULATE(s10_zone, 5 | RV_DEFAULT), /* 227 */
2159 2160 NOSYS, /* 228 */
2160 2161 NOSYS, /* 229 */
2161 2162 EMULATE(s10_so_socket, 5 | RV_DEFAULT), /* 230 */
2162 2163 NOSYS, /* 231 */
2163 2164 NOSYS, /* 232 */
2164 2165 NOSYS, /* 233 */
2165 2166 EMULATE(s10_accept, 4 | RV_DEFAULT), /* 234 */
2166 2167 NOSYS, /* 235 */
2167 2168 NOSYS, /* 236 */
2168 2169 NOSYS, /* 237 */
2169 2170 NOSYS, /* 238 */
2170 2171 NOSYS, /* 239 */
2171 2172 NOSYS, /* 240 */
2172 2173 NOSYS, /* 241 */
2173 2174 NOSYS, /* 242 */
2174 2175 NOSYS, /* 243 */
2175 2176 NOSYS, /* 244 */
2176 2177 NOSYS, /* 245 */
2177 2178 NOSYS, /* 246 */
2178 2179 NOSYS, /* 247 */
2179 2180 NOSYS, /* 248 */
2180 2181 NOSYS, /* 249 */
2181 2182 NOSYS, /* 250 */
2182 2183 EMULATE(s10_lwp_mutex_trylock, 1 | RV_DEFAULT), /* 251 */
2183 2184 NOSYS, /* 252 */
2184 2185 NOSYS, /* 253 */
2185 2186 NOSYS, /* 254 */
2186 2187 NOSYS /* 255 */
2187 2188 };
↓ open down ↓ |
2117 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX