Print this page
sysinfo emulation
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/brand/solaris10/s10_brand.c
+++ new/usr/src/uts/common/brand/solaris10/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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 #include <sys/errno.h>
27 27 #include <sys/exec.h>
28 28 #include <sys/kmem.h>
29 29 #include <sys/modctl.h>
30 30 #include <sys/model.h>
31 31 #include <sys/proc.h>
32 32 #include <sys/syscall.h>
33 33 #include <sys/systm.h>
34 34 #include <sys/thread.h>
35 35 #include <sys/cmn_err.h>
36 36 #include <sys/archsystm.h>
37 37 #include <sys/pathname.h>
38 38 #include <sys/sunddi.h>
39 39
40 40 #include <sys/machbrand.h>
41 41 #include <sys/brand.h>
42 42 #include "s10_brand.h"
43 43
44 44 char *s10_emulation_table = NULL;
45 45
46 46 void s10_init_brand_data(zone_t *);
47 47 void s10_free_brand_data(zone_t *);
48 48 void s10_setbrand(proc_t *);
49 49 int s10_getattr(zone_t *, int, void *, size_t *);
50 50 int s10_setattr(zone_t *, int, void *, size_t);
51 51 int s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
52 52 uintptr_t, uintptr_t, uintptr_t);
53 53 void s10_copy_procdata(proc_t *, proc_t *);
54 54 void s10_proc_exit(struct proc *, klwp_t *);
55 55 void s10_exec();
56 56 int s10_initlwp(klwp_t *);
57 57 void s10_forklwp(klwp_t *, klwp_t *);
58 58 void s10_freelwp(klwp_t *);
59 59 void s10_lwpexit(klwp_t *);
60 60 int s10_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
61 61 long *, int, caddr_t, cred_t *, int);
62 62
63 63 /* s10 brand */
64 64 struct brand_ops s10_brops = {
65 65 s10_init_brand_data,
66 66 s10_free_brand_data,
67 67 s10_brandsys,
68 68 s10_setbrand,
69 69 s10_getattr,
70 70 s10_setattr,
71 71 s10_copy_procdata,
72 72 s10_proc_exit,
73 73 s10_exec,
74 74 lwp_setrval,
75 75 s10_initlwp,
76 76 s10_forklwp,
77 77 s10_freelwp,
78 78 s10_lwpexit,
79 79 s10_elfexec
80 80 };
81 81
82 82 #ifdef sparc
83 83
84 84 struct brand_mach_ops s10_mops = {
85 85 s10_brand_syscall_callback,
86 86 s10_brand_syscall32_callback
87 87 };
88 88
89 89 #else /* sparc */
90 90
91 91 #ifdef __amd64
92 92
93 93 struct brand_mach_ops s10_mops = {
94 94 s10_brand_sysenter_callback,
95 95 NULL,
96 96 s10_brand_int91_callback,
97 97 s10_brand_syscall_callback,
98 98 s10_brand_syscall32_callback,
99 99 NULL
100 100 };
101 101
102 102 #else /* ! __amd64 */
103 103
104 104 struct brand_mach_ops s10_mops = {
105 105 s10_brand_sysenter_callback,
106 106 NULL,
107 107 NULL,
108 108 s10_brand_syscall_callback,
109 109 NULL,
110 110 NULL
111 111 };
112 112 #endif /* __amd64 */
113 113
114 114 #endif /* _sparc */
115 115
116 116 struct brand s10_brand = {
117 117 BRAND_VER_1,
118 118 "solaris10",
119 119 &s10_brops,
120 120 &s10_mops
121 121 };
122 122
123 123 static struct modlbrand modlbrand = {
124 124 &mod_brandops, /* type of module */
125 125 "Solaris 10 Brand", /* description of module */
126 126 &s10_brand /* driver ops */
127 127 };
128 128
129 129 static struct modlinkage modlinkage = {
130 130 MODREV_1, (void *)&modlbrand, NULL
131 131 };
132 132
133 133 void
134 134 s10_setbrand(proc_t *p)
135 135 {
136 136 ASSERT(p->p_brand == &s10_brand);
137 137 ASSERT(p->p_brand_data == NULL);
138 138
139 139 /*
140 140 * We should only be called from exec(), when we know the process
141 141 * is single-threaded.
142 142 */
143 143 ASSERT(p->p_tlist == p->p_tlist->t_forw);
144 144
145 145 p->p_brand_data = kmem_zalloc(sizeof (s10_proc_data_t), KM_SLEEP);
146 146 (void) s10_initlwp(p->p_tlist->t_lwp);
147 147 }
148 148
149 149 int
150 150 s10_get_zone_emul_version(zone_t *zone)
151 151 {
152 152 return (((s10_zone_data_t *)
153 153 zone->zone_brand_data)->s10zd_emul_version);
154 154 }
155 155
156 156 int
157 157 s10_get_emul_version()
158 158 {
159 159 return (s10_get_zone_emul_version(curzone));
160 160 }
161 161
162 162 void
163 163 s10_set_emul_version(zone_t *zone, int vers)
164 164 {
165 165 s10_zone_data_t *s10zd = (s10_zone_data_t *)zone->zone_brand_data;
166 166 s10zd->s10zd_emul_version = vers;
167 167 }
168 168
169 169 /*ARGSUSED*/
170 170 int
171 171 s10_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
172 172 {
173 173 int num;
174 174
175 175 ASSERT(zone->zone_brand == &s10_brand);
176 176 if (attr == S10_EMUL_VERSION_NUM) {
177 177 if (*bufsize < sizeof (int))
178 178 return (ERANGE);
179 179 num = s10_get_emul_version();
180 180 if (copyout(&num, buf, sizeof (int)) != 0)
181 181 return (EFAULT);
182 182 *bufsize = sizeof (int);
183 183 return (0);
184 184 }
185 185
186 186 return (EINVAL);
187 187 }
188 188
189 189 int
190 190 s10_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
191 191 {
192 192 int num;
193 193
194 194 ASSERT(zone->zone_brand == &s10_brand);
195 195 if (attr == S10_EMUL_VERSION_NUM) {
196 196 if (bufsize > sizeof (int))
197 197 return (ERANGE);
198 198 if (copyin(buf, &num, sizeof (num)) != 0)
199 199 return (EFAULT);
200 200 s10_set_emul_version(zone, num);
201 201 return (0);
202 202 }
203 203
204 204 return (EINVAL);
205 205 }
206 206
207 207 int
208 208 s10_native()
209 209 {
210 210 struct user *up = PTOU(curproc);
211 211 char *args_new, *comm_new, *p;
212 212 int len;
213 213
214 214 len = sizeof ("/.SUNWnative/lib/ld.so.1 ") - 1;
215 215
216 216 if (strcmp(up->u_comm, "ld.so.1") != 0)
217 217 return (0);
218 218 if (strncmp(up->u_psargs, "/.SUNWnative/lib/ld.so.1 /", len + 1) != 0)
219 219 return (0);
220 220
221 221 args_new = strdup(&up->u_psargs[len]);
222 222 if ((p = strchr(args_new, ' ')) != NULL)
223 223 *p = '\0';
224 224 if ((comm_new = strrchr(args_new, '/')) != NULL)
225 225 comm_new = strdup(comm_new + 1);
226 226 else
227 227 comm_new = strdup(args_new);
228 228 if (p != NULL)
229 229 *p = ' ';
230 230
231 231 if ((strlen(args_new) != 0) && (strlen(comm_new) != 0)) {
232 232 mutex_enter(&curproc->p_lock);
233 233 (void) strlcpy(up->u_comm, comm_new, MAXCOMLEN+1);
234 234 (void) strlcpy(up->u_psargs, args_new, PSARGSZ);
235 235 mutex_exit(&curproc->p_lock);
236 236 }
237 237
238 238 strfree(args_new);
239 239 strfree(comm_new);
240 240 return (0);
241 241 }
242 242
243 243 /*
244 244 * Get the address of the user-space system call handler from the user
245 245 * process and attach it to the proc structure.
246 246 */
247 247 /*ARGSUSED*/
248 248 int
249 249 s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
250 250 uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
251 251 {
252 252 s10_proc_data_t *spd;
253 253 s10_brand_reg_t reg;
254 254 proc_t *p = curproc;
255 255 int err;
256 256
257 257 *rval = 0;
258 258
259 259 /*
260 260 * B_EXEC_BRAND is redundant
261 261 * since the kernel assumes a native process doing an exec
262 262 * in a branded zone is going to run a branded processes.
263 263 * hence we don't support this operation.
264 264 */
265 265 if (cmd == B_EXEC_BRAND)
266 266 return (ENOSYS);
267 267
268 268 if (cmd == B_S10_NATIVE)
269 269 return (s10_native());
270 270
271 271 /* For all other operations this must be a branded process. */
272 272 if (p->p_brand == &native_brand)
273 273 return (ENOSYS);
274 274
275 275 ASSERT(p->p_brand == &s10_brand);
276 276 ASSERT(p->p_brand_data != NULL);
277 277
278 278 spd = (s10_proc_data_t *)p->p_brand_data;
279 279
280 280 switch (cmd) {
281 281 case B_EXEC_NATIVE:
282 282 err = exec_common(
283 283 (char *)arg1, (const char **)arg2, (const char **)arg3,
284 284 EBA_NATIVE);
285 285 return (err);
286 286
287 287 case B_REGISTER:
288 288 if (p->p_model == DATAMODEL_NATIVE) {
289 289 if (copyin((void *)arg1, ®, sizeof (reg)) != 0)
290 290 return (EFAULT);
291 291 #if defined(_LP64)
292 292 } else {
293 293 s10_brand_reg32_t reg32;
294 294
295 295 if (copyin((void *)arg1, ®32, sizeof (reg32)) != 0)
296 296 return (EFAULT);
297 297 reg.sbr_version = reg32.sbr_version;
298 298 reg.sbr_handler = (caddr_t)(uintptr_t)reg32.sbr_handler;
299 299 #endif /* _LP64 */
300 300 }
301 301
302 302 if (reg.sbr_version != S10_VERSION)
303 303 return (ENOTSUP);
304 304 spd->spd_handler = reg.sbr_handler;
305 305 return (0);
306 306
307 307 case B_ELFDATA:
308 308 if (p->p_model == DATAMODEL_NATIVE) {
309 309 if (copyout(&spd->spd_elf_data, (void *)arg1,
310 310 sizeof (s10_elf_data_t)) != 0)
311 311 return (EFAULT);
312 312 #if defined(_LP64)
313 313 } else {
314 314 s10_elf_data32_t sed32;
315 315
316 316 sed32.sed_phdr = spd->spd_elf_data.sed_phdr;
317 317 sed32.sed_phent = spd->spd_elf_data.sed_phent;
318 318 sed32.sed_phnum = spd->spd_elf_data.sed_phnum;
319 319 sed32.sed_entry = spd->spd_elf_data.sed_entry;
320 320 sed32.sed_base = spd->spd_elf_data.sed_base;
321 321 sed32.sed_ldentry = spd->spd_elf_data.sed_ldentry;
322 322 sed32.sed_lddata = spd->spd_elf_data.sed_lddata;
323 323 if (copyout(&sed32, (void *)arg1, sizeof (sed32)) != 0)
324 324 return (EFAULT);
325 325 #endif /* _LP64 */
326 326 }
327 327 return (0);
328 328
329 329 case B_S10_PIDINFO:
330 330 /*
331 331 * The s10 brand needs to be able to get the pid of the
332 332 * current process and the pid of the zone's init, and it
333 333 * needs to do this on every process startup. Early in
334 334 * brand startup, we can't call getpid() because calls to
335 335 * getpid() represent a magical signal to some old-skool
336 336 * debuggers. By merging all of this into one call, we
337 337 * make this quite a bit cheaper and easier to handle in
338 338 * the brand module.
339 339 */
340 340 if (copyout(&p->p_pid, (void *)arg1, sizeof (pid_t)) != 0)
341 341 return (EFAULT);
342 342 if (copyout(&p->p_zone->zone_proc_initpid, (void *)arg2,
343 343 sizeof (pid_t)) != 0)
344 344 return (EFAULT);
345 345 return (0);
346 346
347 347 case B_S10_TRUSS_POINT:
348 348 /*
349 349 * This subcommand exists so that we can see truss output
350 350 * from interposed system calls that return without first
351 351 * calling any other system call, meaning they would be
352 352 * invisible to truss(1).
353 353 *
354 354 * If the second argument is set non-zero, set errno to that
355 355 * value as well.
356 356 *
357 357 * Arguments are:
358 358 *
359 359 * arg1: syscall number
360 360 * arg2: errno
361 361 */
362 362 return ((arg2 == 0) ? 0 : set_errno((uint_t)arg2));
363 363 }
364 364
365 365 return (EINVAL);
366 366 }
367 367
368 368 /*
369 369 * Copy the per-process brand data from a parent proc to a child.
370 370 */
371 371 void
372 372 s10_copy_procdata(proc_t *child, proc_t *parent)
373 373 {
374 374 s10_proc_data_t *spd;
375 375
376 376 ASSERT(parent->p_brand == &s10_brand);
377 377 ASSERT(child->p_brand == &s10_brand);
378 378 ASSERT(parent->p_brand_data != NULL);
379 379 ASSERT(child->p_brand_data == NULL);
380 380
381 381 /* Just duplicate all the proc data of the parent for the child */
382 382 spd = kmem_alloc(sizeof (s10_proc_data_t), KM_SLEEP);
383 383 bcopy(parent->p_brand_data, spd, sizeof (s10_proc_data_t));
384 384 child->p_brand_data = spd;
385 385 }
386 386
387 387 /*ARGSUSED*/
388 388 void
389 389 s10_proc_exit(struct proc *p, klwp_t *l)
390 390 {
391 391 ASSERT(p->p_brand == &s10_brand);
392 392 ASSERT(p->p_brand_data != NULL);
393 393
394 394 /*
395 395 * We should only be called from proc_exit(), when we know that
396 396 * process is single-threaded.
397 397 */
398 398 ASSERT(p->p_tlist == p->p_tlist->t_forw);
399 399
400 400 /* upon exit, free our lwp brand data */
401 401 (void) s10_freelwp(ttolwp(curthread));
402 402
403 403 /* upon exit, free our proc brand data */
404 404 kmem_free(p->p_brand_data, sizeof (s10_proc_data_t));
405 405 p->p_brand_data = NULL;
406 406 }
407 407
408 408 void
409 409 s10_exec()
410 410 {
411 411 s10_proc_data_t *spd = curproc->p_brand_data;
412 412
413 413 ASSERT(curproc->p_brand == &s10_brand);
414 414 ASSERT(curproc->p_brand_data != NULL);
415 415 ASSERT(ttolwp(curthread)->lwp_brand != NULL);
416 416
417 417 /*
418 418 * We should only be called from exec(), when we know the process
419 419 * is single-threaded.
420 420 */
421 421 ASSERT(curproc->p_tlist == curproc->p_tlist->t_forw);
422 422
423 423 /* Upon exec, reset our lwp brand data. */
424 424 (void) s10_freelwp(ttolwp(curthread));
425 425 (void) s10_initlwp(ttolwp(curthread));
426 426
427 427 /*
428 428 * Upon exec, reset all the proc brand data, except for the elf
429 429 * data associated with the executable we are exec'ing.
430 430 */
431 431 spd->spd_handler = NULL;
432 432 }
433 433
434 434 /*ARGSUSED*/
435 435 int
436 436 s10_initlwp(klwp_t *l)
437 437 {
438 438 ASSERT(l->lwp_procp->p_brand == &s10_brand);
439 439 ASSERT(l->lwp_procp->p_brand_data != NULL);
440 440 ASSERT(l->lwp_brand == NULL);
441 441 l->lwp_brand = (void *)-1;
442 442 return (0);
443 443 }
444 444
445 445 /*ARGSUSED*/
446 446 void
447 447 s10_forklwp(klwp_t *p, klwp_t *c)
448 448 {
449 449 ASSERT(p->lwp_procp->p_brand == &s10_brand);
450 450 ASSERT(c->lwp_procp->p_brand == &s10_brand);
451 451
452 452 ASSERT(p->lwp_procp->p_brand_data != NULL);
453 453 ASSERT(c->lwp_procp->p_brand_data != NULL);
454 454
455 455 /* Both LWPs have already had been initialized via s10_initlwp() */
456 456 ASSERT(p->lwp_brand != NULL);
457 457 ASSERT(c->lwp_brand != NULL);
458 458 }
459 459
460 460 /*ARGSUSED*/
461 461 void
462 462 s10_freelwp(klwp_t *l)
463 463 {
464 464 ASSERT(l->lwp_procp->p_brand == &s10_brand);
465 465 ASSERT(l->lwp_procp->p_brand_data != NULL);
466 466 ASSERT(l->lwp_brand != NULL);
467 467 l->lwp_brand = NULL;
468 468 }
469 469
470 470 /*ARGSUSED*/
471 471 void
472 472 s10_lwpexit(klwp_t *l)
473 473 {
474 474 proc_t *p = l->lwp_procp;
475 475
476 476 ASSERT(l->lwp_procp->p_brand == &s10_brand);
477 477 ASSERT(l->lwp_procp->p_brand_data != NULL);
478 478 ASSERT(l->lwp_brand != NULL);
479 479
480 480 /*
481 481 * We should never be called for the last thread in a process.
482 482 * (That case is handled by s10_proc_exit().) There for this lwp
483 483 * must be exiting from a multi-threaded process.
484 484 */
485 485 ASSERT(p->p_tlist != p->p_tlist->t_forw);
486 486
487 487 l->lwp_brand = NULL;
488 488 }
489 489
490 490 void
491 491 s10_free_brand_data(zone_t *zone)
492 492 {
493 493 kmem_free(zone->zone_brand_data, sizeof (s10_zone_data_t));
494 494 }
495 495
496 496 void
497 497 s10_init_brand_data(zone_t *zone)
498 498 {
499 499 s10_zone_data_t *data;
500 500 ASSERT(zone->zone_brand == &s10_brand);
501 501 ASSERT(zone->zone_brand_data == NULL);
502 502 data = (s10_zone_data_t *)kmem_zalloc(sizeof (s10_zone_data_t),
503 503 KM_SLEEP);
504 504 /*
505 505 * Initialize the default s10zd_emul_version to S10_EMUL_UNDEF.
506 506 * This can be changed by a call to setattr() during zone boot.
507 507 */
508 508 data->s10zd_emul_version = S10_EMUL_UNDEF;
509 509 zone->zone_brand_data = data;
510 510 }
511 511
512 512 #if defined(_LP64)
513 513 static void
514 514 Ehdr32to64(Elf32_Ehdr *src, Ehdr *dst)
515 515 {
516 516 bcopy(src->e_ident, dst->e_ident, sizeof (src->e_ident));
517 517 dst->e_type = src->e_type;
518 518 dst->e_machine = src->e_machine;
519 519 dst->e_version = src->e_version;
520 520 dst->e_entry = src->e_entry;
521 521 dst->e_phoff = src->e_phoff;
522 522 dst->e_shoff = src->e_shoff;
523 523 dst->e_flags = src->e_flags;
524 524 dst->e_ehsize = src->e_ehsize;
525 525 dst->e_phentsize = src->e_phentsize;
526 526 dst->e_phnum = src->e_phnum;
527 527 dst->e_shentsize = src->e_shentsize;
528 528 dst->e_shnum = src->e_shnum;
529 529 dst->e_shstrndx = src->e_shstrndx;
530 530 }
531 531 #endif /* _LP64 */
532 532
533 533 int
534 534 s10_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
535 535 int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
536 536 int brand_action)
537 537 {
538 538 vnode_t *nvp;
539 539 Ehdr ehdr;
540 540 Addr uphdr_vaddr;
541 541 intptr_t voffset;
542 542 int interp;
543 543 int i, err;
544 544 struct execenv env;
545 545 struct user *up = PTOU(curproc);
546 546 s10_proc_data_t *spd;
547 547 s10_elf_data_t sed, *sedp;
548 548 char *linker;
549 549 uintptr_t lddata; /* lddata of executable's linker */
550 550
551 551 ASSERT(curproc->p_brand == &s10_brand);
552 552 ASSERT(curproc->p_brand_data != NULL);
553 553
554 554 spd = (s10_proc_data_t *)curproc->p_brand_data;
555 555 sedp = &spd->spd_elf_data;
556 556
557 557 args->brandname = S10_BRANDNAME;
558 558
559 559 /*
560 560 * We will exec the brand library and then map in the target
561 561 * application and (optionally) the brand's default linker.
562 562 */
563 563 if (args->to_model == DATAMODEL_NATIVE) {
564 564 args->emulator = S10_LIB;
565 565 linker = S10_LINKER;
566 566 #if defined(_LP64)
567 567 } else {
568 568 args->emulator = S10_LIB32;
569 569 linker = S10_LINKER32;
570 570 #endif /* _LP64 */
571 571 }
572 572
573 573 if ((err = lookupname(args->emulator, UIO_SYSSPACE, FOLLOW, NULLVPP,
574 574 &nvp)) != 0) {
575 575 uprintf("%s: not found.", args->emulator);
576 576 return (err);
577 577 }
578 578
579 579 if (args->to_model == DATAMODEL_NATIVE) {
580 580 err = elfexec(nvp, uap, args, idatap, level + 1, execsz,
581 581 setid, exec_file, cred, brand_action);
582 582 #if defined(_LP64)
583 583 } else {
584 584 err = elf32exec(nvp, uap, args, idatap, level + 1, execsz,
585 585 setid, exec_file, cred, brand_action);
586 586 #endif /* _LP64 */
587 587 }
588 588 VN_RELE(nvp);
589 589 if (err != 0)
590 590 return (err);
591 591
592 592 /*
593 593 * The u_auxv vectors are set up by elfexec to point to the brand
594 594 * emulation library and linker. Save these so they can be copied to
595 595 * the specific brand aux vectors.
596 596 */
597 597 bzero(&sed, sizeof (sed));
598 598 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
599 599 switch (up->u_auxv[i].a_type) {
600 600 case AT_SUN_LDDATA:
601 601 sed.sed_lddata = up->u_auxv[i].a_un.a_val;
602 602 break;
603 603 case AT_BASE:
604 604 sed.sed_base = up->u_auxv[i].a_un.a_val;
605 605 break;
606 606 case AT_ENTRY:
607 607 sed.sed_entry = up->u_auxv[i].a_un.a_val;
608 608 break;
609 609 case AT_PHDR:
610 610 sed.sed_phdr = up->u_auxv[i].a_un.a_val;
611 611 break;
612 612 case AT_PHENT:
613 613 sed.sed_phent = up->u_auxv[i].a_un.a_val;
614 614 break;
615 615 case AT_PHNUM:
616 616 sed.sed_phnum = up->u_auxv[i].a_un.a_val;
617 617 break;
618 618 default:
619 619 break;
620 620 }
621 621 }
622 622 /* Make sure the emulator has an entry point */
623 623 ASSERT(sed.sed_entry != NULL);
624 624 ASSERT(sed.sed_phdr != NULL);
625 625
626 626 bzero(&env, sizeof (env));
627 627 if (args->to_model == DATAMODEL_NATIVE) {
628 628 err = mapexec_brand(vp, args, &ehdr, &uphdr_vaddr, &voffset,
629 629 exec_file, &interp, &env.ex_bssbase, &env.ex_brkbase,
630 630 &env.ex_brksize, NULL);
631 631 #if defined(_LP64)
632 632 } else {
633 633 Elf32_Ehdr ehdr32;
634 634 Elf32_Addr uphdr_vaddr32;
635 635 err = mapexec32_brand(vp, args, &ehdr32, &uphdr_vaddr32,
636 636 &voffset, exec_file, &interp, &env.ex_bssbase,
637 637 &env.ex_brkbase, &env.ex_brksize, NULL);
638 638 Ehdr32to64(&ehdr32, &ehdr);
639 639 if (uphdr_vaddr32 == (Elf32_Addr)-1)
640 640 uphdr_vaddr = (Addr)-1;
641 641 else
642 642 uphdr_vaddr = uphdr_vaddr32;
643 643 #endif /* _LP64 */
644 644 }
645 645 if (err != 0)
646 646 return (err);
647 647
648 648 /*
649 649 * Save off the important properties of the executable. The brand
650 650 * library will ask us for this data later, when it is initializing
651 651 * and getting ready to transfer control to the brand application.
652 652 */
653 653 if (uphdr_vaddr == (Addr)-1)
654 654 sedp->sed_phdr = voffset + ehdr.e_phoff;
655 655 else
656 656 sedp->sed_phdr = voffset + uphdr_vaddr;
657 657 sedp->sed_entry = voffset + ehdr.e_entry;
658 658 sedp->sed_phent = ehdr.e_phentsize;
659 659 sedp->sed_phnum = ehdr.e_phnum;
660 660
661 661 if (interp) {
662 662 if (ehdr.e_type == ET_DYN) {
663 663 /*
664 664 * This is a shared object executable, so we need to
665 665 * pick a reasonable place to put the heap. Just don't
666 666 * use the first page.
667 667 */
668 668 env.ex_brkbase = (caddr_t)PAGESIZE;
669 669 env.ex_bssbase = (caddr_t)PAGESIZE;
670 670 }
671 671
672 672 /*
673 673 * If the program needs an interpreter (most do), map it in and
674 674 * store relevant information about it in the aux vector, where
675 675 * the brand library can find it.
676 676 */
677 677 if ((err = lookupname(linker, UIO_SYSSPACE,
678 678 FOLLOW, NULLVPP, &nvp)) != 0) {
679 679 uprintf("%s: not found.", S10_LINKER);
680 680 return (err);
681 681 }
682 682 if (args->to_model == DATAMODEL_NATIVE) {
683 683 err = mapexec_brand(nvp, args, &ehdr,
684 684 &uphdr_vaddr, &voffset, exec_file, &interp,
685 685 NULL, NULL, NULL, &lddata);
686 686 #if defined(_LP64)
687 687 } else {
688 688 Elf32_Ehdr ehdr32;
689 689 Elf32_Addr uphdr_vaddr32;
690 690 err = mapexec32_brand(nvp, args, &ehdr32,
691 691 &uphdr_vaddr32, &voffset, exec_file, &interp,
692 692 NULL, NULL, NULL, &lddata);
693 693 Ehdr32to64(&ehdr32, &ehdr);
694 694 if (uphdr_vaddr32 == (Elf32_Addr)-1)
695 695 uphdr_vaddr = (Addr)-1;
696 696 else
697 697 uphdr_vaddr = uphdr_vaddr32;
698 698 #endif /* _LP64 */
699 699 }
700 700 VN_RELE(nvp);
701 701 if (err != 0)
702 702 return (err);
703 703
704 704 /*
705 705 * Now that we know the base address of the brand's linker,
706 706 * place it in the aux vector.
707 707 */
708 708 sedp->sed_base = voffset;
709 709 sedp->sed_ldentry = voffset + ehdr.e_entry;
710 710 sedp->sed_lddata = voffset + lddata;
711 711 } else {
712 712 /*
713 713 * This program has no interpreter. The brand library will
714 714 * jump to the address in the AT_SUN_BRAND_LDENTRY aux vector,
715 715 * so in this case, put the entry point of the main executable
716 716 * there.
717 717 */
718 718 if (ehdr.e_type == ET_EXEC) {
719 719 /*
720 720 * An executable with no interpreter, this must be a
721 721 * statically linked executable, which means we loaded
722 722 * it at the address specified in the elf header, in
723 723 * which case the e_entry field of the elf header is an
724 724 * absolute address.
725 725 */
726 726 sedp->sed_ldentry = ehdr.e_entry;
727 727 sedp->sed_entry = ehdr.e_entry;
728 728 sedp->sed_lddata = NULL;
729 729 sedp->sed_base = NULL;
730 730 } else {
731 731 /*
732 732 * A shared object with no interpreter, we use the
733 733 * calculated address from above.
734 734 */
735 735 sedp->sed_ldentry = sedp->sed_entry;
736 736 sedp->sed_lddata = NULL;
737 737 sedp->sed_base = NULL;
738 738 }
739 739 }
740 740
741 741 if (uphdr_vaddr != (Addr)-1) {
742 742 if (ehdr.e_type == ET_DYN) {
743 743 /*
744 744 * Delay setting the brkbase until the first call to
745 745 * brk(); see elfexec() for details.
746 746 */
747 747 env.ex_bssbase = (caddr_t)0;
748 748 env.ex_brkbase = (caddr_t)0;
749 749 env.ex_brksize = 0;
750 750 }
751 751 }
752 752
753 753 env.ex_magic = elfmagic;
754 754 env.ex_vp = vp;
755 755 setexecenv(&env);
756 756
757 757 /*
758 758 * It's time to manipulate the process aux vectors. First
759 759 * we need to update the AT_SUN_AUXFLAGS aux vector to set
760 760 * the AF_SUN_NOPLM flag.
761 761 */
762 762 if (args->to_model == DATAMODEL_NATIVE) {
763 763 auxv_t auxflags_auxv;
764 764
765 765 if (copyin(args->auxp_auxflags, &auxflags_auxv,
766 766 sizeof (auxflags_auxv)) != 0)
767 767 return (EFAULT);
768 768
769 769 ASSERT(auxflags_auxv.a_type == AT_SUN_AUXFLAGS);
770 770 auxflags_auxv.a_un.a_val |= AF_SUN_NOPLM;
771 771 if (copyout(&auxflags_auxv, args->auxp_auxflags,
772 772 sizeof (auxflags_auxv)) != 0)
773 773 return (EFAULT);
774 774 #if defined(_LP64)
775 775 } else {
776 776 auxv32_t auxflags_auxv32;
777 777
778 778 if (copyin(args->auxp_auxflags, &auxflags_auxv32,
779 779 sizeof (auxflags_auxv32)) != 0)
780 780 return (EFAULT);
781 781
782 782 ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
783 783 auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
784 784 if (copyout(&auxflags_auxv32, args->auxp_auxflags,
785 785 sizeof (auxflags_auxv32)) != 0)
786 786 return (EFAULT);
787 787 #endif /* _LP64 */
788 788 }
789 789
790 790 /* Second, copy out the brand specific aux vectors. */
791 791 if (args->to_model == DATAMODEL_NATIVE) {
792 792 auxv_t s10_auxv[] = {
793 793 { AT_SUN_BRAND_AUX1, 0 },
794 794 { AT_SUN_BRAND_AUX2, 0 },
795 795 { AT_SUN_BRAND_AUX3, 0 }
796 796 };
797 797
798 798 ASSERT(s10_auxv[0].a_type == AT_SUN_BRAND_S10_LDDATA);
799 799 s10_auxv[0].a_un.a_val = sed.sed_lddata;
800 800
801 801 if (copyout(&s10_auxv, args->auxp_brand,
802 802 sizeof (s10_auxv)) != 0)
803 803 return (EFAULT);
804 804 #if defined(_LP64)
805 805 } else {
806 806 auxv32_t s10_auxv32[] = {
807 807 { AT_SUN_BRAND_AUX1, 0 },
808 808 { AT_SUN_BRAND_AUX2, 0 },
809 809 { AT_SUN_BRAND_AUX3, 0 }
810 810 };
811 811
812 812 ASSERT(s10_auxv32[0].a_type == AT_SUN_BRAND_S10_LDDATA);
813 813 s10_auxv32[0].a_un.a_val = (uint32_t)sed.sed_lddata;
814 814 if (copyout(&s10_auxv32, args->auxp_brand,
815 815 sizeof (s10_auxv32)) != 0)
816 816 return (EFAULT);
817 817 #endif /* _LP64 */
818 818 }
819 819
820 820 /*
821 821 * Third, the the /proc aux vectors set up by elfexec() point to brand
822 822 * emulation library and it's linker. Copy these to the /proc brand
823 823 * specific aux vector, and update the regular /proc aux vectors to
824 824 * point to the executable (and it's linker). This will enable
825 825 * debuggers to access the executable via the usual /proc or elf notes
826 826 * aux vectors.
827 827 *
828 828 * The brand emulation library's linker will get it's aux vectors off
829 829 * the stack, and then update the stack with the executable's aux
830 830 * vectors before jumping to the executable's linker.
831 831 *
832 832 * Debugging the brand emulation library must be done from
833 833 * the global zone, where the librtld_db module knows how to fetch the
834 834 * brand specific aux vectors to access the brand emulation libraries
835 835 * linker.
836 836 */
837 837 for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
838 838 switch (up->u_auxv[i].a_type) {
839 839 case AT_SUN_BRAND_S10_LDDATA:
840 840 up->u_auxv[i].a_un.a_val = sed.sed_lddata;
841 841 break;
842 842 case AT_BASE:
843 843 if (sedp->sed_base == NULL) {
844 844 /* Hide base for static binaries */
845 845 up->u_auxv[i].a_type = AT_IGNORE;
846 846 up->u_auxv[i].a_un.a_val = NULL;
847 847 } else {
848 848 up->u_auxv[i].a_un.a_val = sedp->sed_base;
849 849 }
850 850 break;
851 851 case AT_ENTRY:
852 852 up->u_auxv[i].a_un.a_val = sedp->sed_entry;
853 853 break;
854 854 case AT_PHDR:
855 855 up->u_auxv[i].a_un.a_val = sedp->sed_phdr;
856 856 break;
857 857 case AT_PHENT:
858 858 up->u_auxv[i].a_un.a_val = sedp->sed_phent;
859 859 break;
860 860 case AT_PHNUM:
861 861 up->u_auxv[i].a_un.a_val = sedp->sed_phnum;
862 862 break;
863 863 case AT_SUN_LDDATA:
864 864 if (sedp->sed_lddata == NULL) {
865 865 /* Hide lddata for static binaries */
866 866 up->u_auxv[i].a_type = AT_IGNORE;
867 867 up->u_auxv[i].a_un.a_val = NULL;
868 868 } else {
869 869 up->u_auxv[i].a_un.a_val = sedp->sed_lddata;
870 870 }
871 871 break;
872 872 default:
873 873 break;
874 874 }
875 875 }
876 876
877 877 /*
878 878 * The last thing we do here is clear spd->spd_handler. This is
879 879 * important because if we're already a branded process and if this
880 880 * exec succeeds, there is a window between when the exec() first
881 881 * returns to the userland of the new process and when our brand
882 882 * library get's initialized, during which we don't want system
883 883 * calls to be re-directed to our brand library since it hasn't
884 884 * been initialized yet.
885 885 */
886 886 spd->spd_handler = NULL;
887 887
888 888 return (0);
889 889 }
890 890
891 891
892 892 int
893 893 _init(void)
894 894 {
895 895 int err;
896 896
897 897 /*
898 898 * Set up the table indicating which system calls we want to
899 899 * interpose on. We should probably build this automatically from
900 900 * a list of system calls that is shared with the user-space
|
↓ open down ↓ |
900 lines elided |
↑ open up ↑ |
901 901 * library.
902 902 */
903 903 s10_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
904 904 s10_emulation_table[SYS_exec] = 1; /* 11 */
905 905 s10_emulation_table[SYS_ioctl] = 1; /* 54 */
906 906 s10_emulation_table[SYS_execve] = 1; /* 59 */
907 907 s10_emulation_table[SYS_acctctl] = 1; /* 71 */
908 908 s10_emulation_table[SYS_getpagesizes] = 1; /* 73 */
909 909 s10_emulation_table[S10_SYS_issetugid] = 1; /* 75 */
910 910 s10_emulation_table[SYS_uname] = 1; /* 135 */
911 + s10_emulation_table[SYS_systeminfo] = 1; /* 139 */
911 912 s10_emulation_table[SYS_pwrite] = 1; /* 174 */
912 913 s10_emulation_table[SYS_sigqueue] = 1; /* 190 */
913 914 s10_emulation_table[SYS_pwrite64] = 1; /* 223 */
914 915 s10_emulation_table[SYS_zone] = 1; /* 227 */
915 916
916 917 err = mod_install(&modlinkage);
917 918 if (err) {
918 919 cmn_err(CE_WARN, "Couldn't install brand module");
919 920 kmem_free(s10_emulation_table, NSYSCALL);
920 921 }
921 922
922 923 return (err);
923 924 }
924 925
925 926 int
926 927 _info(struct modinfo *modinfop)
927 928 {
928 929 return (mod_info(&modlinkage, modinfop));
929 930 }
930 931
931 932 int
932 933 _fini(void)
933 934 {
934 935 int err;
935 936
936 937 /*
937 938 * If there are any zones using this brand, we can't allow it to be
938 939 * unloaded.
939 940 */
940 941 if (brand_zone_count(&s10_brand))
941 942 return (EBUSY);
942 943
943 944 kmem_free(s10_emulation_table, NSYSCALL);
944 945 s10_emulation_table = NULL;
945 946
946 947 err = mod_remove(&modlinkage);
947 948 if (err)
948 949 cmn_err(CE_WARN, "Couldn't unload s10 brand module");
949 950
950 951 return (err);
951 952 }
|
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX