o Make the credential used by socreate() an explicit argument to

socreate(), rather than getting it implicitly from the thread
  argument.

o Make NFS cache the credential provided at mount-time, and use
  the cached credential (nfsmount->nm_cred) when making calls to
  socreate() on initially connecting, or reconnecting the socket.

This fixes bugs involving NFS over TCP and ipfw uid/gid rules, as well
as bugs involving NFS and mandatory access control implementations.

Reviewed by:	freebsd-arch
This commit is contained in:
Robert Watson 2001-12-31 17:45:16 +00:00
parent 536550c3f2
commit 9c4d63da6d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=88739
13 changed files with 42 additions and 21 deletions

View File

@ -264,7 +264,8 @@ streamsopen(dev_t dev, int oflags, int devtype, struct thread *td)
if ((error = falloc(td, &fp, &fd)) != 0)
return error;
if ((error = socreate(family, &so, type, protocol, td)) != 0) {
if ((error = socreate(family, &so, type, protocol,
td->td_proc->p_ucred, td)) != 0) {
p->p_fd->fd_ofiles[fd] = 0;
ffree(fp);
return error;

View File

@ -174,14 +174,16 @@ fifo_open(ap)
if ((fip = vp->v_fifoinfo) == NULL) {
MALLOC(fip, struct fifoinfo *, sizeof(*fip), M_VNODE, M_WAITOK);
vp->v_fifoinfo = fip;
error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0, ap->a_td);
error = socreate(AF_LOCAL, &rso, SOCK_STREAM, 0,
ap->a_td->td_proc->p_ucred, ap->a_td);
if (error) {
free(fip, M_VNODE);
vp->v_fifoinfo = NULL;
return (error);
}
fip->fi_readsock = rso;
error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0, ap->a_td);
error = socreate(AF_LOCAL, &wso, SOCK_STREAM, 0,
ap->a_td->td_proc->p_ucred, ap->a_td);
if (error) {
(void)soclose(rso);
free(fip, M_VNODE);

View File

@ -246,7 +246,8 @@ portal_open(ap)
/*
* Create a new socket.
*/
error = socreate(AF_UNIX, &so, SOCK_STREAM, 0, ap->a_td);
error = socreate(AF_UNIX, &so, SOCK_STREAM, 0,
ap->a_td->td_proc->p_ucred, ap->a_td);
if (error)
goto bad;

View File

@ -137,11 +137,12 @@ soalloc(waitok)
* closed with soclose().
*/
int
socreate(dom, aso, type, proto, td)
socreate(dom, aso, type, proto, cred, td)
int dom;
struct socket **aso;
register int type;
int proto;
struct ucred *cred;
struct thread *td;
{
register struct protosw *prp;
@ -172,7 +173,7 @@ socreate(dom, aso, type, proto, td)
TAILQ_INIT(&so->so_incomp);
TAILQ_INIT(&so->so_comp);
so->so_type = type;
so->so_cred = crhold(td->td_proc->p_ucred);
so->so_cred = crhold(cred);
so->so_proto = prp;
soref(so);
error = (*prp->pr_usrreqs->pru_attach)(so, proto, td);

View File

@ -132,7 +132,8 @@ socket(td, uap)
if (error)
goto done2;
fhold(fp);
error = socreate(uap->domain, &so, uap->type, uap->protocol, td);
error = socreate(uap->domain, &so, uap->type, uap->protocol,
td->td_proc->p_ucred, td);
if (error) {
if (fdp->fd_ofiles[fd] == fp) {
fdp->fd_ofiles[fd] = NULL;
@ -478,10 +479,12 @@ socketpair(td, uap)
int fd, error, sv[2];
mtx_lock(&Giant);
error = socreate(uap->domain, &so1, uap->type, uap->protocol, td);
error = socreate(uap->domain, &so1, uap->type, uap->protocol,
td->td_proc->p_ucred, td);
if (error)
goto done2;
error = socreate(uap->domain, &so2, uap->type, uap->protocol, td);
error = socreate(uap->domain, &so2, uap->type, uap->protocol,
td->td_proc->p_ucred, td);
if (error)
goto free1;
error = falloc(td, &fp1, &fd);

View File

@ -586,7 +586,8 @@ ng_ksocket_newhook(node_p node, hook_p hook, const char *name0)
return (EINVAL);
/* Create the socket */
error = socreate(family, &priv->so, type, protocol, td);
error = socreate(family, &priv->so, type, protocol,
td->td_proc->p_ucred, td);
if (error != 0)
return (error);

View File

@ -226,7 +226,8 @@ nb_connect_in(struct nbpcb *nbp, struct sockaddr_in *to, struct thread *td)
struct socket *so;
int error, s;
error = socreate(AF_INET, &so, SOCK_STREAM, IPPROTO_TCP, td);
error = socreate(AF_INET, &so, SOCK_STREAM, IPPROTO_TCP,
td->td_proc->p_ucred, td);
if (error)
return error;
nbp->nbp_tso = so;

View File

@ -586,7 +586,8 @@ bootpc_call(struct bootpc_globalcontext *gctx, struct thread *td)
/*
* Create socket and set its recieve timeout.
*/
error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td);
error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td->td_proc->p_ucred,
td);
if (error != 0)
goto out;
@ -971,7 +972,8 @@ bootpc_fakeup_interface(struct bootpc_ifcontext *ifctx,
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0, td);
error = socreate(AF_INET, &ifctx->so, SOCK_DGRAM, 0,
td->td_proc->p_ucred, td);
if (error != 0)
panic("nfs_boot: socreate, error=%d", error);

View File

@ -215,7 +215,8 @@ krpc_call(struct sockaddr_in *sa, u_int prog, u_int vers, u_int func,
/*
* Create socket and set its recieve timeout.
*/
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0, td)))
if ((error = socreate(AF_INET, &so, SOCK_DGRAM, 0,
td->td_proc->p_ucred, td)))
goto out;
tv.tv_sec = 1;

View File

@ -163,7 +163,7 @@ nfs_connect(struct nfsmount *nmp, struct nfsreq *rep)
nmp->nm_so = (struct socket *)0;
saddr = nmp->nm_nam;
error = socreate(saddr->sa_family, &nmp->nm_so, nmp->nm_sotype,
nmp->nm_soproto, td);
nmp->nm_soproto, nmp->nm_cred, td);
if (error)
goto bad;
so = nmp->nm_so;

