1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/errno.h> 27 #include <sys/exec.h> 28 #include <sys/kmem.h> 29 #include <sys/modctl.h> 30 #include <sys/model.h> 31 #include <sys/proc.h> 32 #include <sys/syscall.h> 33 #include <sys/systm.h> 34 #include <sys/thread.h> 35 #include <sys/cmn_err.h> 36 #include <sys/archsystm.h> 37 #include <sys/pathname.h> 38 39 #include <sys/machbrand.h> 40 #include <sys/brand.h> 41 #include "sn1_brand.h" 42 43 char *sn1_emulation_table = NULL; 44 45 void sn1_init_brand_data(zone_t *); 46 void sn1_free_brand_data(zone_t *); 47 void sn1_setbrand(proc_t *); 48 int sn1_getattr(zone_t *, int, void *, size_t *); 49 int sn1_setattr(zone_t *, int, void *, size_t); 50 int sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t, 51 uintptr_t, uintptr_t, uintptr_t); 52 void sn1_copy_procdata(proc_t *, proc_t *); 53 void sn1_proc_exit(struct proc *, klwp_t *); 54 void sn1_exec(); 55 int sn1_initlwp(klwp_t *); 56 void sn1_forklwp(klwp_t *, klwp_t *); 57 void sn1_freelwp(klwp_t *); 58 void sn1_lwpexit(klwp_t *); 59 int sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int, 60 long *, int, caddr_t, cred_t *, int); 61 62 /* sn1 brand */ 63 struct brand_ops sn1_brops = { 64 sn1_init_brand_data, 65 sn1_free_brand_data, 66 sn1_brandsys, 67 sn1_setbrand, 68 sn1_getattr, 69 sn1_setattr, 70 sn1_copy_procdata, 71 sn1_proc_exit, 72 sn1_exec, 73 lwp_setrval, 74 sn1_initlwp, 75 sn1_forklwp, 76 sn1_freelwp, 77 sn1_lwpexit, 78 sn1_elfexec 79 }; 80 81 #ifdef sparc 82 83 struct brand_mach_ops sn1_mops = { 84 sn1_brand_syscall_callback, 85 sn1_brand_syscall32_callback 86 }; 87 88 #else /* sparc */ 89 90 #ifdef __amd64 91 92 struct brand_mach_ops sn1_mops = { 93 sn1_brand_sysenter_callback, 94 NULL, 95 sn1_brand_int91_callback, 96 sn1_brand_syscall_callback, 97 sn1_brand_syscall32_callback, 98 NULL 99 }; 100 101 #else /* ! __amd64 */ 102 103 struct brand_mach_ops sn1_mops = { 104 sn1_brand_sysenter_callback, 105 NULL, 106 NULL, 107 sn1_brand_syscall_callback, 108 NULL, 109 NULL 110 }; 111 #endif /* __amd64 */ 112 113 #endif /* _sparc */ 114 115 struct brand sn1_brand = { 116 BRAND_VER_1, 117 "sn1", 118 &sn1_brops, 119 &sn1_mops 120 }; 121 122 static struct modlbrand modlbrand = { 123 &mod_brandops, /* type of module */ 124 "Solaris N-1 Brand", /* description of module */ 125 &sn1_brand /* driver ops */ 126 }; 127 128 static struct modlinkage modlinkage = { 129 MODREV_1, (void *)&modlbrand, NULL 130 }; 131 132 void 133 sn1_setbrand(proc_t *p) 134 { 135 ASSERT(p->p_brand == &sn1_brand); 136 ASSERT(p->p_brand_data == NULL); 137 138 /* 139 * We should only be called from exec(), when we know the process 140 * is single-threaded. 141 */ 142 ASSERT(p->p_tlist == p->p_tlist->t_forw); 143 144 p->p_brand_data = kmem_zalloc(sizeof (sn1_proc_data_t), KM_SLEEP); 145 (void) sn1_initlwp(p->p_tlist->t_lwp); 146 } 147 148 /* ARGSUSED */ 149 int 150 sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize) 151 { 152 return (EINVAL); 153 } 154 155 /* ARGSUSED */ 156 int 157 sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize) 158 { 159 return (EINVAL); 160 } 161 162 /* 163 * Get the address of the user-space system call handler from the user 164 * process and attach it to the proc structure. 165 */ 166 /*ARGSUSED*/ 167 int 168 sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, 169 uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6) 170 { 171 sn1_proc_data_t *spd; 172 sn1_brand_reg_t reg; 173 proc_t *p = curproc; 174 int err; 175 176 *rval = 0; 177 178 /* 179 * There is one operation that is suppored for non-branded 180 * process. B_EXEC_BRAND. This brand operaion is redundant 181 * since the kernel assumes a native process doing an exec 182 * in a branded zone is going to run a branded processes. 183 * hence we don't support this operation. 184 */ 185 if (cmd == B_EXEC_BRAND) 186 return (ENOSYS); 187 188 /* For all other operations this must be a branded process. */ 189 if (p->p_brand == &native_brand) 190 return (ENOSYS); 191 192 ASSERT(p->p_brand == &sn1_brand); 193 ASSERT(p->p_brand_data != NULL); 194 195 spd = (sn1_proc_data_t *)p->p_brand_data; 196 197 switch (cmd) { 198 case B_EXEC_NATIVE: 199 err = exec_common( 200 (char *)arg1, (const char **)arg2, (const char **)arg3, 201 EBA_NATIVE); 202 return (err); 203 204 case B_REGISTER: 205 if (p->p_model == DATAMODEL_NATIVE) { 206 if (copyin((void *)arg1, ®, sizeof (reg)) != 0) 207 return (EFAULT); 208 #if defined(_LP64) 209 } else { 210 sn1_brand_reg32_t reg32; 211 212 if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0) 213 return (EFAULT); 214 reg.sbr_version = reg32.sbr_version; 215 reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler; 216 #endif /* _LP64 */ 217 } 218 219 if (reg.sbr_version != SN1_VERSION) 220 return (ENOTSUP); 221 spd->spd_handler = reg.sbr_handler; 222 return (0); 223 case B_ELFDATA: 224 if (p->p_model == DATAMODEL_NATIVE) { 225 if (copyout(&spd->spd_elf_data, (void *)arg1, 226 sizeof (sn1_elf_data_t)) != 0) 227 return (EFAULT); 228 #if defined(_LP64) 229 } else { 230 sn1_elf_data32_t sed32; 231 232 sed32.sed_phdr = spd->spd_elf_data.sed_phdr; 233 sed32.sed_phent = spd->spd_elf_data.sed_phent; 234 sed32.sed_phnum = spd->spd_elf_data.sed_phnum; 235 sed32.sed_entry = spd->spd_elf_data.sed_entry; 236 sed32.sed_base = spd->spd_elf_data.sed_base; 237 sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry; 238 sed32.sed_lddata = spd->spd_elf_data.sed_lddata; 239 if (copyout(&sed32, (void *)arg1, sizeof (sed32)) != 0) 240 return (EFAULT); 241 #endif /* _LP64 */ 242 } 243 return (0); 244 } 245 246 return (EINVAL); 247 } 248 249 /* 250 * Copy the per-process brand data from a parent proc to a child. 251 */ 252 void 253 sn1_copy_procdata(proc_t *child, proc_t *parent) 254 { 255 sn1_proc_data_t *spd; 256 257 ASSERT(parent->p_brand == &sn1_brand); 258 ASSERT(child->p_brand == &sn1_brand); 259 ASSERT(parent->p_brand_data != NULL); 260 ASSERT(child->p_brand_data == NULL); 261 262 /* Just duplicate all the proc data of the parent for the child */ 263 spd = kmem_alloc(sizeof (sn1_proc_data_t), KM_SLEEP); 264 bcopy(parent->p_brand_data, spd, sizeof (sn1_proc_data_t)); 265 child->p_brand_data = spd; 266 } 267 268 /*ARGSUSED*/ 269 void 270 sn1_proc_exit(struct proc *p, klwp_t *l) 271 { 272 ASSERT(p->p_brand == &sn1_brand); 273 ASSERT(p->p_brand_data != NULL); 274 275 /* 276 * We should only be called from proc_exit(), when we know that 277 * process is single-threaded. 278 */ 279 ASSERT(p->p_tlist == p->p_tlist->t_forw); 280 281 /* upon exit, free our lwp brand data */ 282 (void) sn1_freelwp(ttolwp(curthread)); 283 284 /* upon exit, free our proc brand data */ 285 kmem_free(p->p_brand_data, sizeof (sn1_proc_data_t)); 286 p->p_brand_data = NULL; 287 } 288 289 void 290 sn1_exec() 291 { 292 sn1_proc_data_t *spd = curproc->p_brand_data; 293 294 ASSERT(curproc->p_brand == &sn1_brand); 295 ASSERT(curproc->p_brand_data != NULL); 296 ASSERT(ttolwp(curthread)->lwp_brand != NULL); 297 298 /* 299 * We should only be called from exec(), when we know the process 300 * is single-threaded. 301 */ 302 ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw); 303 304 /* Upon exec, reset our lwp brand data. */ 305 (void) sn1_freelwp(ttolwp(curthread)); 306 (void) sn1_initlwp(ttolwp(curthread)); 307 308 /* 309 * Upon exec, reset all the proc brand data, except for the elf 310 * data associated with the executable we are exec'ing. 311 */ 312 spd->spd_handler = NULL; 313 } 314 315 /*ARGSUSED*/ 316 int 317 sn1_initlwp(klwp_t *l) 318 { 319 ASSERT(l->lwp_procp->p_brand == &sn1_brand); 320 ASSERT(l->lwp_procp->p_brand_data != NULL); 321 ASSERT(l->lwp_brand == NULL); 322 l->lwp_brand = (void *)-1; 323 return (0); 324 } 325 326 /*ARGSUSED*/ 327 void 328 sn1_forklwp(klwp_t *p, klwp_t *c) 329 { 330 ASSERT(p->lwp_procp->p_brand == &sn1_brand); 331 ASSERT(c->lwp_procp->p_brand == &sn1_brand); 332 333 ASSERT(p->lwp_procp->p_brand_data != NULL); 334 ASSERT(c->lwp_procp->p_brand_data != NULL); 335 336 /* Both LWPs have already had been initialized via sn1_initlwp() */ 337 ASSERT(p->lwp_brand != NULL); 338 ASSERT(c->lwp_brand != NULL); 339 } 340 341 /*ARGSUSED*/ 342 void 343 sn1_freelwp(klwp_t *l) 344 { 345 ASSERT(l->lwp_procp->p_brand == &sn1_brand); 346 ASSERT(l->lwp_procp->p_brand_data != NULL); 347 ASSERT(l->lwp_brand != NULL); 348 l->lwp_brand = NULL; 349 } 350 351 /*ARGSUSED*/ 352 void 353 sn1_lwpexit(klwp_t *l) 354 { 355 proc_t *p = l->lwp_procp; 356 357 ASSERT(l->lwp_procp->p_brand == &sn1_brand); 358 ASSERT(l->lwp_procp->p_brand_data != NULL); 359 ASSERT(l->lwp_brand != NULL); 360 361 /* 362 * We should never be called for the last thread in a process. 363 * (That case is handled by sn1_proc_exit().) There for this lwp 364 * must be exiting from a multi-threaded process. 365 */ 366 ASSERT(p->p_tlist != p->p_tlist->t_forw); 367 368 l->lwp_brand = NULL; 369 } 370 371 /*ARGSUSED*/ 372 void 373 sn1_free_brand_data(zone_t *zone) 374 { 375 } 376 377 /*ARGSUSED*/ 378 void 379 sn1_init_brand_data(zone_t *zone) 380 { 381 } 382 383 #if defined(_LP64) 384 static void 385 Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst) 386 { 387 bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident)); 388 dst->e_type = src->e_type; 389 dst->e_machine = src->e_machine; 390 dst->e_version = src->e_version; 391 dst->e_entry = src->e_entry; 392 dst->e_phoff = src->e_phoff; 393 dst->e_shoff = src->e_shoff; 394 dst->e_flags = src->e_flags; 395 dst->e_ehsize = src->e_ehsize; 396 dst->e_phentsize = src->e_phentsize; 397 dst->e_phnum = src->e_phnum; 398 dst->e_shentsize = src->e_shentsize; 399 dst->e_shnum = src->e_shnum; 400 dst->e_shstrndx = src->e_shstrndx; 401 } 402 #endif /* _LP64 */ 403 404 int 405 sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, 406 int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred, 407 int brand_action) 408 { 409 vnode_t *nvp; 410 Ehdr ehdr; 411 Addr uphdr_vaddr; 412 intptr_t voffset; 413 int interp; 414 int i, err; 415 struct execenv env; 416 struct user *up = PTOU(curproc); 417 sn1_proc_data_t *spd; 418 sn1_elf_data_t sed, *sedp; 419 char *linker; 420 uintptr_t lddata; /* lddata of executable's linker */ 421 422 ASSERT(curproc->p_brand == &sn1_brand); 423 ASSERT(curproc->p_brand_data != NULL); 424 425 spd = (sn1_proc_data_t *)curproc->p_brand_data; 426 sedp = &spd->spd_elf_data; 427 428 args->brandname = SN1_BRANDNAME; 429 430 /* 431 * We will exec the brand library and then map in the target 432 * application and (optionally) the brand's default linker. 433 */ 434 if (args->to_model == DATAMODEL_NATIVE) { 435 args->emulator = SN1_LIB; 436 linker = SN1_LINKER; 437 #if defined(_LP64) 438 } else { 439 args->emulator = SN1_LIB32; 440 linker = SN1_LINKER32; 441 #endif /* _LP64 */ 442 } 443 444 if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, NULLVPP, 445 &nvp)) != 0) { 446 uprintf("%s: not found.", args->emulator); 447 return (err); 448 } 449 450 if (args->to_model == DATAMODEL_NATIVE) { 451 err = elfexec(nvp, uap, args, idatap, level + 1, execsz, 452 setid, exec_file, cred, brand_action); 453 #if defined(_LP64) 454 } else { 455 err = elf32exec(nvp, uap, args, idatap, level + 1, execsz, 456 setid, exec_file, cred, brand_action); 457 #endif /* _LP64 */ 458 } 459 VN_RELE(nvp); 460 if (err != 0) 461 return (err); 462 463 /* 464 * The u_auxv vectors are set up by elfexec to point to the brand 465 * emulation library and linker. Save these so they can be copied to 466 * the specific brand aux vectors. 467 */ 468 bzero(&sed, sizeof (sed)); 469 for (i = 0; i < __KERN_NAUXV_IMPL; i++) { 470 switch (up->u_auxv[i].a_type) { 471 case AT_SUN_LDDATA: 472 sed.sed_lddata = up->u_auxv[i].a_un.a_val; 473 break; 474 case AT_BASE: 475 sed.sed_base = up->u_auxv[i].a_un.a_val; 476 break; 477 case AT_ENTRY: 478 sed.sed_entry = up->u_auxv[i].a_un.a_val; 479 break; 480 case AT_PHDR: 481 sed.sed_phdr = up->u_auxv[i].a_un.a_val; 482 break; 483 case AT_PHENT: 484 sed.sed_phent = up->u_auxv[i].a_un.a_val; 485 break; 486 case AT_PHNUM: 487 sed.sed_phnum = up->u_auxv[i].a_un.a_val; 488 break; 489 default: 490 break; 491 } 492 } 493 /* Make sure the emulator has an entry point */ 494 ASSERT(sed.sed_entry != NULL); 495 ASSERT(sed.sed_phdr != NULL); 496 497 bzero(&env, sizeof (env)); 498 if (args->to_model == DATAMODEL_NATIVE) { 499 err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, &voffset, 500 exec_file, &interp, &env.ex_bssbase, &env.ex_brkbase, 501 &env.ex_brksize, NULL); 502 #if defined(_LP64) 503 } else { 504 Elf32_Ehdr ehdr32; 505 Elf32_Addr uphdr_vaddr32; 506 err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32, 507 &voffset, exec_file, &interp, &env.ex_bssbase, 508 &env.ex_brkbase, &env.ex_brksize, NULL); 509 Ehdr32to64(&ehdr32, &ehdr); 510 if (uphdr_vaddr32 == (Elf32_Addr)-1) 511 uphdr_vaddr = (Addr)-1; 512 else 513 uphdr_vaddr = uphdr_vaddr32; 514 #endif /* _LP64 */ 515 } 516 if (err != 0) 517 return (err); 518 519 /* 520 * Save off the important properties of the executable. The brand 521 * library will ask us for this data later, when it is initializing 522 * and getting ready to transfer control to the brand application. 523 */ 524 if (uphdr_vaddr == (Addr)-1) 525 sedp->sed_phdr = voffset + ehdr.e_phoff; 526 else 527 sedp->sed_phdr = voffset + uphdr_vaddr; 528 sedp->sed_entry = voffset + ehdr.e_entry; 529 sedp->sed_phent = ehdr.e_phentsize; 530 sedp->sed_phnum = ehdr.e_phnum; 531 532 if (interp) { 533 if (ehdr.e_type == ET_DYN) { 534 /* 535 * This is a shared object executable, so we need to 536 * pick a reasonable place to put the heap. Just don't 537 * use the first page. 538 */ 539 env.ex_brkbase = (caddr_t)PAGESIZE; 540 env.ex_bssbase = (caddr_t)PAGESIZE; 541 } 542 543 /* 544 * If the program needs an interpreter (most do), map it in and 545 * store relevant information about it in the aux vector, where 546 * the brand library can find it. 547 */ 548 if ((err = lookupname(linker, UIO_SYSSPACE, 549 FOLLOW, NULLVPP, &nvp)) != 0) { 550 uprintf("%s: not found.", SN1_LINKER); 551 return (err); 552 } 553 if (args->to_model == DATAMODEL_NATIVE) { 554 err = mapexec_brand(nvp, args, &ehdr, 555 &uphdr_vaddr, &voffset, exec_file, &interp, 556 NULL, NULL, NULL, &lddata); 557 #if defined(_LP64) 558 } else { 559 Elf32_Ehdr ehdr32; 560 Elf32_Addr uphdr_vaddr32; 561 err = mapexec32_brand(nvp, args, &ehdr32, 562 &uphdr_vaddr32, &voffset, exec_file, &interp, 563 NULL, NULL, NULL, &lddata); 564 Ehdr32to64(&ehdr32, &ehdr); 565 if (uphdr_vaddr32 == (Elf32_Addr)-1) 566 uphdr_vaddr = (Addr)-1; 567 else 568 uphdr_vaddr = uphdr_vaddr32; 569 #endif /* _LP64 */ 570 } 571 VN_RELE(nvp); 572 if (err != 0) 573 return (err); 574 575 /* 576 * Now that we know the base address of the brand's linker, 577 * place it in the aux vector. 578 */ 579 sedp->sed_base = voffset; 580 sedp->sed_ldentry = voffset + ehdr.e_entry; 581 sedp->sed_lddata = voffset + lddata; 582 } else { 583 /* 584 * This program has no interpreter. The brand library will 585 * jump to the address in the AT_SUN_BRAND_LDENTRY aux vector, 586 * so in this case, put the entry point of the main executable 587 * there. 588 */ 589 if (ehdr.e_type == ET_EXEC) { 590 /* 591 * An executable with no interpreter, this must be a 592 * statically linked executable, which means we loaded 593 * it at the address specified in the elf header, in 594 * which case the e_entry field of the elf header is an 595 * absolute address. 596 */ 597 sedp->sed_ldentry = ehdr.e_entry; 598 sedp->sed_entry = ehdr.e_entry; 599 sedp->sed_lddata = NULL; 600 sedp->sed_base = NULL; 601 } else { 602 /* 603 * A shared object with no interpreter, we use the 604 * calculated address from above. 605 */ 606 sedp->sed_ldentry = sedp->sed_entry; 607 sedp->sed_entry = NULL; 608 sedp->sed_phdr = NULL; 609 sedp->sed_phent = NULL; 610 sedp->sed_phnum = NULL; 611 sedp->sed_lddata = NULL; 612 sedp->sed_base = voffset; 613 614 if (ehdr.e_type == ET_DYN) { 615 /* 616 * Delay setting the brkbase until the first 617 * call to brk(); see elfexec() for details. 618 */ 619 env.ex_bssbase = (caddr_t)0; 620 env.ex_brkbase = (caddr_t)0; 621 env.ex_brksize = 0; 622 } 623 } 624 } 625 626 env.ex_magic = elfmagic; 627 env.ex_vp = vp; 628 setexecenv(&env); 629 630 /* 631 * It's time to manipulate the process aux vectors. First 632 * we need to update the AT_SUN_AUXFLAGS aux vector to set 633 * the AF_SUN_NOPLM flag. 634 */ 635 if (args->to_model == DATAMODEL_NATIVE) { 636 auxv_t auxflags_auxv; 637 638 if (copyin(args->auxp_auxflags, &auxflags_auxv, 639 sizeof (auxflags_auxv)) != 0) 640 return (EFAULT); 641 642 ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS); 643 auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM; 644 if (copyout(&auxflags_auxv, args->auxp_auxflags, 645 sizeof (auxflags_auxv)) != 0) 646 return (EFAULT); 647 #if defined(_LP64) 648 } else { 649 auxv32_t auxflags_auxv32; 650 651 if (copyin(args->auxp_auxflags, &auxflags_auxv32, 652 sizeof (auxflags_auxv32)) != 0) 653 return (EFAULT); 654 655 ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS); 656 auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM; 657 if (copyout(&auxflags_auxv32, args->auxp_auxflags, 658 sizeof (auxflags_auxv32)) != 0) 659 return (EFAULT); 660 #endif /* _LP64 */ 661 } 662 663 /* Second, copy out the brand specific aux vectors. */ 664 if (args->to_model == DATAMODEL_NATIVE) { 665 auxv_t sn1_auxv[] = { 666 { AT_SUN_BRAND_AUX1, 0 }, 667 { AT_SUN_BRAND_AUX2, 0 }, 668 { AT_SUN_BRAND_AUX3, 0 } 669 }; 670 671 ASSERT(sn1_auxv[0].a_type == AT_SUN_BRAND_SN1_LDDATA); 672 sn1_auxv[0].a_un.a_val = sed.sed_lddata; 673 674 if (copyout(&sn1_auxv, args->auxp_brand, 675 sizeof (sn1_auxv)) != 0) 676 return (EFAULT); 677 #if defined(_LP64) 678 } else { 679 auxv32_t sn1_auxv32[] = { 680 { AT_SUN_BRAND_AUX1, 0 }, 681 { AT_SUN_BRAND_AUX2, 0 }, 682 { AT_SUN_BRAND_AUX3, 0 } 683 }; 684 685 ASSERT(sn1_auxv32[0].a_type == AT_SUN_BRAND_SN1_LDDATA); 686 sn1_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata; 687 if (copyout(&sn1_auxv32, args->auxp_brand, 688 sizeof (sn1_auxv32)) != 0) 689 return (EFAULT); 690 #endif /* _LP64 */ 691 } 692 693 /* 694 * Third, the the /proc aux vectors set up by elfexec() point to brand 695 * emulation library and it's linker. Copy these to the /proc brand 696 * specific aux vector, and update the regular /proc aux vectors to 697 * point to the executable (and it's linker). This will enable 698 * debuggers to access the executable via the usual /proc or elf notes 699 * aux vectors. 700 * 701 * The brand emulation library's linker will get it's aux vectors off 702 * the stack, and then update the stack with the executable's aux 703 * vectors before jumping to the executable's linker. 704 * 705 * Debugging the brand emulation library must be done from 706 * the global zone, where the librtld_db module knows how to fetch the 707 * brand specific aux vectors to access the brand emulation libraries 708 * linker. 709 */ 710 for (i = 0; i < __KERN_NAUXV_IMPL; i++) { 711 ulong_t val; 712 713 switch (up->u_auxv[i].a_type) { 714 case AT_SUN_BRAND_SN1_LDDATA: 715 up->u_auxv[i].a_un.a_val = sed.sed_lddata; 716 continue; 717 case AT_BASE: 718 val = sedp->sed_base; 719 break; 720 case AT_ENTRY: 721 val = sedp->sed_entry; 722 break; 723 case AT_PHDR: 724 val = sedp->sed_phdr; 725 break; 726 case AT_PHENT: 727 val = sedp->sed_phent; 728 break; 729 case AT_PHNUM: 730 val = sedp->sed_phnum; 731 break; 732 case AT_SUN_LDDATA: 733 val = sedp->sed_lddata; 734 break; 735 default: 736 continue; 737 } 738 739 up->u_auxv[i].a_un.a_val = val; 740 if (val == NULL) { 741 /* Hide the entry for static binaries */ 742 up->u_auxv[i].a_type = AT_IGNORE; 743 } 744 } 745 746 /* 747 * The last thing we do here is clear spd->spd_handler. This is 748 * important because if we're already a branded process and if this 749 * exec succeeds, there is a window between when the exec() first 750 * returns to the userland of the new process and when our brand 751 * library get's initialized, during which we don't want system 752 * calls to be re-directed to our brand library since it hasn't 753 * been initialized yet. 754 */ 755 spd->spd_handler = NULL; 756 757 return (0); 758 } 759 760 761 int 762 _init(void) 763 { 764 int err; 765 766 /* 767 * Set up the table indicating which system calls we want to 768 * interpose on. We should probably build this automatically from 769 * a list of system calls that is shared with the user-space 770 * library. 771 */ 772 sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP); 773 sn1_emulation_table[SYS_read] = 1; /* 3 */ 774 sn1_emulation_table[SYS_write] = 1; /* 4 */ 775 sn1_emulation_table[SYS_wait] = 1; /* 7 */ 776 sn1_emulation_table[SYS_time] = 1; /* 13 */ 777 sn1_emulation_table[SYS_getpid] = 1; /* 20 */ 778 sn1_emulation_table[SYS_mount] = 1; /* 21 */ 779 sn1_emulation_table[SYS_getuid] = 1; /* 24 */ 780 sn1_emulation_table[SYS_times] = 1; /* 43 */ 781 sn1_emulation_table[SYS_getgid] = 1; /* 47 */ 782 sn1_emulation_table[SYS_utssys] = 1; /* 57 */ 783 sn1_emulation_table[SYS_readlink] = 1; /* 90 */ 784 sn1_emulation_table[SYS_uname] = 1; /* 135 */ 785 786 err = mod_install(&modlinkage); 787 if (err) { 788 cmn_err(CE_WARN, "Couldn't install brand module"); 789 kmem_free(sn1_emulation_table, NSYSCALL); 790 } 791 792 return (err); 793 } 794 795 int 796 _info(struct modinfo *modinfop) 797 { 798 return (mod_info(&modlinkage, modinfop)); 799 } 800 801 int 802 _fini(void) 803 { 804 int err; 805 806 /* 807 * If there are any zones using this brand, we can't allow it to be 808 * unloaded. 809 */ 810 if (brand_zone_count(&sn1_brand)) 811 return (EBUSY); 812 813 kmem_free(sn1_emulation_table, NSYSCALL); 814 sn1_emulation_table = NULL; 815 816 err = mod_remove(&modlinkage); 817 if (err) 818 cmn_err(CE_WARN, "Couldn't unload sn1 brand module"); 819 820 return (err); 821 } 822