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 | |
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
-rw-r--r-- | sys/compat/linux/linux_misc.c | 2 | ||||
-rw-r--r-- | sys/compat/svr4/svr4_stat.c | 1 | ||||
-rw-r--r-- | sys/dev/syscons/daemon/daemon_saver.c | 2 | ||||
-rw-r--r-- | sys/fs/cd9660/cd9660_rrip.c | 2 | ||||
-rw-r--r-- | sys/geom/vinum/geom_vinum_drive.c | 2 | ||||
-rw-r--r-- | sys/i386/ibcs2/ibcs2_socksys.c | 8 | ||||
-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 | ||||
-rw-r--r-- | sys/netinet6/icmp6.c | 6 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 5 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 5 | ||||
-rw-r--r-- | sys/nfsclient/bootp_subr.c | 2 | ||||
-rw-r--r-- | sys/nfsclient/nfs_vfsops.c | 2 | ||||
-rw-r--r-- | sys/nlm/nlm_advlock.c | 4 | ||||
-rw-r--r-- | sys/rpc/authunix_prot.c | 4 | ||||
-rw-r--r-- | sys/sys/kernel.h | 1 |
17 files changed, 106 insertions, 25 deletions
diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 9989948..e9fdccc 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -761,7 +761,9 @@ linux_newuname(struct thread *td, struct linux_newuname_args *args) #else /* something other than i386 or amd64 - assume we and Linux agree */ strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME); #endif /* __i386__ */ + mtx_lock(&hostname_mtx); strlcpy(utsname.domainname, domainname, LINUX_MAX_UTSNAME); + mtx_unlock(&hostname_mtx); return (copyout(&utsname, args->buf, sizeof(utsname))); } diff --git a/sys/compat/svr4/svr4_stat.c b/sys/compat/svr4/svr4_stat.c index 915175a..7b6f200 100644 --- a/sys/compat/svr4/svr4_stat.c +++ b/sys/compat/svr4/svr4_stat.c @@ -454,6 +454,7 @@ svr4_sys_systeminfo(td, uap) break; case SVR4_SI_SRPC_DOMAIN: + /* XXXRW: locking? */ str = domainname; break; diff --git a/sys/dev/syscons/daemon/daemon_saver.c b/sys/dev/syscons/daemon/daemon_saver.c index b15e04c..2afc4c0 100644 --- a/sys/dev/syscons/daemon/daemon_saver.c +++ b/sys/dev/syscons/daemon/daemon_saver.c @@ -350,6 +350,8 @@ daemon_saver(video_adapter_t *adp, int blank) static int daemon_init(video_adapter_t *adp) { + + /* XXXRW: Locking -- these can change! */ messagelen = strlen(hostname) + 3 + strlen(ostype) + 1 + strlen(osrelease); message = malloc(messagelen + 1, M_DEVBUF, M_WAITOK); diff --git a/sys/fs/cd9660/cd9660_rrip.c b/sys/fs/cd9660/cd9660_rrip.c index c3c8027..fd28218 100644 --- a/sys/fs/cd9660/cd9660_rrip.c +++ b/sys/fs/cd9660/cd9660_rrip.c @@ -170,6 +170,7 @@ cd9660_rrip_slink(p,ana) break; case ISO_SUSP_CFLAG_HOST: + /* XXXRW: locking. */ /* Inserting hostname i.e. "kurt.tools.de" */ inbuf = hostname; wlen = strlen(hostname); @@ -242,6 +243,7 @@ cd9660_rrip_altname(p,ana) break; case ISO_SUSP_CFLAG_HOST: + /* XXXRW: locking. */ /* Inserting hostname i.e. "kurt.tools.de" */ inbuf = hostname; wlen = strlen(hostname); diff --git a/sys/geom/vinum/geom_vinum_drive.c b/sys/geom/vinum/geom_vinum_drive.c index 237d55e..a72937c 100644 --- a/sys/geom/vinum/geom_vinum_drive.c +++ b/sys/geom/vinum/geom_vinum_drive.c @@ -62,7 +62,9 @@ gv_config_new_drive(struct gv_drive *d) vhdr->magic = GV_MAGIC; vhdr->config_length = GV_CFG_LEN; + mtx_lock(&hostname_mtx); bcopy(hostname, vhdr->label.sysname, GV_HOSTNAME_LEN); + mtx_unlock(&hostname_mtx); strncpy(vhdr->label.name, d->name, GV_MAXDRIVENAME); microtime(&vhdr->label.date_of_birth); diff --git a/sys/i386/ibcs2/ibcs2_socksys.c b/sys/i386/ibcs2/ibcs2_socksys.c index f4939cf..62d300f 100644 --- a/sys/i386/ibcs2/ibcs2_socksys.c +++ b/sys/i386/ibcs2/ibcs2_socksys.c @@ -31,6 +31,8 @@ __FBSDID("$FreeBSD$"); #include <sys/sysproto.h> #include <sys/jail.h> #include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/sysctl.h> #include <i386/ibcs2/ibcs2_socksys.h> @@ -175,11 +177,15 @@ ibcs2_setipdomainname(td, uap) int error, sctl[2], hlen; /* W/out a hostname a domain-name is nonsense */ - if ( strlen(hostname) == 0 ) + mtx_lock(&hostname_mtx); + if ( strlen(hostname) == 0 ) { + mtx_unlock(&hostname_mtx); return EINVAL; + } /* Get the host's unqualified name (strip off the domain) */ snprintf(hname, sizeof(hname), "%s", hostname); + mtx_unlock(&hostname_mtx); ptr = index(hname, '.'); if ( ptr != NULL ) { ptr++; 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); } diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index d3c8315..e926c49 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -696,6 +696,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) n->m_pkthdr.rcvif = NULL; n->m_len = 0; maxhlen = M_TRAILINGSPACE(n) - maxlen; + mtx_lock(&hostname_mtx); if (maxhlen > hostnamelen) maxhlen = hostnamelen; /* @@ -708,6 +709,7 @@ icmp6_input(struct mbuf **mp, int *offp, int proto) p = (u_char *)(nicmp6 + 1); bzero(p, 4); bcopy(hostname, p + 4, maxhlen); /* meaningless TTL */ + mtx_unlock(&hostname_mtx); noff = sizeof(struct ip6_hdr); n->m_pkthdr.len = n->m_len = sizeof(struct ip6_hdr) + sizeof(struct icmp6_hdr) + 4 + maxhlen; @@ -1296,7 +1298,9 @@ ni6_input(struct mbuf *m, int off) * wildcard match, if gethostname(3) side has * truncated hostname. */ + mtx_lock(&hostname_mtx); n = ni6_nametodns(hostname, hostnamelen, 0); + mtx_unlock(&hostname_mtx); if (!n || n->m_next || n->m_len == 0) goto bad; IP6_EXTHDR_GET(subj, char *, m, @@ -1420,7 +1424,9 @@ ni6_input(struct mbuf *m, int off) /* * XXX do we really have FQDN in variable "hostname"? */ + mtx_lock(&hostname_mtx); n->m_next = ni6_nametodns(hostname, hostnamelen, oldfqdn); + mtx_unlock(&hostname_mtx); if (n->m_next == NULL) goto bad; /* XXX we assume that n->m_next is not a chain */ diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index c24ca20..bc9dcc9 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -1159,8 +1159,10 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, delay = arc4random() % (MAX_RTR_SOLICITATION_DELAY * hz); } + mtx_lock(&hostname_mtx); if (in6_nigroup(ifp, hostname, hostnamelen, &mltaddr.sin6_addr) == 0) { + mtx_unlock(&hostname_mtx); imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay); /* XXX jinmei */ if (!imm) { @@ -1174,7 +1176,8 @@ in6_update_ifa(struct ifnet *ifp, struct in6_aliasreq *ifra, LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); } - } + } else + mtx_unlock(&hostname_mtx); #undef hostnamelen /* diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 29dca4f..8714377 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -105,8 +105,10 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) { MD5_CTX ctxt; u_int8_t digest[16]; - int hostnamelen = strlen(hostname); + int hostnamelen; + mtx_lock(&hostname_mtx); + hostnamelen = strlen(hostname); #if 0 /* we need at least several letters as seed for ifid */ if (hostnamelen < 3) @@ -117,6 +119,7 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6) bzero(&ctxt, sizeof(ctxt)); MD5Init(&ctxt); MD5Update(&ctxt, hostname, hostnamelen); + mtx_unlock(&hostname_mtx); MD5Final(digest, &ctxt); /* assumes sizeof(digest) > sizeof(ifid) */ diff --git a/sys/nfsclient/bootp_subr.c b/sys/nfsclient/bootp_subr.c index 77c7739..7f65fe2 100644 --- a/sys/nfsclient/bootp_subr.c +++ b/sys/nfsclient/bootp_subr.c @@ -1569,8 +1569,10 @@ bootpc_decode_reply(struct nfsv3_diskless *nd, struct bootpc_ifcontext *ifctx, printf("hostname %s (ignored) ", p); } else { strcpy(nd->my_hostnam, p); + mtx_lock(&hostname_mtx); strcpy(hostname, p); printf("hostname %s ", hostname); + mtx_unlock(&hostname_mtx); gctx->sethostname = ifctx; } } diff --git a/sys/nfsclient/nfs_vfsops.c b/sys/nfsclient/nfs_vfsops.c index 17536491..c21b48e 100644 --- a/sys/nfsclient/nfs_vfsops.c +++ b/sys/nfsclient/nfs_vfsops.c @@ -506,11 +506,13 @@ nfs_mountroot(struct mount *mp, struct thread *td) * set hostname here and then let the "/etc/rc.xxx" files * mount the right /var based upon its preset value. */ + mtx_lock(&hostname_mtx); bcopy(nd->my_hostnam, hostname, MAXHOSTNAMELEN); hostname[MAXHOSTNAMELEN - 1] = '\0'; for (i = 0; i < MAXHOSTNAMELEN; i++) if (hostname[i] == '\0') break; + mtx_unlock(&hostname_mtx); inittodr(ntohl(nd->root_time)); return (0); } diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c index fb8b5a7..5d1cc83 100644 --- a/sys/nlm/nlm_advlock.c +++ b/sys/nlm/nlm_advlock.c @@ -230,7 +230,9 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl, sa = nmp->nm_nam; memcpy(&ss, sa, sa->sa_len); sa = (struct sockaddr *) &ss; + mtx_lock(&hostname_mtx); strcpy(servername, nmp->nm_hostname); + mtx_unlock(&hostname_mtx); fhlen = np->n_fhsize; memcpy(&fh.fh_bytes, np->n_fhp, fhlen); timo.tv_sec = nmp->nm_timeo / NFS_HZ; @@ -1218,7 +1220,9 @@ nlm_init_lock(struct flock *fl, int flags, int svid, return (EOVERFLOW); } + mtx_lock(&hostname_mtx); snprintf(oh_space, 32, "%d@%s", svid, hostname); + mtx_unlock(&hostname_mtx); oh_len = strlen(oh_space); memset(lock, 0, sizeof(*lock)); diff --git a/sys/rpc/authunix_prot.c b/sys/rpc/authunix_prot.c index 141f594..b229fb3 100644 --- a/sys/rpc/authunix_prot.c +++ b/sys/rpc/authunix_prot.c @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> #include <sys/systm.h> #include <sys/ucred.h> @@ -67,6 +69,7 @@ xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) uint32_t ngroups, i; uint32_t junk; + mtx_lock(&hostname_mtx); if (xdrs->x_op == XDR_ENCODE) { /* * Restrict name length to 255 according to RFC 1057. @@ -92,6 +95,7 @@ xdr_authunix_parms(XDR *xdrs, uint32_t *time, struct xucred *cred) } else { xdr_setpos(xdrs, xdr_getpos(xdrs) + RNDUP(namelen)); } + mtx_unlock(&hostname_mtx); if (!xdr_uint32_t(xdrs, &cred->cr_uid)) return (FALSE); diff --git a/sys/sys/kernel.h b/sys/sys/kernel.h index de57a6f..951d6bc 100644 --- a/sys/sys/kernel.h +++ b/sys/sys/kernel.h @@ -55,6 +55,7 @@ /* Global variables for the kernel. */ /* 1.1 */ +extern struct mtx hostname_mtx; extern unsigned long hostid; extern char hostuuid[64]; extern char hostname[MAXHOSTNAMELEN]; |