diff options
Diffstat (limited to 'sys/kern/kern_mib.c')
-rw-r--r-- | sys/kern/kern_mib.c | 156 |
1 files changed, 79 insertions, 77 deletions
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index 38116d5..823df6b 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/sx.h> #include <sys/unistd.h> -#include <sys/vimage.h> SYSCTL_NODE(, 0, sysctl, CTLFLAG_RW, 0, "Sysctl internal magic"); @@ -209,71 +208,69 @@ static char machine_arch[] = MACHINE_ARCH; SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, machine_arch, 0, "System architecture"); -#ifdef VIMAGE_GLOBALS -char hostname[MAXHOSTNAMELEN]; -#endif - -/* - * This mutex is used to protect the hostname and domainname variables, and - * perhaps in the future should also protect hostid, hostuid, and others. - */ -struct mtx hostname_mtx; -MTX_SYSINIT(hostname_mtx, &hostname_mtx, "hostname", MTX_DEF); - static int sysctl_hostname(SYSCTL_HANDLER_ARGS) { - INIT_VPROCG(TD_TO_VPROCG(req->td)); - struct prison *pr; - char tmphostname[MAXHOSTNAMELEN]; - int error; + struct prison *pr, *cpr; + size_t pr_offset; + char tmpname[MAXHOSTNAMELEN]; + int descend, error, len; + + /* + * This function can set: hostname domainname hostuuid. + * Keep that in mind when comments say "hostname". + */ + pr_offset = (size_t)arg1; + len = arg2; + KASSERT(len <= sizeof(tmpname), + ("length %d too long for %s", len, __func__)); pr = req->td->td_ucred->cr_prison; - if (pr != &prison0) { - if (!(pr->pr_allow & PR_ALLOW_SET_HOSTNAME) && req->newptr) - return (EPERM); + if (!(pr->pr_allow & PR_ALLOW_SET_HOSTNAME) && req->newptr) + return (EPERM); + /* + * Make a local copy of hostname to get/set so we don't have to hold + * the jail mutex during the sysctl copyin/copyout activities. + */ + mtx_lock(&pr->pr_mtx); + bcopy((char *)pr + pr_offset, tmpname, len); + mtx_unlock(&pr->pr_mtx); + + error = sysctl_handle_string(oidp, tmpname, len, req); + + if (req->newptr != NULL && error == 0) { /* - * Process is in jail, so make a local copy of jail - * hostname to get/set so we don't have to hold the jail - * mutex during the sysctl copyin/copyout activities. + * Copy the locally set hostname to all jails that share + * this host info. */ + sx_slock(&allprison_lock); + while (!(pr->pr_flags & PR_HOST)) + pr = pr->pr_parent; mtx_lock(&pr->pr_mtx); - bcopy(pr->pr_host, tmphostname, MAXHOSTNAMELEN); + bcopy(tmpname, (char *)pr + pr_offset, len); + FOREACH_PRISON_DESCENDANT_LOCKED(pr, cpr, descend) + if (cpr->pr_flags & PR_HOST) + descend = 0; + else + bcopy(tmpname, (char *)cpr + pr_offset, len); mtx_unlock(&pr->pr_mtx); - - error = sysctl_handle_string(oidp, tmphostname, - sizeof pr->pr_host, req); - - if (req->newptr != NULL && error == 0) { - /* - * Copy the locally set hostname to the jail, if - * appropriate. - */ - mtx_lock(&pr->pr_mtx); - bcopy(tmphostname, pr->pr_host, MAXHOSTNAMELEN); - mtx_unlock(&pr->pr_mtx); - } - } else { - mtx_lock(&hostname_mtx); - bcopy(V_hostname, tmphostname, MAXHOSTNAMELEN); - mtx_unlock(&hostname_mtx); - error = sysctl_handle_string(oidp, tmphostname, - sizeof tmphostname, req); - if (req->newptr != NULL && error == 0) { - mtx_lock(&prison0.pr_mtx); - mtx_lock(&hostname_mtx); - bcopy(tmphostname, prison0.pr_host, MAXHOSTNAMELEN); - bcopy(tmphostname, V_hostname, MAXHOSTNAMELEN); - mtx_unlock(&hostname_mtx); - mtx_unlock(&prison0.pr_mtx); - } + sx_sunlock(&allprison_lock); } return (error); } SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, - CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON|CTLFLAG_MPSAFE, - 0, 0, sysctl_hostname, "A", "Hostname"); + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + (void *)(offsetof(struct prison, pr_host)), MAXHOSTNAMELEN, + sysctl_hostname, "A", "Hostname"); +SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + (void *)(offsetof(struct prison, pr_domain)), MAXHOSTNAMELEN, + sysctl_hostname, "A", "Name of the current YP/NIS domain"); +SYSCTL_PROC(_kern, KERN_HOSTUUID, hostuuid, + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + (void *)(offsetof(struct prison, pr_uuid)), HOSTUUIDLEN, + sysctl_hostname, "A", "Host UUID"); static int regression_securelevel_nonmonotonic = 0; @@ -341,38 +338,43 @@ SYSCTL_PROC(_kern, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RW, 0, 0, sysctl_kern_config, "", "Kernel configuration file"); #endif -#ifdef VIMAGE_GLOBALS -char domainname[MAXHOSTNAMELEN]; /* Protected by hostname_mtx. */ -#endif - static int -sysctl_domainname(SYSCTL_HANDLER_ARGS) +sysctl_hostid(SYSCTL_HANDLER_ARGS) { - INIT_VPROCG(TD_TO_VPROCG(req->td)); - char tmpdomainname[MAXHOSTNAMELEN]; - int error; - - mtx_lock(&hostname_mtx); - bcopy(V_domainname, tmpdomainname, MAXHOSTNAMELEN); - mtx_unlock(&hostname_mtx); - error = sysctl_handle_string(oidp, tmpdomainname, - sizeof tmpdomainname, req); + struct prison *pr, *cpr; + u_long tmpid; + int descend, error; + + /* + * Like sysctl_hostname, except it operates on a u_long + * instead of a string, and is used only for hostid. + */ + pr = req->td->td_ucred->cr_prison; + if (!(pr->pr_allow & PR_ALLOW_SET_HOSTNAME) && req->newptr) + return (EPERM); + tmpid = pr->pr_hostid; + error = sysctl_handle_long(oidp, &tmpid, 0, req); + if (req->newptr != NULL && error == 0) { - mtx_lock(&hostname_mtx); - bcopy(tmpdomainname, V_domainname, MAXHOSTNAMELEN); - mtx_unlock(&hostname_mtx); + sx_slock(&allprison_lock); + while (!(pr->pr_flags & PR_HOST)) + pr = pr->pr_parent; + mtx_lock(&pr->pr_mtx); + pr->pr_hostid = tmpid; + FOREACH_PRISON_DESCENDANT_LOCKED(pr, cpr, descend) + if (cpr->pr_flags & PR_HOST) + descend = 0; + else + cpr->pr_hostid = tmpid; + mtx_unlock(&pr->pr_mtx); + sx_sunlock(&allprison_lock); } return (error); } -SYSCTL_PROC(_kern, KERN_NISDOMAINNAME, domainname, CTLTYPE_STRING|CTLFLAG_RW, - 0, 0, sysctl_domainname, "A", "Name of the current YP/NIS domain"); - -u_long hostid; -SYSCTL_ULONG(_kern, KERN_HOSTID, hostid, CTLFLAG_RW, &hostid, 0, "Host ID"); -char hostuuid[64] = "00000000-0000-0000-0000-000000000000"; -SYSCTL_STRING(_kern, KERN_HOSTUUID, hostuuid, CTLFLAG_RW, hostuuid, - sizeof(hostuuid), "Host UUID"); +SYSCTL_PROC(_kern, KERN_HOSTID, hostid, + CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, + NULL, 0, sysctl_hostid, "LU", "Host ID"); SYSCTL_NODE(_kern, OID_AUTO, features, CTLFLAG_RD, 0, "Kernel Features"); |