View File

@ -92,7 +92,8 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, "");
static int nfs_iosize(struct nfsmount *nmp);
static void nfs_decode_args(struct nfsmount *nmp, struct nfs_args *argp);
static int mountnfs(struct nfs_args *, struct mount *,
struct sockaddr *, char *, char *, struct vnode **);
struct sockaddr *, char *, char *, struct vnode **,
struct ucred *cred);
static int nfs_mount(struct mount *mp, char *path, caddr_t data,
struct nameidata *ndp, struct thread *td);
static int nfs_unmount(struct mount *mp, int mntflags, struct thread *td);
@ -377,6 +378,7 @@ int
nfs_mountroot(struct mount *mp)
{
struct mount *swap_mp;
struct nfsmount *nmp = VFSTONFS(mp);
struct nfsv3_diskless *nd = &nfsv3_diskless;
struct socket *so;
struct vnode *vp;
@ -419,7 +421,8 @@ nfs_mountroot(struct mount *mp)
* Do enough of ifconfig(8) so that the critical net interface can
* talk to the server.
*/
error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0, td);
error = socreate(nd->myif.ifra_addr.sa_family, &so, SOCK_DGRAM, 0,
nmp->nm_cred, td);
if (error)
panic("nfs_mountroot: socreate(%04x): %d",
nd->myif.ifra_addr.sa_family, error);
@ -557,7 +560,8 @@ nfs_mountdiskless(char *path, char *which, int mountflag,
mp->mnt_kern_flag = 0;
mp->mnt_flag = mountflag;
nam = dup_sockaddr((struct sockaddr *)sin, 1);
if ((error = mountnfs(args, mp, nam, which, path, vpp)) != 0) {
if ((error = mountnfs(args, mp, nam, which, path, vpp, td->td_ucred))
!= 0) {
printf("nfs_mountroot: mount %s on %s: %d", path, which, error);
mp->mnt_vfc->vfc_refcount--;
vfs_unbusy(mp, td);
@ -785,7 +789,7 @@ nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
if (error)
return (error);
args.fh = nfh;
error = mountnfs(&args, mp, nam, path, hst, &vp);
error = mountnfs(&args, mp, nam, path, hst, &vp, td->td_ucred);
return (error);
}
@ -794,7 +798,7 @@ nfs_mount(struct mount *mp, char *path, caddr_t data, struct nameidata *ndp,
*/
static int
mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
char *pth, char *hst, struct vnode **vpp)
char *pth, char *hst, struct vnode **vpp, struct ucred *cred)
{
struct nfsmount *nmp;
struct nfsnode *np;
@ -814,6 +818,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_cred = crhold(cred);
/*
* V2 can only handle 32 bit filesizes. A 4GB-1 limit may be too
@ -891,6 +896,7 @@ mountnfs(struct nfs_args *argp, struct mount *mp, struct sockaddr *nam,
return (0);
bad:
nfs_disconnect(nmp);
crfree(nmp->nm_cred);
zfree(nfsmount_zone, nmp);
FREE(nam, M_SONAME);
return (error);
@ -925,6 +931,7 @@ nfs_unmount(struct mount *mp, int mntflags, struct thread *td)
nfs_disconnect(nmp);
FREE(nmp->nm_nam, M_SONAME);
crfree(nmp->nm_cred);
zfree(nfsmount_zone, nmp);
return (0);
}

View File

@ -53,6 +53,7 @@ struct nfsmount {
u_char nm_fh[NFSX_V3FHMAX]; /* File handle of root dir */
int nm_fhsize; /* Size of root file handle */
struct socket *nm_so; /* Rpc socket */
struct ucred *nm_cred; /* Cached mount-time credential */
int nm_sotype; /* Type of socket */
int nm_soproto; /* and protocol */
int nm_soflags; /* pr_flags for socket protocol */

View File

@ -383,7 +383,7 @@ int soclose __P((struct socket *so));
int soconnect __P((struct socket *so, struct sockaddr *nam, struct thread *td));
int soconnect2 __P((struct socket *so1, struct socket *so2));
int socreate __P((int dom, struct socket **aso, int type, int proto,
struct thread *td));
struct ucred *cred, struct thread *td));
int sodisconnect __P((struct socket *so));
void sofree __P((struct socket *so));
int sogetopt __P((struct socket *so, struct sockopt *sopt));