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 /*
23 * Copyright (c) 2013, OmniTI Computer Consulting, Inc. All rights reserved.
24 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 #include <sys/errno.h>
28 #include <sys/exec.h>
29 #include <sys/file.h>
30 #include <sys/kmem.h>
31 #include <sys/modctl.h>
32 #include <sys/model.h>
33 #include <sys/proc.h>
34 #include <sys/syscall.h>
35 #include <sys/systm.h>
36 #include <sys/thread.h>
37 #include <sys/cmn_err.h>
38 #include <sys/archsystm.h>
39 #include <sys/pathname.h>
40 #include <sys/sunddi.h>
41
42 #include <sys/machbrand.h>
43 #include <sys/brand.h>
44 #include "s10_brand.h"
45
46 char *s10_emulation_table = NULL;
47
48 void s10_init_brand_data(zone_t *);
49 void s10_free_brand_data(zone_t *);
50 void s10_setbrand(proc_t *);
51 int s10_getattr(zone_t *, int, void *, size_t *);
52 int s10_setattr(zone_t *, int, void *, size_t);
53 int s10_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t,
54 uintptr_t, uintptr_t, uintptr_t);
55 void s10_copy_procdata(proc_t *, proc_t *);
56 void s10_proc_exit(struct proc *, klwp_t *);
57 void s10_exec();
58 int s10_initlwp(klwp_t *);
59 void s10_forklwp(klwp_t *, klwp_t *);
60 void s10_freelwp(klwp_t *);
61 void s10_lwpexit(klwp_t *);
62 int s10_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
63 long *, int, caddr_t, cred_t *, int);
64 void s10_sigset_native_to_s10(sigset_t *);
65 void s10_sigset_s10_to_native(sigset_t *);
66
67 /* s10 brand */
68 struct brand_ops s10_brops = {
69 s10_init_brand_data,
70 s10_free_brand_data,
71 s10_brandsys,
72 s10_setbrand,
73 s10_getattr,
74 s10_setattr,
75 s10_copy_procdata,
76 s10_proc_exit,
77 s10_exec,
78 lwp_setrval,
79 s10_initlwp,
80 s10_forklwp,
81 s10_freelwp,
82 s10_lwpexit,
83 s10_elfexec,
84 s10_sigset_native_to_s10,
85 s10_sigset_s10_to_native,
86 S10_NSIG,
87 };
88
89 #ifdef sparc
90
91 struct brand_mach_ops s10_mops = {
92 s10_brand_syscall_callback,
93 s10_brand_syscall32_callback
94 };
95
96 #else /* sparc */
97
98 #ifdef __amd64
99
100 struct brand_mach_ops s10_mops = {
101 s10_brand_sysenter_callback,
102 NULL,
103 s10_brand_int91_callback,
104 s10_brand_syscall_callback,
105 s10_brand_syscall32_callback,
106 NULL
107 };
108
109 #else /* ! __amd64 */
110
111 struct brand_mach_ops s10_mops = {
112 s10_brand_sysenter_callback,
113 NULL,
114 NULL,
115 s10_brand_syscall_callback,
116 NULL,
117 NULL
118 };
119 #endif /* __amd64 */
120
121 #endif /* _sparc */
122
123 struct brand s10_brand = {
124 BRAND_VER_1,
125 "solaris10",
126 &s10_brops,
127 &s10_mops
128 };
129
130 static struct modlbrand modlbrand = {
131 &mod_brandops, /* type of module */
132 "Solaris 10 Brand", /* description of module */
133 &s10_brand /* driver ops */
134 };
135
136 static struct modlinkage modlinkage = {
137 MODREV_1, (void *)&modlbrand, NULL
138 };
139
140 void
141 s10_setbrand(proc_t *p)
142 {
143 brand_solaris_setbrand(p, &s10_brand);
144 }
145
146 /*ARGSUSED*/
147 int
148 s10_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize)
149 {
150 ASSERT(zone->zone_brand == &s10_brand);
151 if (attr == S10_EMUL_BITMAP) {
152 if (buf == NULL || *bufsize != sizeof (s10_emul_bitmap_t))
153 return (EINVAL);
154 if (copyout(((s10_zone_data_t *)zone->zone_brand_data)->
155 emul_bitmap, buf, sizeof (s10_emul_bitmap_t)) != 0)
156 return (EFAULT);
157 return (0);
158 }
159
160 return (EINVAL);
161 }
162
163 int
164 s10_setattr(zone_t *zone, int attr, void *buf, size_t bufsize)
165 {
166 ASSERT(zone->zone_brand == &s10_brand);
167 if (attr == S10_EMUL_BITMAP) {
168 if (buf == NULL || bufsize != sizeof (s10_emul_bitmap_t))
169 return (EINVAL);
170 if (copyin(buf, ((s10_zone_data_t *)zone->zone_brand_data)->
171 emul_bitmap, sizeof (s10_emul_bitmap_t)) != 0)
172 return (EFAULT);
173 return (0);
174 }
175
176 return (EINVAL);
177 }
178
179 #ifdef __amd64
180 /*
181 * The Nevada kernel clears %fs for threads in 64-bit x86 processes but S10's
182 * libc expects %fs to be nonzero. This causes some committed
183 * libc/libthread interfaces (e.g., thr_main()) to fail, which impacts several
184 * libraries, including libdoor. This function sets the specified LWP's %fs
185 * register to the legacy S10 selector value (LWPFS_SEL).
186 *
187 * The best solution to the aforementioned problem is backporting CRs
188 * 6467491 to Solaris 10 so that 64-bit x86 Solaris 10 processes
189 * would accept zero for %fs. Backporting the CRs is a requirement for running
190 * S10 Containers in PV domUs because 64-bit Xen clears %fsbase when %fs is
191 * nonzero. Such behavior breaks 64-bit processes because Xen has to fetch the
192 * FS segments' base addresses from the LWPs' GDTs, which are only capable of
193 * 32-bit addressing.
194 */
195 /*ARGSUSED*/
196 static void
197 s10_amd64_correct_fsreg(klwp_t *l)
198 {
199 if (lwp_getdatamodel(l) == DATAMODEL_NATIVE) {
200 kpreempt_disable();
201 l->lwp_pcb.pcb_fs = LWPFS_SEL;
202 l->lwp_pcb.pcb_rupdate = 1;
203 lwptot(l)->t_post_sys = 1; /* Guarantee update_sregs() */
204 kpreempt_enable();
205 }
206 }
207 #endif /* __amd64 */
208
209 /*
210 * Native processes are started with the native ld.so.1 as the command. This
211 * brand op is invoked by s10_npreload to fix up the command and arguments
212 * so that apps like pgrep or ps see the expected command strings.
213 */
214 int
215 s10_native(void *cmd, void *args)
216 {
217 struct user *up = PTOU(curproc);
218 char cmd_buf[MAXCOMLEN + 1];
219 char arg_buf[PSARGSZ];
220
221 if (copyin(cmd, &cmd_buf, sizeof (cmd_buf)) != 0)
222 return (EFAULT);
223 if (copyin(args, &arg_buf, sizeof (arg_buf)) != 0)
224 return (EFAULT);
225
226 /*
227 * Make sure that the process' interpreter is the native dynamic linker.
228 * Convention dictates that native processes executing within solaris10-
229 * branded zones are interpreted by the native dynamic linker (the
230 * process and its arguments are specified as arguments to the dynamic
231 * linker). If this convention is violated (i.e.,
232 * brandsys(B_S10_NATIVE, ...) is invoked by a process that shouldn't be
233 * native), then do nothing and silently indicate success.
234 */
235 if (strcmp(up->u_comm, S10_LINKER_NAME) != 0)
236 return (0);
237
238 /*
239 * The sizeof has an extra value for the trailing '\0' so this covers
240 * the appended " " in the following strcmps.
241 */
242 if (strncmp(up->u_psargs, BRAND_NATIVE_LINKER64 " ",
243 sizeof (BRAND_NATIVE_LINKER64)) != 0 &&
244 strncmp(up->u_psargs, BRAND_NATIVE_LINKER32 " ",
245 sizeof (BRAND_NATIVE_LINKER32)) != 0)
246 return (0);
247
248 mutex_enter(&curproc->p_lock);
249 (void) strlcpy(up->u_comm, cmd_buf, sizeof (up->u_comm));
250 (void) strlcpy(up->u_psargs, arg_buf, sizeof (up->u_psargs));
251 mutex_exit(&curproc->p_lock);
252
253 return (0);
254 }
255
256 /*ARGSUSED*/
257 int
258 s10_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
259 uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6)
260 {
261 proc_t *p = curproc;
262 int res;
263
264 *rval = 0;
265
266 if (cmd == B_S10_NATIVE)
267 return (s10_native((void *)arg1, (void *)arg2));
268
269 res = brand_solaris_cmd(cmd, arg1, arg2, arg3, &s10_brand, S10_VERSION);
270 if (res >= 0)
271 return (res);
272
273 switch ((cmd)) {
274 case B_S10_PIDINFO:
275 /*
276 * The s10 brand needs to be able to get the pid of the
277 * current process and the pid of the zone's init, and it
278 * needs to do this on every process startup. Early in
279 * brand startup, we can't call getpid() because calls to
280 * getpid() represent a magical signal to some old-skool
281 * debuggers. By merging all of this into one call, we
282 * make this quite a bit cheaper and easier to handle in
283 * the brand module.
284 */
285 if (copyout(&p->p_pid, (void *)arg1, sizeof (pid_t)) != 0)
286 return (EFAULT);
287 if (copyout(&p->p_zone->zone_proc_initpid, (void *)arg2,
288 sizeof (pid_t)) != 0)
289 return (EFAULT);
290 return (0);
291
292 case B_S10_ISFDXATTRDIR: {
293 /*
294 * This subcommand enables the userland brand emulation library
295 * to determine whether a file descriptor refers to an extended
296 * file attributes directory. There is no standard syscall or
297 * libc function that can make such a determination.
298 */
299 file_t *dir_filep;
300
301 dir_filep = getf((int)arg1);
302 if (dir_filep == NULL)
303 return (EBADF);
304 ASSERT(dir_filep->f_vnode != NULL);
305 *rval = IS_XATTRDIR(dir_filep->f_vnode);
306 releasef((int)arg1);
307 return (0);
308 }
309
310 #ifdef __amd64
311 case B_S10_FSREGCORRECTION:
312 /*
313 * This subcommand exists so that the SYS_lwp_private and
314 * SYS_lwp_create syscalls can manually set the current thread's
315 * %fs register to the legacy S10 selector value for 64-bit x86
316 * processes.
317 */
318 s10_amd64_correct_fsreg(ttolwp(curthread));
319 return (0);
320 #endif /* __amd64 */
321 }
322
323 return (EINVAL);
324 }
325
326 void
327 s10_copy_procdata(proc_t *child, proc_t *parent)
328 {
329 brand_solaris_copy_procdata(child, parent, &s10_brand);
330 }
331
332 void
333 s10_proc_exit(struct proc *p, klwp_t *l)
334 {
335 brand_solaris_proc_exit(p, l, &s10_brand);
336 }
337
338 void
339 s10_exec()
340 {
341 brand_solaris_exec(&s10_brand);
342 }
343
344 int
345 s10_initlwp(klwp_t *l)
346 {
347 return (brand_solaris_initlwp(l, &s10_brand));
348 }
349
350 void
351 s10_forklwp(klwp_t *p, klwp_t *c)
352 {
353 brand_solaris_forklwp(p, c, &s10_brand);
354
355 #ifdef __amd64
356 /*
357 * Only correct the child's %fs register if the parent's %fs register
358 * is LWPFS_SEL. If the parent's %fs register is zero, then the Solaris
359 * 10 environment that we're emulating uses a version of libc that
360 * works when %fs is zero (i.e., it contains backports of CRs 6467491
361 * and 6501650).
362 */
363 if (p->lwp_pcb.pcb_fs == LWPFS_SEL)
364 s10_amd64_correct_fsreg(c);
365 #endif /* __amd64 */
366 }
367
368 void
369 s10_freelwp(klwp_t *l)
370 {
371 brand_solaris_freelwp(l, &s10_brand);
372 }
373
374 void
375 s10_lwpexit(klwp_t *l)
376 {
377 brand_solaris_lwpexit(l, &s10_brand);
378 }
379
380 void
381 s10_free_brand_data(zone_t *zone)
382 {
383 kmem_free(zone->zone_brand_data, sizeof (s10_zone_data_t));
384 }
385
386 void
387 s10_init_brand_data(zone_t *zone)
388 {
389 ASSERT(zone->zone_brand == &s10_brand);
390 ASSERT(zone->zone_brand_data == NULL);
391 zone->zone_brand_data = kmem_zalloc(sizeof (s10_zone_data_t), KM_SLEEP);
392 }
393
394 int
395 s10_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap,
396 int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred,
397 int brand_action)
398 {
399 return (brand_solaris_elfexec(vp, uap, args, idatap, level, execsz,
400 setid, exec_file, cred, brand_action, &s10_brand, S10_BRANDNAME,
401 S10_LIB, S10_LIB32, S10_LINKER, S10_LINKER32));
402 }
403
404 void
405 s10_sigset_native_to_s10(sigset_t *set)
406 {
407 int nativesig;
408 int s10sig;
409 sigset_t s10set;
410
411 /*
412 * Shortcut: we know the first 32 signals are the same in both
413 * s10 and native Solaris. Just assign the first word.
414 */
415 s10set.__sigbits[0] = set->__sigbits[0];
416 s10set.__sigbits[1] = 0;
417 s10set.__sigbits[2] = 0;
418 s10set.__sigbits[3] = 0;
419
420 /*
421 * Copy the remainder of the initial set of common signals.
422 */
423 for (nativesig = 33; nativesig < S10_SIGRTMIN; nativesig++)
424 if (sigismember(set, nativesig))
425 sigaddset(&s10set, nativesig);
426
427 /*
428 * Convert any native RT signals to their S10 values.
429 */
430 for (nativesig = _SIGRTMIN, s10sig = S10_SIGRTMIN;
431 nativesig <= _SIGRTMAX && s10sig <= S10_SIGRTMAX;
432 nativesig++, s10sig++) {
433 if (sigismember(set, nativesig))
434 sigaddset(&s10set, s10sig);
435 }
436
437 *set = s10set;
438 }
439
440 void
441 s10_sigset_s10_to_native(sigset_t *set)
442 {
443 int s10sig;
444 int nativesig;
445 sigset_t nativeset;
446
447 /*
448 * Shortcut: we know the first 32 signals are the same in both
449 * s10 and native Solaris. Just assign the first word.
450 */
451 nativeset.__sigbits[0] = set->__sigbits[0];
452 nativeset.__sigbits[1] = 0;
453 nativeset.__sigbits[2] = 0;
454 nativeset.__sigbits[3] = 0;
455
456 /*
457 * Copy the remainder of the initial set of common signals.
458 */
459 for (s10sig = 33; s10sig < S10_SIGRTMIN; s10sig++)
460 if (sigismember(set, s10sig))
461 sigaddset(&nativeset, s10sig);
462
463 /*
464 * Convert any S10 RT signals to their native values.
465 */
466 for (s10sig = S10_SIGRTMIN, nativesig = _SIGRTMIN;
467 s10sig <= S10_SIGRTMAX && nativesig <= _SIGRTMAX;
468 s10sig++, nativesig++) {
469 if (sigismember(set, s10sig))
470 sigaddset(&nativeset, nativesig);
471 }
472
473 *set = nativeset;
474 }
475
476 int
477 _init(void)
478 {
479 int err;
480
481 /*
482 * Set up the table indicating which system calls we want to
483 * interpose on. We should probably build this automatically from
484 * a list of system calls that is shared with the user-space
485 * library.
486 */
487 s10_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP);
488 s10_emulation_table[S10_SYS_forkall] = 1; /* 2 */
489 s10_emulation_table[S10_SYS_open] = 1; /* 5 */
490 s10_emulation_table[S10_SYS_wait] = 1; /* 7 */
491 s10_emulation_table[S10_SYS_creat] = 1; /* 8 */
492 s10_emulation_table[S10_SYS_link] = 1; /* 9 */
493 s10_emulation_table[S10_SYS_unlink] = 1; /* 10 */
494 s10_emulation_table[S10_SYS_exec] = 1; /* 11 */
495 s10_emulation_table[S10_SYS_mknod] = 1; /* 14 */
496 s10_emulation_table[S10_SYS_chmod] = 1; /* 15 */
497 s10_emulation_table[S10_SYS_chown] = 1; /* 16 */
498 s10_emulation_table[S10_SYS_stat] = 1; /* 18 */
499 s10_emulation_table[S10_SYS_umount] = 1; /* 22 */
500 s10_emulation_table[S10_SYS_fstat] = 1; /* 28 */
501 s10_emulation_table[S10_SYS_utime] = 1; /* 30 */
502 s10_emulation_table[S10_SYS_access] = 1; /* 33 */
503 s10_emulation_table[SYS_kill] = 1; /* 37 */
504 s10_emulation_table[S10_SYS_dup] = 1; /* 41 */
505 s10_emulation_table[S10_SYS_pipe] = 1; /* 42 */
506 s10_emulation_table[SYS_ioctl] = 1; /* 54 */
507 s10_emulation_table[SYS_execve] = 1; /* 59 */
508 s10_emulation_table[SYS_acctctl] = 1; /* 71 */
509 s10_emulation_table[S10_SYS_issetugid] = 1; /* 75 */
510 s10_emulation_table[S10_SYS_fsat] = 1; /* 76 */
511 s10_emulation_table[S10_SYS_rmdir] = 1; /* 79 */
512 s10_emulation_table[S10_SYS_mkdir] = 1; /* 80 */
513 s10_emulation_table[SYS_getdents] = 1; /* 81 */
514 s10_emulation_table[S10_SYS_poll] = 1; /* 87 */
515 s10_emulation_table[S10_SYS_lstat] = 1; /* 88 */
516 s10_emulation_table[S10_SYS_symlink] = 1; /* 89 */
517 s10_emulation_table[S10_SYS_readlink] = 1; /* 90 */
518 s10_emulation_table[S10_SYS_fchmod] = 1; /* 93 */
519 s10_emulation_table[S10_SYS_fchown] = 1; /* 94 */
520 s10_emulation_table[SYS_sigprocmask] = 1; /* 95 */
521 s10_emulation_table[SYS_sigsuspend] = 1; /* 96 */
522 s10_emulation_table[SYS_sigaction] = 1; /* 98 */
523 s10_emulation_table[SYS_sigpending] = 1; /* 99 */
524 s10_emulation_table[SYS_waitid] = 1; /* 107 */
525 s10_emulation_table[SYS_sigsendsys] = 1; /* 108 */
526 #if defined(__x86)
527 s10_emulation_table[S10_SYS_xstat] = 1; /* 123 */
528 s10_emulation_table[S10_SYS_lxstat] = 1; /* 124 */
529 s10_emulation_table[S10_SYS_fxstat] = 1; /* 125 */
530 s10_emulation_table[S10_SYS_xmknod] = 1; /* 126 */
531 #endif
532 s10_emulation_table[S10_SYS_lchown] = 1; /* 130 */
533 s10_emulation_table[S10_SYS_rename] = 1; /* 134 */
534 s10_emulation_table[SYS_uname] = 1; /* 135 */
535 s10_emulation_table[SYS_sysconfig] = 1; /* 137 */
536 s10_emulation_table[SYS_systeminfo] = 1; /* 139 */
537 s10_emulation_table[S10_SYS_fork1] = 1; /* 143 */
538 s10_emulation_table[SYS_sigtimedwait] = 1; /* 144 */
539 s10_emulation_table[S10_SYS_lwp_sema_wait] = 1; /* 147 */
540 s10_emulation_table[S10_SYS_utimes] = 1; /* 154 */
541 s10_emulation_table[SYS_lwp_create] = 1; /* 159 */
542 s10_emulation_table[SYS_lwp_kill] = 1; /* 163 */
543 s10_emulation_table[SYS_lwp_sigmask] = 1; /* 165 */
544 #if defined(__amd64)
545 s10_emulation_table[SYS_lwp_private] = 1; /* 166 */
546 #endif /* __amd64 */
547 s10_emulation_table[S10_SYS_lwp_mutex_lock] = 1; /* 169 */
548 s10_emulation_table[SYS_pwrite] = 1; /* 174 */
549 s10_emulation_table[SYS_acl] = 1; /* 185 */
550 s10_emulation_table[SYS_auditsys] = 1; /* 186 */
551 s10_emulation_table[SYS_sigqueue] = 1; /* 190 */
552 s10_emulation_table[SYS_facl] = 1; /* 200 */
553 s10_emulation_table[SYS_signotify] = 1; /* 205 */
554 s10_emulation_table[SYS_lwp_mutex_timedlock] = 1; /* 210 */
555 s10_emulation_table[SYS_getdents64] = 1; /* 213 */
556 s10_emulation_table[S10_SYS_stat64] = 1; /* 215 */
557 s10_emulation_table[S10_SYS_lstat64] = 1; /* 216 */
558 s10_emulation_table[S10_SYS_fstat64] = 1; /* 217 */
559 s10_emulation_table[SYS_pwrite64] = 1; /* 223 */
560 s10_emulation_table[S10_SYS_creat64] = 1; /* 224 */
561 s10_emulation_table[S10_SYS_open64] = 1; /* 225 */
562 s10_emulation_table[SYS_zone] = 1; /* 227 */
563 s10_emulation_table[S10_SYS_so_socket] = 1; /* 230 */
564 s10_emulation_table[S10_SYS_accept] = 1; /* 234 */
565 s10_emulation_table[SYS_lwp_mutex_trylock] = 1; /* 251 */
566
567 err = mod_install(&modlinkage);
568 if (err) {
569 cmn_err(CE_WARN, "Couldn't install brand module");
570 kmem_free(s10_emulation_table, NSYSCALL);
571 }
572
573 return (err);
574 }
575
576 int
577 _info(struct modinfo *modinfop)
578 {
579 return (mod_info(&modlinkage, modinfop));
580 }
581
582 int
583 _fini(void)
584 {
585 return (brand_solaris_fini(&s10_emulation_table, &modlinkage,
586 &s10_brand));
587 }