19acbbeafSnn /* 29acbbeafSnn * CDDL HEADER START 39acbbeafSnn * 49acbbeafSnn * The contents of this file are subject to the terms of the 59acbbeafSnn * Common Development and Distribution License (the "License"). 69acbbeafSnn * You may not use this file except in compliance with the License. 79acbbeafSnn * 89acbbeafSnn * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 99acbbeafSnn * or http://www.opensolaris.org/os/licensing. 109acbbeafSnn * See the License for the specific language governing permissions 119acbbeafSnn * and limitations under the License. 129acbbeafSnn * 139acbbeafSnn * When distributing Covered Code, include this CDDL HEADER in each 149acbbeafSnn * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 159acbbeafSnn * If applicable, add the following below this CDDL HEADER, with the 169acbbeafSnn * fields enclosed by brackets "[]" replaced with your own identifying 179acbbeafSnn * information: Portions Copyright [yyyy] [name of copyright owner] 189acbbeafSnn * 199acbbeafSnn * CDDL HEADER END 209acbbeafSnn */ 219acbbeafSnn /* 2259f2ff5cSedp * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 239acbbeafSnn * Use is subject to license terms. 249acbbeafSnn */ 259acbbeafSnn 269acbbeafSnn #pragma ident "%Z%%M% %I% %E% SMI" 279acbbeafSnn 289acbbeafSnn #include <sys/errno.h> 299acbbeafSnn #include <sys/exec.h> 309acbbeafSnn #include <sys/kmem.h> 319acbbeafSnn #include <sys/modctl.h> 329acbbeafSnn #include <sys/model.h> 339acbbeafSnn #include <sys/proc.h> 349acbbeafSnn #include <sys/syscall.h> 359acbbeafSnn #include <sys/systm.h> 369acbbeafSnn #include <sys/thread.h> 379acbbeafSnn #include <sys/cmn_err.h> 389acbbeafSnn #include <sys/archsystm.h> 399acbbeafSnn 409acbbeafSnn #include <sys/machbrand.h> 419acbbeafSnn #include <sys/brand.h> 429acbbeafSnn #include "sn1_brand.h" 439acbbeafSnn 449acbbeafSnn char *sn1_emulation_table = NULL; 459acbbeafSnn 46*319378d9Seh void sn1_init_brand_data(zone_t *); 47*319378d9Seh void sn1_free_brand_data(zone_t *); 489acbbeafSnn void sn1_setbrand(proc_t *); 499acbbeafSnn int sn1_getattr(zone_t *, int, void *, size_t *); 509acbbeafSnn int sn1_setattr(zone_t *, int, void *, size_t); 519acbbeafSnn int sn1_brandsys(int, int64_t *, uintptr_t, uintptr_t, uintptr_t, 529acbbeafSnn uintptr_t, uintptr_t, uintptr_t); 539acbbeafSnn void sn1_copy_procdata(proc_t *, proc_t *); 549acbbeafSnn void sn1_proc_exit(struct proc *, klwp_t *); 559acbbeafSnn void sn1_exec(); 569acbbeafSnn int sn1_initlwp(klwp_t *); 579acbbeafSnn void sn1_forklwp(klwp_t *, klwp_t *); 589acbbeafSnn void sn1_freelwp(klwp_t *); 599acbbeafSnn void sn1_lwpexit(klwp_t *); 609acbbeafSnn int sn1_elfexec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int, 619acbbeafSnn long *, int, caddr_t, cred_t *, int); 629acbbeafSnn 639acbbeafSnn /* sn1 brand */ 649acbbeafSnn struct brand_ops sn1_brops = { 65*319378d9Seh sn1_init_brand_data, 66*319378d9Seh sn1_free_brand_data, 679acbbeafSnn sn1_brandsys, 689acbbeafSnn sn1_setbrand, 699acbbeafSnn sn1_getattr, 709acbbeafSnn sn1_setattr, 719acbbeafSnn sn1_copy_procdata, 729acbbeafSnn sn1_proc_exit, 739acbbeafSnn sn1_exec, 749acbbeafSnn lwp_setrval, 759acbbeafSnn sn1_initlwp, 769acbbeafSnn sn1_forklwp, 779acbbeafSnn sn1_freelwp, 789acbbeafSnn sn1_lwpexit, 799acbbeafSnn sn1_elfexec 809acbbeafSnn }; 819acbbeafSnn 829acbbeafSnn #ifdef sparc 839acbbeafSnn 849acbbeafSnn struct brand_mach_ops sn1_mops = { 859acbbeafSnn sn1_brand_syscall_callback, 869acbbeafSnn sn1_brand_syscall_callback 879acbbeafSnn }; 889acbbeafSnn 899acbbeafSnn #else /* sparc */ 909acbbeafSnn 919acbbeafSnn #ifdef __amd64 929acbbeafSnn 939acbbeafSnn struct brand_mach_ops sn1_mops = { 949acbbeafSnn sn1_brand_sysenter_callback, 959acbbeafSnn NULL, 969acbbeafSnn sn1_brand_int91_callback, 979acbbeafSnn sn1_brand_syscall_callback, 989acbbeafSnn sn1_brand_syscall32_callback, 999acbbeafSnn NULL 1009acbbeafSnn }; 1019acbbeafSnn 1029acbbeafSnn #else /* ! __amd64 */ 1039acbbeafSnn 1049acbbeafSnn struct brand_mach_ops sn1_mops = { 1059acbbeafSnn sn1_brand_sysenter_callback, 1069acbbeafSnn NULL, 1079acbbeafSnn NULL, 1089acbbeafSnn sn1_brand_syscall_callback, 1099acbbeafSnn NULL, 1109acbbeafSnn NULL 1119acbbeafSnn }; 1129acbbeafSnn #endif /* __amd64 */ 1139acbbeafSnn 1149acbbeafSnn #endif /* _sparc */ 1159acbbeafSnn 1169acbbeafSnn struct brand sn1_brand = { 1179acbbeafSnn BRAND_VER_1, 1189acbbeafSnn "sn1", 1199acbbeafSnn &sn1_brops, 1209acbbeafSnn &sn1_mops 1219acbbeafSnn }; 1229acbbeafSnn 1239acbbeafSnn static struct modlbrand modlbrand = { 1249acbbeafSnn &mod_brandops, "Solaris N-1 Brand %I%", &sn1_brand 1259acbbeafSnn }; 1269acbbeafSnn 1279acbbeafSnn static struct modlinkage modlinkage = { 1289acbbeafSnn MODREV_1, (void *)&modlbrand, NULL 1299acbbeafSnn }; 1309acbbeafSnn 1319acbbeafSnn void 1329acbbeafSnn sn1_setbrand(proc_t *p) 1339acbbeafSnn { 1349acbbeafSnn p->p_brand_data = NULL; 1359acbbeafSnn p->p_brand = &sn1_brand; 1369acbbeafSnn } 1379acbbeafSnn 1389acbbeafSnn /* ARGSUSED */ 1399acbbeafSnn int 1409acbbeafSnn sn1_getattr(zone_t *zone, int attr, void *buf, size_t *bufsize) 1419acbbeafSnn { 1429acbbeafSnn return (EINVAL); 1439acbbeafSnn } 1449acbbeafSnn 1459acbbeafSnn /* ARGSUSED */ 1469acbbeafSnn int 1479acbbeafSnn sn1_setattr(zone_t *zone, int attr, void *buf, size_t bufsize) 1489acbbeafSnn { 1499acbbeafSnn return (EINVAL); 1509acbbeafSnn } 1519acbbeafSnn 1529acbbeafSnn /* 1539acbbeafSnn * Get the address of the user-space system call handler from the user 1549acbbeafSnn * process and attach it to the proc structure. 1559acbbeafSnn */ 1569acbbeafSnn /*ARGSUSED*/ 1579acbbeafSnn int 1589acbbeafSnn sn1_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2, 1599acbbeafSnn uintptr_t arg3, uintptr_t arg4, uintptr_t arg5, uintptr_t arg6) 1609acbbeafSnn { 1619acbbeafSnn proc_t *p = curproc; 1629acbbeafSnn *rval = 0; 1639acbbeafSnn 1649acbbeafSnn if (cmd == B_REGISTER) { 1659acbbeafSnn p->p_brand = &sn1_brand; 1669acbbeafSnn p->p_brand_data = (void *) arg1; 1679acbbeafSnn return (0); 1689acbbeafSnn } 1699acbbeafSnn 1709acbbeafSnn ASSERT(p->p_brand == &sn1_brand); 1719acbbeafSnn 1729acbbeafSnn return (EINVAL); 1739acbbeafSnn } 1749acbbeafSnn 1759acbbeafSnn /* 1769acbbeafSnn * Copy the per-process brand data from a parent proc to a child. In the 1779acbbeafSnn * sn1 brand, the only per-process state is the address of the user-space 1789acbbeafSnn * handler. 1799acbbeafSnn */ 1809acbbeafSnn void 1819acbbeafSnn sn1_copy_procdata(proc_t *child, proc_t *parent) 1829acbbeafSnn { 1839acbbeafSnn child->p_brand_data = parent->p_brand_data; 1849acbbeafSnn } 1859acbbeafSnn 1869acbbeafSnn /*ARGSUSED*/ 1879acbbeafSnn void 1889acbbeafSnn sn1_proc_exit(struct proc *p, klwp_t *l) 1899acbbeafSnn { 1909acbbeafSnn p->p_brand_data = NULL; 1919acbbeafSnn p->p_brand = &native_brand; 1929acbbeafSnn } 1939acbbeafSnn 1949acbbeafSnn void 1959acbbeafSnn sn1_exec() 1969acbbeafSnn { 1979acbbeafSnn curproc->p_brand_data = NULL; 1989acbbeafSnn } 1999acbbeafSnn 2009acbbeafSnn /*ARGSUSED*/ 2019acbbeafSnn int 2029acbbeafSnn sn1_initlwp(klwp_t *l) 2039acbbeafSnn { 2049acbbeafSnn return (0); 2059acbbeafSnn } 2069acbbeafSnn 207*319378d9Seh /*ARGSUSED*/ 208*319378d9Seh void 209*319378d9Seh sn1_init_brand_data(zone_t *zone) 210*319378d9Seh { 211*319378d9Seh } 212*319378d9Seh 213*319378d9Seh /*ARGSUSED*/ 214*319378d9Seh void 215*319378d9Seh sn1_free_brand_data(zone_t *zone) 216*319378d9Seh { 217*319378d9Seh } 218*319378d9Seh 2199acbbeafSnn /*ARGSUSED*/ 2209acbbeafSnn void 2219acbbeafSnn sn1_forklwp(klwp_t *p, klwp_t *c) 2229acbbeafSnn { 2239acbbeafSnn } 2249acbbeafSnn 2259acbbeafSnn /*ARGSUSED*/ 2269acbbeafSnn void 2279acbbeafSnn sn1_freelwp(klwp_t *l) 2289acbbeafSnn { 2299acbbeafSnn } 2309acbbeafSnn 2319acbbeafSnn /*ARGSUSED*/ 2329acbbeafSnn void 2339acbbeafSnn sn1_lwpexit(klwp_t *l) 2349acbbeafSnn { 2359acbbeafSnn } 2369acbbeafSnn 2379acbbeafSnn int 2389acbbeafSnn sn1_elfexec(vnode_t *vp, execa_t *uap, uarg_t *args, intpdata_t *idatap, 2399acbbeafSnn int level, long *execsz, int setid, caddr_t exec_file, cred_t *cred, 2409acbbeafSnn int brand_action) 2419acbbeafSnn { 2429acbbeafSnn args->brandname = "sn1"; 2439acbbeafSnn return ((args->execswp->exec_func)(vp, uap, args, idatap, level + 1, 2449acbbeafSnn execsz, setid, exec_file, cred, brand_action)); 2459acbbeafSnn } 2469acbbeafSnn 2479acbbeafSnn 2489acbbeafSnn int 2499acbbeafSnn _init(void) 2509acbbeafSnn { 2519acbbeafSnn int err; 2529acbbeafSnn 2539acbbeafSnn /* 2549acbbeafSnn * Set up the table indicating which system calls we want to 2559acbbeafSnn * interpose on. We should probably build this automatically from 2569acbbeafSnn * a list of system calls that is shared with the user-space 2579acbbeafSnn * library. 2589acbbeafSnn */ 2599acbbeafSnn sn1_emulation_table = kmem_zalloc(NSYSCALL, KM_SLEEP); 2609acbbeafSnn sn1_emulation_table[SYS_uname] = 1; 2619acbbeafSnn 2629acbbeafSnn err = mod_install(&modlinkage); 2639acbbeafSnn if (err) { 2649acbbeafSnn cmn_err(CE_WARN, "Couldn't install brand module"); 2659acbbeafSnn kmem_free(sn1_emulation_table, NSYSCALL); 2669acbbeafSnn } 2679acbbeafSnn 2689acbbeafSnn return (err); 2699acbbeafSnn } 2709acbbeafSnn 2719acbbeafSnn int 2729acbbeafSnn _info(struct modinfo *modinfop) 2739acbbeafSnn { 2749acbbeafSnn return (mod_info(&modlinkage, modinfop)); 2759acbbeafSnn } 2769acbbeafSnn 2779acbbeafSnn int 2789acbbeafSnn _fini(void) 2799acbbeafSnn { 2809acbbeafSnn int err; 2819acbbeafSnn 2829acbbeafSnn /* 2839acbbeafSnn * If there are any zones using this brand, we can't allow it to be 2849acbbeafSnn * unloaded. 2859acbbeafSnn */ 2869acbbeafSnn if (brand_zone_count(&sn1_brand)) 2879acbbeafSnn return (EBUSY); 2889acbbeafSnn 2899acbbeafSnn kmem_free(sn1_emulation_table, NSYSCALL); 2909acbbeafSnn sn1_emulation_table = NULL; 2919acbbeafSnn 2929acbbeafSnn err = mod_remove(&modlinkage); 2939acbbeafSnn if (err) 2949acbbeafSnn cmn_err(CE_WARN, "Couldn't unload sn1 brand module"); 2959acbbeafSnn 2969acbbeafSnn return (err); 2979acbbeafSnn } 298