diff options
author | rwatson <rwatson@FreeBSD.org> | 2008-07-05 13:10:10 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2008-07-05 13:10:10 +0000 |
commit | 051819b84758e212ecd632e9bd6f47e70f37aa3a (patch) | |
tree | fcde383ade7af0060da3dd095039791d9e423bee /sys/kern | |
parent | b754e07b66100e4e4d6ac8caa8f6302730552936 (diff) | |
download | FreeBSD-src-051819b84758e212ecd632e9bd6f47e70f37aa3a.zip FreeBSD-src-051819b84758e212ecd632e9bd6f47e70f37aa3a.tar.gz |
Introduce a new lock, hostname_mtx, and use it to synchronize access
to global hostname and domainname variables. Where necessary, copy
to or from a stack-local buffer before performing copyin() or
copyout(). A few uses, such as in cd9660 and daemon_saver, remain
under-synchronized and will require further updates.
Correct a bug in which a failed copyin() of domainname would leave
domainname potentially corrupted.
MFC after: 3 weeks
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_jail.c | 5 | ||||
-rw-r--r-- | sys/kern/kern_mib.c | 48 | ||||
-rw-r--r-- | sys/kern/kern_xxx.c | 32 |
3 files changed, 63 insertions, 22 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index fe34616..869551f 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -475,8 +475,11 @@ getcredhostname(struct ucred *cred, char *buf, size_t size) mtx_lock(&cred->cr_prison->pr_mtx); strlcpy(buf, cred->cr_prison->pr_host, size); mtx_unlock(&cred->cr_prison->pr_mtx); - } else + } else { + mtx_lock(&hostname_mtx); strlcpy(buf, hostname, size); + mtx_unlock(&hostname_mtx); + } } /* diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index b8ce527..e178ce6 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -208,6 +208,13 @@ SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, char hostname[MAXHOSTNAMELEN]; +/* + * 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) { @@ -240,9 +247,18 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS) bcopy(tmphostname, pr->pr_host, MAXHOSTNAMELEN); mtx_unlock(&pr->pr_mtx); } - } else - error = sysctl_handle_string(oidp, - hostname, sizeof hostname, req); + } else { + mtx_lock(&hostname_mtx); + bcopy(hostname, tmphostname, MAXHOSTNAMELEN); + mtx_unlock(&hostname_mtx); + error = sysctl_handle_string(oidp, tmphostname, + sizeof tmphostname, req); + if (req->newptr != NULL && error == 0) { + mtx_lock(&hostname_mtx); + bcopy(tmphostname, hostname, MAXHOSTNAMELEN); + mtx_unlock(&hostname_mtx); + } + } return (error); } @@ -328,9 +344,29 @@ SYSCTL_PROC(_kern, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RW, 0, 0, sysctl_kern_config, "", "Kernel configuration file"); #endif -char domainname[MAXHOSTNAMELEN]; -SYSCTL_STRING(_kern, KERN_NISDOMAINNAME, domainname, CTLFLAG_RW, - &domainname, sizeof(domainname), "Name of the current YP/NIS domain"); +char domainname[MAXHOSTNAMELEN]; /* Protected by hostname_mtx. */ + +static int +sysctl_domainname(SYSCTL_HANDLER_ARGS) +{ + char tmpdomainname[MAXHOSTNAMELEN]; + int error; + + mtx_lock(&hostname_mtx); + bcopy(domainname, tmpdomainname, MAXHOSTNAMELEN); + mtx_unlock(&hostname_mtx); + error = sysctl_handle_string(oidp, tmpdomainname, + sizeof tmpdomainname, req); + if (req->newptr != NULL && error == 0) { + mtx_lock(&hostname_mtx); + bcopy(tmpdomainname, domainname, MAXHOSTNAMELEN); + mtx_unlock(&hostname_mtx); + } + 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"); diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c index ffb0729..0a4f42d 100644 --- a/sys/kern/kern_xxx.c +++ b/sys/kern/kern_xxx.c @@ -245,16 +245,17 @@ getdomainname(td, uap) struct thread *td; struct getdomainname_args *uap; { + char tmpdomainname[MAXHOSTNAMELEN]; int domainnamelen; - int error; - mtx_lock(&Giant); - domainnamelen = strlen(domainname) + 1; + mtx_lock(&hostname_mtx); + bcopy(domainname, tmpdomainname, sizeof(tmpdomainname)); + mtx_unlock(&hostname_mtx); + + domainnamelen = strlen(tmpdomainname) + 1; if ((u_int)uap->len > domainnamelen) uap->len = domainnamelen; - error = copyout(domainname, uap->domainname, uap->len); - mtx_unlock(&Giant); - return (error); + return (copyout(tmpdomainname, uap->domainname, uap->len)); } #ifndef _SYS_SYSPROTO_H_ @@ -269,20 +270,21 @@ setdomainname(td, uap) struct thread *td; struct setdomainname_args *uap; { + char tmpdomainname[MAXHOSTNAMELEN]; int error, domainnamelen; error = priv_check(td, PRIV_SETDOMAINNAME); if (error) return (error); - mtx_lock(&Giant); - if ((u_int)uap->len > sizeof (domainname) - 1) { - error = EINVAL; - goto done2; - } + if ((u_int)uap->len > sizeof(tmpdomainname) - 1) + return (EINVAL); domainnamelen = uap->len; - error = copyin(uap->domainname, domainname, uap->len); - domainname[domainnamelen] = 0; -done2: - mtx_unlock(&Giant); + error = copyin(uap->domainname, tmpdomainname, uap->len); + if (error == 0) { + tmpdomainname[domainnamelen] = 0; + mtx_lock(&hostname_mtx); + bcopy(tmpdomainname, domainname, sizeof(domainname)); + mtx_unlock(&hostname_mtx); + } return (error); } |