diff options
Diffstat (limited to 'usr/src/uts/common/os/zone.c')
-rw-r--r-- | usr/src/uts/common/os/zone.c | 80 |
1 files changed, 69 insertions, 11 deletions
diff --git a/usr/src/uts/common/os/zone.c b/usr/src/uts/common/os/zone.c index 6a5c9243b3..9fd6b423bd 100644 --- a/usr/src/uts/common/os/zone.c +++ b/usr/src/uts/common/os/zone.c @@ -228,6 +228,7 @@ #include <sys/nvpair.h> #include <sys/rctl.h> #include <sys/fss.h> +#include <sys/brand.h> #include <sys/zone.h> #include <sys/tsol/label.h> @@ -330,7 +331,6 @@ static kmutex_t mount_lock; const char * const zone_default_initname = "/sbin/init"; static char * const zone_prefix = "/zone/"; - static int zone_shutdown(zoneid_t zoneid); /* @@ -1223,6 +1223,8 @@ zone_init(void) zone0.zone_nlwps = p0.p_lwpcnt; zone0.zone_ntasks = 1; mutex_exit(&p0.p_lock); + zone0.zone_restart_init = B_TRUE; + zone0.zone_brand = &native_brand; rctl_prealloc_destroy(gp); /* * pool_default hasn't been initialized yet, so we let pool_init() take @@ -2330,33 +2332,40 @@ void zone_start_init(void) { proc_t *p = ttoproc(curthread); + zone_t *z = p->p_zone; ASSERT(!INGLOBALZONE(curproc)); /* + * For all purposes (ZONE_ATTR_INITPID and restart_init), + * storing just the pid of init is sufficient. + */ + z->zone_proc_initpid = p->p_pid; + + /* * We maintain zone_boot_err so that we can return the cause of the * failure back to the caller of the zone_boot syscall. */ p->p_zone->zone_boot_err = start_init_common(); mutex_enter(&zone_status_lock); - if (p->p_zone->zone_boot_err != 0) { + if (z->zone_boot_err != 0) { /* * Make sure we are still in the booting state-- we could have * raced and already be shutting down, or even further along. */ - if (zone_status_get(p->p_zone) == ZONE_IS_BOOTING) - zone_status_set(p->p_zone, ZONE_IS_SHUTTING_DOWN); + if (zone_status_get(z) == ZONE_IS_BOOTING) + zone_status_set(z, ZONE_IS_SHUTTING_DOWN); mutex_exit(&zone_status_lock); /* It's gone bad, dispose of the process */ - if (proc_exit(CLD_EXITED, p->p_zone->zone_boot_err) != 0) { + if (proc_exit(CLD_EXITED, z->zone_boot_err) != 0) { mutex_enter(&p->p_lock); ASSERT(p->p_flag & SEXITLWPS); lwp_exit(); } } else { - if (zone_status_get(p->p_zone) == ZONE_IS_BOOTING) - zone_status_set(p->p_zone, ZONE_IS_RUNNING); + if (zone_status_get(z) == ZONE_IS_BOOTING) + zone_status_set(z, ZONE_IS_RUNNING); mutex_exit(&zone_status_lock); /* cause the process to return to userland. */ lwp_rtt(); @@ -2939,6 +2948,9 @@ zone_create(const char *zone_name, const char *zone_root, zone->zone_psetid = ZONE_PS_INVAL; zone->zone_ncpus = 0; zone->zone_ncpus_online = 0; + zone->zone_restart_init = B_TRUE; + zone->zone_brand = &native_brand; + zone->zone_initname = NULL; mutex_init(&zone->zone_lock, NULL, MUTEX_DEFAULT, NULL); mutex_init(&zone->zone_nlwps_lock, NULL, MUTEX_DEFAULT, NULL); cv_init(&zone->zone_cv, NULL, CV_DEFAULT, NULL); @@ -3464,6 +3476,9 @@ zone_shutdown(zoneid_t zoneid) zone_rele(zone); return (set_errno(EINTR)); } + + brand_unregister_zone(zone->zone_brand); + zone_rele(zone); return (0); } @@ -3771,6 +3786,18 @@ zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize) copyout(&initpid, buf, bufsize) != 0) error = EFAULT; break; + case ZONE_ATTR_BRAND: + size = strlen(zone->zone_brand->b_name) + 1; + + if (bufsize > size) + bufsize = size; + if (buf != NULL) { + err = copyoutstr(zone->zone_brand->b_name, buf, + bufsize, NULL); + if (err != 0 && err != ENAMETOOLONG) + error = EFAULT; + } + break; case ZONE_ATTR_INITNAME: size = strlen(zone->zone_initname) + 1; if (bufsize > size) @@ -3797,7 +3824,12 @@ zone_getattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize) } break; default: - error = EINVAL; + if ((attr >= ZONE_ATTR_BRAND_ATTRS) && ZONE_IS_BRANDED(zone)) { + size = bufsize; + error = ZBROP(zone)->b_getattr(zone, attr, buf, &size); + } else { + error = EINVAL; + } } zone_rele(zone); @@ -3815,6 +3847,7 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize) { zone_t *zone; zone_status_t zone_status; + struct brand_attr *attrp; int err; if (secpolicy_zone_config(CRED()) != 0) @@ -3847,8 +3880,33 @@ zone_setattr(zoneid_t zoneid, int attr, void *buf, size_t bufsize) case ZONE_ATTR_BOOTARGS: err = zone_set_bootargs(zone, (const char *)buf); break; + case ZONE_ATTR_BRAND: + ASSERT(!ZONE_IS_BRANDED(zone)); + err = 0; + attrp = kmem_alloc(sizeof (struct brand_attr), KM_SLEEP); + if ((buf == NULL) || + (copyin(buf, attrp, sizeof (struct brand_attr)) != 0)) { + kmem_free(attrp, sizeof (struct brand_attr)); + err = EFAULT; + break; + } + + if (is_system_labeled() && strncmp(attrp->ba_brandname, + NATIVE_BRAND_NAME, MAXNAMELEN) != 0) { + err = EPERM; + break; + } + + zone->zone_brand = brand_register_zone(attrp); + kmem_free(attrp, sizeof (struct brand_attr)); + if (zone->zone_brand == NULL) + err = EINVAL; + break; default: - err = EINVAL; + if ((attr >= ZONE_ATTR_BRAND_ATTRS) && ZONE_IS_BRANDED(zone)) + err = ZBROP(zone)->b_setattr(zone, attr, buf, bufsize); + else + err = EINVAL; } done: @@ -4145,10 +4203,10 @@ zone_enter(zoneid_t zoneid) */ mutex_enter(&pidlock); sp = zone->zone_zsched->p_sessp; - SESS_HOLD(sp); + sess_hold(zone->zone_zsched); mutex_enter(&pp->p_lock); pgexit(pp); - SESS_RELE(pp->p_sessp); + sess_rele(pp->p_sessp, B_TRUE); pp->p_sessp = sp; pgjoin(pp, zone->zone_zsched->p_pidp); mutex_exit(&pp->p_lock); |