int _zexec_init_template(void) { int fd; int err = 0; fd = open64(CTFS_ROOT "/process/template", O_RDWR); if (fd == -1) { return (-1); } /* * zlogin doesn't do anything with the contract. * Deliver no events, don't inherit, and allow it to be orphaned. */ err |= ct_tmpl_set_critical(fd, 0); err |= ct_tmpl_set_informative(fd, 0); err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR); err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT); if (err || ct_tmpl_activate(fd)) { (void) close(fd); return (-1); } return (fd); }
void solaris_contract_pre_fork(void) { if ((tmpl_fd = open64(CT_TEMPLATE, O_RDWR)) == -1) { error("%s: open %s: %s", __func__, CT_TEMPLATE, strerror(errno)); return; } debug2("%s: setting up process contract template on fd %d", __func__, tmpl_fd); /* First we set the template parameters and event sets. */ if (ct_pr_tmpl_set_param(tmpl_fd, CT_PR_PGRPONLY) != 0) { error("%s: Error setting process contract parameter set " "(pgrponly): %s", __func__, strerror(errno)); goto fail; } if (ct_pr_tmpl_set_fatal(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "fatal events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_critical(tmpl_fd, 0) != 0) { error("%s: Error setting process contract template " "critical events: %s", __func__, strerror(errno)); goto fail; } if (ct_tmpl_set_informative(tmpl_fd, CT_PR_EV_HWERR) != 0) { error("%s: Error setting process contract template " "informative events: %s", __func__, strerror(errno)); goto fail; } /* Now make this the active template for this process. */ if (ct_tmpl_activate(tmpl_fd) != 0) { error("%s: Error activating process contract " "template: %s", __func__, strerror(errno)); goto fail; } return; fail: if (tmpl_fd != -1) { close(tmpl_fd); tmpl_fd = -1; } }
static int init_template(void) { int fd = 0; int err = 0; fd = open(CTFS_ROOT "/process/template", O_RDWR); if (fd == -1) return (-1); err |= ct_tmpl_set_critical(fd, 0); err |= ct_tmpl_set_informative(fd, 0); err |= ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR); err |= ct_pr_tmpl_set_param(fd, CT_PR_PGRPONLY | CT_PR_REGENT); if (err || ct_tmpl_activate(fd)) { (void) close(fd); return (-1); } return (fd); }
/** @todo the error reporting of the Solaris process contract code could be * a lot better, but essentially it is not meant to run into errors after * the debugging phase. */ static int rtSolarisContractPreFork(void) { int templateFd = open64(CTFS_ROOT "/process/template", O_RDWR); if (templateFd < 0) return -1; /* Set template parameters and event sets. */ if (ct_pr_tmpl_set_param(templateFd, CT_PR_PGRPONLY)) { close(templateFd); return -1; } if (ct_pr_tmpl_set_fatal(templateFd, CT_PR_EV_HWERR)) { close(templateFd); return -1; } if (ct_tmpl_set_critical(templateFd, 0)) { close(templateFd); return -1; } if (ct_tmpl_set_informative(templateFd, CT_PR_EV_HWERR)) { close(templateFd); return -1; } /* Make this the active template for the process. */ if (ct_tmpl_activate(templateFd)) { close(templateFd); return -1; } return templateFd; }
static int init_template(int flag) { int fd; if ((fd = open64(CTFS_ROOT "/process/template", O_RDWR)) == -1) { fatal(ERR_CONTRACT, "open %s/process/template failed: %s\n", CTFS_ROOT, strerror(errno)); } if (ct_tmpl_set_critical(fd, 0) != 0) { fatal(ERR_CONTRACT, "ct_tmpl_set_critical failed: %s\n", strerror(errno)); } if (ct_tmpl_set_informative(fd, 0) != 0) { fatal(ERR_CONTRACT, "ct_tmpl_set_informative failed: %s\n", strerror(errno)); } if (ct_pr_tmpl_set_fatal(fd, CT_PR_EV_HWERR) != 0) { fatal(ERR_CONTRACT, "ct_pr_tmpl_set_fatal failed: %s\n", strerror(errno)); } if (ct_pr_tmpl_set_param(fd, flag) != 0) { fatal(ERR_CONTRACT, "ct_pr_tmpl_set_param failed: %s\n", strerror(errno)); } /* requires PRIV_CONTRACT_IDENTITY so ignore error if it fails */ (void) ct_pr_tmpl_set_svc_fmri(fd, "svc:/dockerinit/child:default"); if (ct_tmpl_activate(fd) != 0) { fatal(ERR_CONTRACT, "ct_tmpl_activate failed: %s\n", strerror(errno)); } return (fd); }
/* * int method_ready_contract(restarter_inst_t *, int, method_restart_t, int) * * Activate a contract template for the type method of inst. type, * restart_on, and cte_mask dictate the critical events term of the contract. * Returns * 0 - success * ECANCELED - inst has been deleted from the repository */ static int method_ready_contract(restarter_inst_t *inst, int type, method_restart_t restart_on, uint_t cte_mask) { int tmpl, err, istrans, iswait, ret; uint_t cevents, fevents; /* * Correctly supporting wait-style services is tricky without * rearchitecting startd to cope with multiple event sources * simultaneously trying to stop an instance. Until a better * solution is implemented, we avoid this problem for * wait-style services by making contract events fatal and * letting the wait code alone handle stopping the service. */ iswait = instance_is_wait_style(inst); istrans = method_is_transient(inst, type); tmpl = open64(CTFS_ROOT "/process/template", O_RDWR); if (tmpl == -1) uu_die("Could not create contract template"); /* * We assume non-login processes are unlikely to create * multiple process groups, and set CT_PR_PGRPONLY for all * wait-style services' contracts. */ err = ct_pr_tmpl_set_param(tmpl, CT_PR_INHERIT | CT_PR_REGENT | (iswait ? CT_PR_PGRPONLY : 0)); assert(err == 0); if (istrans) { cevents = 0; fevents = 0; } else { assert(restart_on >= 0); assert(restart_on <= METHOD_RESTART_ANY_FAULT); cevents = method_events[restart_on] & ~cte_mask; fevents = iswait ? (method_events[restart_on] & ~cte_mask & CT_PR_ALLFATAL) : 0; } err = ct_tmpl_set_critical(tmpl, cevents); assert(err == 0); err = ct_tmpl_set_informative(tmpl, 0); assert(err == 0); err = ct_pr_tmpl_set_fatal(tmpl, fevents); assert(err == 0); err = ct_tmpl_set_cookie(tmpl, istrans ? METHOD_OTHER_COOKIE : METHOD_START_COOKIE); assert(err == 0); if (type == METHOD_START && inst->ri_i.i_primary_ctid != 0) { ret = ct_pr_tmpl_set_transfer(tmpl, inst->ri_i.i_primary_ctid); switch (ret) { case 0: break; case ENOTEMPTY: /* No contracts for you! */ method_remove_contract(inst, B_TRUE, B_TRUE); if (inst->ri_mi_deleted) { ret = ECANCELED; goto out; } break; case EINVAL: case ESRCH: case EACCES: default: bad_error("ct_pr_tmpl_set_transfer", ret); } } err = ct_tmpl_activate(tmpl); assert(err == 0); ret = 0; out: err = close(tmpl); assert(err == 0); return (ret); }
/* * Execute an operation on filename relative to zoneid's zone root. If the * file is in the global zone, then the zfcb() callback will simply be called * directly. If the file is in a non-global zone, then zfcb() will be called * both from the global zone's context, and from the non-global zone's context * (from a fork()'ed child that has entered the non-global zone). This is * done to allow the callback to communicate with itself if needed (e.g. to * pass back the file descriptor of an opened file). */ static int dlmgmt_zfop(const char *filename, zoneid_t zoneid, zfcb_t *zfcb, zfoparg_t *zfoparg) { int ctfd; int err; pid_t childpid; siginfo_t info; zfarg_t zfarg; ctid_t ct; if (zoneid != GLOBAL_ZONEID) { /* * We need to access a file that isn't in the global zone. * Accessing non-global zone files from the global zone is * unsafe (due to symlink attacks), we'll need to fork a child * that enters the zone in question and executes the callback * that will operate on the file. * * Before we proceed with this zone tango, we need to create a * new process contract for the child, as required by * zone_enter(). */ errno = 0; ctfd = open64("/system/contract/process/template", O_RDWR); if (ctfd == -1) return (errno); if ((err = ct_tmpl_set_critical(ctfd, 0)) != 0 || (err = ct_tmpl_set_informative(ctfd, 0)) != 0 || (err = ct_pr_tmpl_set_fatal(ctfd, CT_PR_EV_HWERR)) != 0 || (err = ct_pr_tmpl_set_param(ctfd, CT_PR_PGRPONLY)) != 0 || (err = ct_tmpl_activate(ctfd)) != 0) { (void) close(ctfd); return (err); } childpid = fork(); switch (childpid) { case -1: (void) ct_tmpl_clear(ctfd); (void) close(ctfd); return (err); case 0: (void) ct_tmpl_clear(ctfd); (void) close(ctfd); /* * Elevate our privileges as zone_enter() requires all * privileges. */ if ((err = dlmgmt_elevate_privileges()) != 0) _exit(err); if (zone_enter(zoneid) == -1) _exit(errno); if ((err = dlmgmt_drop_privileges()) != 0) _exit(err); break; default: if (contract_latest(&ct) == -1) ct = -1; (void) ct_tmpl_clear(ctfd); (void) close(ctfd); if (waitid(P_PID, childpid, &info, WEXITED) == -1) { (void) contract_abandon_id(ct); return (errno); } (void) contract_abandon_id(ct); if (info.si_status != 0) return (info.si_status); } } zfarg.zfarg_inglobalzone = (zoneid == GLOBAL_ZONEID || childpid != 0); zfarg.zfarg_finglobalzone = (zoneid == GLOBAL_ZONEID); zfarg.zfarg_filename = filename; zfarg.zfarg_oparg = zfoparg; err = zfcb(&zfarg); if (!zfarg.zfarg_inglobalzone) _exit(err); return (err); }